Browse Source

Specs for precompute feed service (#3142)

* Add spec for precompute feed service

* Refactor PrecomputeFeedService

* spec wip
master
Matt Jankowski 7 years ago
committed by Eugen Rochko
parent
commit
db4119f971
3 changed files with 57 additions and 10 deletions
  1. +37
    -9
      app/services/precompute_feed_service.rb
  2. +3
    -1
      app/workers/regeneration_worker.rb
  3. +17
    -0
      spec/services/precompute_feed_service_spec.rb

+ 37
- 9
app/services/precompute_feed_service.rb View File

@ -1,20 +1,48 @@
# frozen_string_literal: true # frozen_string_literal: true
class PrecomputeFeedService < BaseService class PrecomputeFeedService < BaseService
# Fill up a user's home/mentions feed from DB and return a subset
# @param [Symbol] type :home or :mentions
# @param [Account] account
def call(_, account)
LIMIT = FeedManager::MAX_ITEMS / 4
def call(account)
@account = account
populate_feed
end
private
attr_reader :account
def populate_feed
redis.pipelined do redis.pipelined do
# NOTE: Added `id desc, account_id desc` to `ORDER BY` section to optimize query.
Status.as_home_timeline(account).order(account_id: :desc).limit(FeedManager::MAX_ITEMS / 4).each do |status|
next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account.id)
redis.zadd(FeedManager.instance.key(:home, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
statuses.each do |status|
process_status(status)
end end
end end
end end
private
def process_status(status)
add_status_to_feed(status) unless skip_status?(status)
end
def skip_status?(status)
status.direct_visibility? || status_filtered?(status)
end
def add_status_to_feed(status)
redis.zadd(account_home_key, status.id, status.reblog? ? status.reblog_of_id : status.id)
end
def status_filtered?(status)
FeedManager.instance.filter?(:home, status, account.id)
end
def account_home_key
FeedManager.instance.key(:home, account.id)
end
def statuses
Status.as_home_timeline(account).order(account_id: :desc).limit(LIMIT)
end
def redis def redis
Redis.current Redis.current

+ 3
- 1
app/workers/regeneration_worker.rb View File

@ -6,6 +6,8 @@ class RegenerationWorker
sidekiq_options queue: 'pull', backtrace: true, unique: :until_executed sidekiq_options queue: 'pull', backtrace: true, unique: :until_executed
def perform(account_id, _ = :home) def perform(account_id, _ = :home)
PrecomputeFeedService.new.call(:home, Account.find(account_id))
account = Account.find(account_id)
PrecomputeFeedService.new.call(account)
end end
end end

+ 17
- 0
spec/services/precompute_feed_service_spec.rb View File

@ -1,5 +1,22 @@
# frozen_string_literal: true
require 'rails_helper' require 'rails_helper'
RSpec.describe PrecomputeFeedService do RSpec.describe PrecomputeFeedService do
subject { PrecomputeFeedService.new } subject { PrecomputeFeedService.new }
describe 'call' do
let(:account) { Fabricate(:account) }
it 'fills a user timeline with statuses' do
account = Fabricate(:account)
followed_account = Fabricate(:account)
Fabricate(:follow, account: account, target_account: followed_account)
status = Fabricate(:status, account: followed_account)
expected_redis_args = FeedManager.instance.key(:home, account.id), status.id, status.id
expect_any_instance_of(Redis).to receive(:zadd).with(*expected_redis_args)
subject.call(account)
end
end
end end

Loading…
Cancel
Save