mirror of
https://github.com/viq/NewsBlur.git
synced 2025-08-05 16:49:45 +00:00
A bit risky but this commit fixes read status issues with stories found in both blurblogs and feeds. Adds a new redis set of read stories, specific to users and blurblog subscriptions, that won't get cleared out when the story is removed from mongo.
This commit is contained in:
parent
9ac6c399cf
commit
5af6e3835a
2 changed files with 53 additions and 36 deletions
|
@ -653,7 +653,7 @@ class UserSubscription(models.Model):
|
||||||
class RUserStory:
|
class RUserStory:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mark_read(cls, user_id, story_feed_id, story_hash, r=None, r2=None):
|
def mark_read(cls, user_id, story_feed_id, story_hash, social_user_ids=None, r=None, r2=None):
|
||||||
if not r:
|
if not r:
|
||||||
r = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
|
r = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
|
||||||
if not r2:
|
if not r2:
|
||||||
|
@ -663,34 +663,43 @@ class RUserStory:
|
||||||
|
|
||||||
if not story_hash: return
|
if not story_hash: return
|
||||||
|
|
||||||
now = int(time.time())
|
def redis_commands(key):
|
||||||
|
r.sadd(key, story_hash)
|
||||||
|
r2.sadd(key, story_hash)
|
||||||
|
r.expire(key, settings.DAYS_OF_UNREAD*24*60*60)
|
||||||
|
r2.expire(key, settings.DAYS_OF_UNREAD*24*60*60)
|
||||||
|
|
||||||
all_read_stories_key = 'RS:%s' % (user_id)
|
all_read_stories_key = 'RS:%s' % (user_id)
|
||||||
r.sadd(all_read_stories_key, story_hash)
|
redis_commands(all_read_stories_key)
|
||||||
r2.sadd(all_read_stories_key, story_hash)
|
|
||||||
r2.zadd('z' + all_read_stories_key, story_hash, now)
|
|
||||||
r.expire(all_read_stories_key, settings.DAYS_OF_UNREAD*24*60*60)
|
|
||||||
r2.expire(all_read_stories_key, settings.DAYS_OF_UNREAD*24*60*60)
|
|
||||||
r2.expire('z' + all_read_stories_key, settings.DAYS_OF_UNREAD*24*60*60)
|
|
||||||
|
|
||||||
read_story_key = 'RS:%s:%s' % (user_id, story_feed_id)
|
read_story_key = 'RS:%s:%s' % (user_id, story_feed_id)
|
||||||
r.sadd(read_story_key, story_hash)
|
redis_commands(read_story_key)
|
||||||
r2.sadd(read_story_key, story_hash)
|
|
||||||
r2.zadd('z' + read_story_key, story_hash, now)
|
if social_user_ids:
|
||||||
r.expire(read_story_key, settings.DAYS_OF_UNREAD*24*60*60)
|
for social_user_id in social_user_ids:
|
||||||
r2.expire(read_story_key, settings.DAYS_OF_UNREAD*24*60*60)
|
social_read_story_key = 'RS:%s:B:%s' % (user_id, social_user_id)
|
||||||
r2.expire('z' + read_story_key, settings.DAYS_OF_UNREAD*24*60*60)
|
redis_commands(social_read_story_key)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def mark_unread(user_id, story_feed_id, story_hash):
|
def mark_unread(user_id, story_feed_id, story_hash, social_user_ids=None):
|
||||||
r = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
|
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||||
r2 = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL2)
|
h = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
|
||||||
|
h2 = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL2)
|
||||||
r.srem('RS:%s' % user_id, story_hash)
|
|
||||||
r2.srem('RS:%s' % user_id, story_hash)
|
h.srem('RS:%s' % user_id, story_hash)
|
||||||
r2.zrem('zRS:%s' % user_id, story_hash)
|
h2.srem('RS:%s' % user_id, story_hash)
|
||||||
r.srem('RS:%s:%s' % (user_id, story_feed_id), story_hash)
|
h.srem('RS:%s:%s' % (user_id, story_feed_id), story_hash)
|
||||||
r2.srem('RS:%s:%s' % (user_id, story_feed_id), story_hash)
|
h2.srem('RS:%s:%s' % (user_id, story_feed_id), story_hash)
|
||||||
r2.zrem('zRS:%s:%s' % (user_id, story_feed_id), story_hash)
|
|
||||||
|
# Find other social feeds with this story to update their counts
|
||||||
|
friend_key = "F:%s:F" % (user_id)
|
||||||
|
share_key = "S:%s" % (story_hash)
|
||||||
|
friends_with_shares = [int(f) for f in r.sinter(share_key, friend_key)]
|
||||||
|
|
||||||
|
if friends_with_shares:
|
||||||
|
for social_user_id in friends_with_shares:
|
||||||
|
h.srem('RS:%s:B:%s' % (user_id, social_user_id), story_hash)
|
||||||
|
h2.srem('RS:%s:B:%s' % (user_id, social_user_id), story_hash)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_stories(user_id, feed_id, r=None):
|
def get_stories(user_id, feed_id, r=None):
|
||||||
|
@ -706,7 +715,6 @@ class RUserStory:
|
||||||
p = r.pipeline()
|
p = r.pipeline()
|
||||||
p2 = r2.pipeline()
|
p2 = r2.pipeline()
|
||||||
story_hashes = cls.get_stories(user_id, old_feed_id, r=r)
|
story_hashes = cls.get_stories(user_id, old_feed_id, r=r)
|
||||||
now = int(time.time())
|
|
||||||
|
|
||||||
for story_hash in story_hashes:
|
for story_hash in story_hashes:
|
||||||
_, hash_story = MStory.split_story_hash(story_hash)
|
_, hash_story = MStory.split_story_hash(story_hash)
|
||||||
|
@ -714,18 +722,14 @@ class RUserStory:
|
||||||
read_feed_key = "RS:%s:%s" % (user_id, new_feed_id)
|
read_feed_key = "RS:%s:%s" % (user_id, new_feed_id)
|
||||||
p.sadd(read_feed_key, new_story_hash)
|
p.sadd(read_feed_key, new_story_hash)
|
||||||
p2.sadd(read_feed_key, new_story_hash)
|
p2.sadd(read_feed_key, new_story_hash)
|
||||||
p2.zadd('z' + read_feed_key, new_story_hash, now)
|
|
||||||
p.expire(read_feed_key, settings.DAYS_OF_UNREAD*24*60*60)
|
p.expire(read_feed_key, settings.DAYS_OF_UNREAD*24*60*60)
|
||||||
p2.expire(read_feed_key, settings.DAYS_OF_UNREAD*24*60*60)
|
p2.expire(read_feed_key, settings.DAYS_OF_UNREAD*24*60*60)
|
||||||
p2.expire('z' + read_feed_key, settings.DAYS_OF_UNREAD*24*60*60)
|
|
||||||
|
|
||||||
read_user_key = "RS:%s" % (user_id)
|
read_user_key = "RS:%s" % (user_id)
|
||||||
p.sadd(read_user_key, new_story_hash)
|
p.sadd(read_user_key, new_story_hash)
|
||||||
p2.sadd(read_user_key, new_story_hash)
|
p2.sadd(read_user_key, new_story_hash)
|
||||||
p2.zadd('z' + read_user_key, new_story_hash, now)
|
|
||||||
p.expire(read_user_key, settings.DAYS_OF_UNREAD*24*60*60)
|
p.expire(read_user_key, settings.DAYS_OF_UNREAD*24*60*60)
|
||||||
p2.expire(read_user_key, settings.DAYS_OF_UNREAD*24*60*60)
|
p2.expire(read_user_key, settings.DAYS_OF_UNREAD*24*60*60)
|
||||||
p2.expire('z' + read_user_key, settings.DAYS_OF_UNREAD*24*60*60)
|
|
||||||
|
|
||||||
p.execute()
|
p.execute()
|
||||||
p2.execute()
|
p2.execute()
|
||||||
|
|
|
@ -857,9 +857,10 @@ class MSocialSubscription(mongo.Document):
|
||||||
r = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
|
r = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
|
||||||
ignore_user_stories = False
|
ignore_user_stories = False
|
||||||
|
|
||||||
stories_key = 'B:%s' % (self.subscription_user_id)
|
stories_key = 'B:%s' % (self.subscription_user_id)
|
||||||
read_stories_key = 'RS:%s' % (self.user_id)
|
read_stories_key = 'RS:%s' % (self.user_id)
|
||||||
unread_stories_key = 'UB:%s:%s' % (self.user_id, self.subscription_user_id)
|
read_social_stories_key = 'RS:%s:B:%s' % (self.user_id, self.subscription_user_id)
|
||||||
|
unread_stories_key = 'UB:%s:%s' % (self.user_id, self.subscription_user_id)
|
||||||
|
|
||||||
if not r.exists(stories_key):
|
if not r.exists(stories_key):
|
||||||
return []
|
return []
|
||||||
|
@ -868,6 +869,7 @@ class MSocialSubscription(mongo.Document):
|
||||||
unread_stories_key = stories_key
|
unread_stories_key = stories_key
|
||||||
else:
|
else:
|
||||||
r.sdiffstore(unread_stories_key, stories_key, read_stories_key)
|
r.sdiffstore(unread_stories_key, stories_key, read_stories_key)
|
||||||
|
r.sdiffstore(unread_stories_key, unread_stories_key, read_social_stories_key)
|
||||||
|
|
||||||
sorted_stories_key = 'zB:%s' % (self.subscription_user_id)
|
sorted_stories_key = 'zB:%s' % (self.subscription_user_id)
|
||||||
unread_ranked_stories_key = 'z%sUB:%s:%s' % ('h' if hashes_only else '',
|
unread_ranked_stories_key = 'z%sUB:%s:%s' % ('h' if hashes_only else '',
|
||||||
|
@ -970,14 +972,18 @@ class MSocialSubscription(mongo.Document):
|
||||||
logging.user(request, "~FYRead story in social subscription: %s" % (sub_username))
|
logging.user(request, "~FYRead story in social subscription: %s" % (sub_username))
|
||||||
|
|
||||||
for story_hash in set(story_hashes):
|
for story_hash in set(story_hashes):
|
||||||
|
if feed_id:
|
||||||
|
story_hash = MStory.ensure_story_hash(story_hash, story_feed_id=feed_id)
|
||||||
if not feed_id:
|
if not feed_id:
|
||||||
feed_id, _ = MStory.split_story_hash(story_hash)
|
feed_id, _ = MStory.split_story_hash(story_hash)
|
||||||
RUserStory.mark_read(self.user_id, feed_id, story_hash)
|
|
||||||
|
|
||||||
# Find other social feeds with this story to update their counts
|
# Find other social feeds with this story to update their counts
|
||||||
friend_key = "F:%s:F" % (self.user_id)
|
friend_key = "F:%s:F" % (self.user_id)
|
||||||
share_key = "S:%s" % (story_hash)
|
share_key = "S:%s" % (story_hash)
|
||||||
friends_with_shares = [int(f) for f in r.sinter(share_key, friend_key)]
|
friends_with_shares = [int(f) for f in r.sinter(share_key, friend_key)]
|
||||||
|
|
||||||
|
RUserStory.mark_read(self.user_id, feed_id, story_hash, social_user_ids=friends_with_shares)
|
||||||
|
|
||||||
if self.user_id in friends_with_shares:
|
if self.user_id in friends_with_shares:
|
||||||
friends_with_shares.remove(self.user_id)
|
friends_with_shares.remove(self.user_id)
|
||||||
if friends_with_shares:
|
if friends_with_shares:
|
||||||
|
@ -1003,7 +1009,8 @@ class MSocialSubscription(mongo.Document):
|
||||||
def mark_unsub_story_ids_as_read(cls, user_id, social_user_id, story_ids, feed_id=None,
|
def mark_unsub_story_ids_as_read(cls, user_id, social_user_id, story_ids, feed_id=None,
|
||||||
request=None):
|
request=None):
|
||||||
data = dict(code=0, payload=story_ids)
|
data = dict(code=0, payload=story_ids)
|
||||||
|
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||||
|
|
||||||
if not request:
|
if not request:
|
||||||
request = User.objects.get(pk=user_id)
|
request = User.objects.get(pk=user_id)
|
||||||
|
|
||||||
|
@ -1019,7 +1026,13 @@ class MSocialSubscription(mongo.Document):
|
||||||
except MSharedStory.DoesNotExist:
|
except MSharedStory.DoesNotExist:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
RUserStory.mark_read(user_id, story.story_feed_id, story.story_hash)
|
# Find other social feeds with this story to update their counts
|
||||||
|
friend_key = "F:%s:F" % (user_id)
|
||||||
|
share_key = "S:%s" % (story.story_hash)
|
||||||
|
friends_with_shares = [int(f) for f in r.sinter(share_key, friend_key)]
|
||||||
|
|
||||||
|
RUserStory.mark_read(user_id, story.story_feed_id, story.story_hash,
|
||||||
|
social_user_ids=friends_with_shares)
|
||||||
|
|
||||||
# Also count on original subscription
|
# Also count on original subscription
|
||||||
usersubs = UserSubscription.objects.filter(user=user_id, feed=story.story_feed_id)
|
usersubs = UserSubscription.objects.filter(user=user_id, feed=story.story_feed_id)
|
||||||
|
|
Loading…
Add table
Reference in a new issue