Merge and unmerge timelines on follow/unfollow, solves #21, #22

This commit is contained in:
Eugen Rochko 2016-09-10 18:36:48 +02:00
parent 35b6c4b36a
commit 0077fc26df
13 changed files with 133 additions and 52 deletions

View file

@ -3,6 +3,5 @@ class BaseService
include ActionView::Helpers::SanitizeHelper
include RoutingHelper
include ApplicationHelper
include AtomBuilderHelper
end

View file

@ -10,13 +10,13 @@ class FanOutOnWriteService < BaseService
private
def deliver_to_self(status)
push(:home, status.account, status)
FeedManager.instance.push(:home, status.account, status)
end
def deliver_to_followers(status)
status.account.followers.each do |follower|
next if !follower.local? || FeedManager.instance.filter_status?(status, follower)
push(:home, follower, status)
FeedManager.instance.push(:home, follower, status)
end
end
@ -24,42 +24,7 @@ class FanOutOnWriteService < BaseService
status.mentions.each do |mention|
mentioned_account = mention.account
next unless mentioned_account.local?
push(:mentions, mentioned_account, status)
FeedManager.instance.push(:mentions, mentioned_account, status)
end
end
def push(type, receiver, status)
redis.zadd(FeedManager.instance.key(type, receiver.id), status.id, status.id)
trim(type, receiver)
ActionCable.server.broadcast("timeline:#{receiver.id}", type: 'update', timeline: type, message: inline_render(receiver, status))
end
def trim(type, receiver)
return unless redis.zcard(FeedManager.instance.key(type, receiver.id)) > FeedManager::MAX_ITEMS
last = redis.zrevrange(FeedManager.instance.key(type, receiver.id), FeedManager::MAX_ITEMS - 1, FeedManager::MAX_ITEMS - 1)
redis.zremrangebyscore(FeedManager.instance.key(type, receiver.id), '-inf', "(#{last.last}")
end
def redis
$redis
end
def inline_render(receiver, status)
rabl_scope = Class.new(BaseService) do
def initialize(account)
@account = account
end
def current_user
@account.user
end
def current_account
@account
end
end
Rabl::Renderer.new('api/statuses/show', status, view_path: 'app/views', format: :json, scope: rabl_scope.new(receiver)).render
end
end

View file

@ -15,12 +15,27 @@ class FollowService < BaseService
NotificationWorker.perform_async(follow.stream_entry.id, target_account.id)
end
merge_into_timeline(target_account, source_account)
source_account.ping!(account_url(source_account, format: 'atom'), [Rails.configuration.x.hub_url])
follow
end
private
def merge_into_timeline(from_account, into_account)
timeline_key = FeedManager.instance.key(:home, into_account.id)
from_account.statuses.find_each do |status|
redis.zadd(timeline_key, status.id, status.id)
end
FeedManager.instance.trim(:home, into_account.id)
end
def redis
$redis
end
def follow_remote_account_service
@follow_remote_account_service ||= FollowRemoteAccountService.new
end

View file

@ -6,7 +6,7 @@ class PrecomputeFeedService < BaseService
def call(type, account, limit)
instant_return = []
Status.send("as_#{type}_timeline", account).order('created_at desc').limit(FeedManager::MAX_ITEMS).each do |status|
Status.send("as_#{type}_timeline", account).order('created_at desc').limit(FeedManager::MAX_ITEMS).find_each do |status|
next if type == :home && FeedManager.instance.filter_status?(status, account)
redis.zadd(FeedManager.instance.key(type, account.id), status.id, status.id)
instant_return << status unless instant_return.size > limit

View file

@ -5,5 +5,20 @@ class UnfollowService < BaseService
def call(source_account, target_account)
follow = source_account.unfollow!(target_account)
NotificationWorker.perform_async(follow.stream_entry.id, target_account.id) unless target_account.local?
unmerge_from_timeline(target_account, source_account)
end
private
def unmerge_from_timeline(from_account, into_account)
timeline_key = FeedManager.instance.key(:home, into_account.id)
from_account.statuses.find_each do |status|
redis.zrem(timeline_key, status.id)
end
end
def redis
$redis
end
end