Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

Commit

Permalink
Upgrade to latest redis-rb 4.x and fix deprecations (mastodon#23616)
Browse files Browse the repository at this point in the history
Co-authored-by: Jean Boussier <[email protected]>
  • Loading branch information
casperisfine and byroot authored Mar 4, 2023
1 parent aa98c8f commit 922837d
Show file tree
Hide file tree
Showing 11 changed files with 37 additions and 38 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ GEM
rdf-normalize (0.5.1)
rdf (~> 3.2)
redcarpet (3.6.0)
redis (4.5.1)
redis (4.8.1)
redis-namespace (1.10.0)
redis (>= 4)
redlock (1.3.2)
Expand Down
20 changes: 10 additions & 10 deletions app/lib/feed_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -273,27 +273,27 @@ def populate_home(account)
def clean_feeds!(type, ids)
reblogged_id_sets = {}

redis.pipelined do
redis.pipelined do |pipeline|
ids.each do |feed_id|
redis.del(key(type, feed_id))
reblog_key = key(type, feed_id, 'reblogs')
# We collect a future for this: we don't block while getting
# it, but we can iterate over it later.
reblogged_id_sets[feed_id] = redis.zrange(reblog_key, 0, -1)
redis.del(reblog_key)
reblogged_id_sets[feed_id] = pipeline.zrange(reblog_key, 0, -1)
pipeline.del(key(type, feed_id), reblog_key)
end
end

# Remove all of the reblog tracking keys we just removed the
# references to.
redis.pipelined do
reblogged_id_sets.each do |feed_id, future|
future.value.each do |reblogged_id|
reblog_set_key = key(type, feed_id, "reblogs:#{reblogged_id}")
redis.del(reblog_set_key)
end
keys_to_delete = reblogged_id_sets.flat_map do |feed_id, future|
future.value.map do |reblogged_id|
key(type, feed_id, "reblogs:#{reblogged_id}")
end
end

redis.del(keys_to_delete) unless keys_to_delete.empty?

nil
end

private
Expand Down
4 changes: 2 additions & 2 deletions app/models/follow_recommendation_suppression.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class FollowRecommendationSuppression < ApplicationRecord
private

def remove_follow_recommendations
redis.pipelined do
redis.pipelined do |pipeline|
I18n.available_locales.each do |locale|
redis.zrem("follow_recommendations:#{locale}", account_id)
pipeline.zrem("follow_recommendations:#{locale}", account_id)
end
end
end
Expand Down
18 changes: 9 additions & 9 deletions app/services/batched_remove_status_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ def call(statuses, **options)

# Cannot be batched
@status_id_cutoff = Mastodon::Snowflake.id_at(2.weeks.ago)
redis.pipelined do
redis.pipelined do |pipeline|
statuses.each do |status|
unpush_from_public_timelines(status)
unpush_from_public_timelines(status, pipeline)
end
end
end
Expand All @@ -70,22 +70,22 @@ def unpush_from_list_timelines(account, statuses)
end
end

def unpush_from_public_timelines(status)
def unpush_from_public_timelines(status, pipeline)
return unless status.public_visibility? && status.id > @status_id_cutoff

payload = Oj.dump(event: :delete, payload: status.id.to_s)

redis.publish('timeline:public', payload)
redis.publish(status.local? ? 'timeline:public:local' : 'timeline:public:remote', payload)
pipeline.publish('timeline:public', payload)
pipeline.publish(status.local? ? 'timeline:public:local' : 'timeline:public:remote', payload)

if status.media_attachments.any?
redis.publish('timeline:public:media', payload)
redis.publish(status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', payload)
pipeline.publish('timeline:public:media', payload)
pipeline.publish(status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', payload)
end

status.tags.map { |tag| tag.name.mb_chars.downcase }.each do |hashtag|
redis.publish("timeline:hashtag:#{hashtag}", payload)
redis.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local?
pipeline.publish("timeline:hashtag:#{hashtag}", payload)
pipeline.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local?
end
end
end
13 changes: 5 additions & 8 deletions app/workers/scheduler/follow_recommendations_scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def perform

Trends.available_locales.each do |locale|
recommendations = if AccountSummary.safe.filtered.localized(locale).exists? # We can skip the work if no accounts with that language exist
FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.account_id, recommendation.rank] }
FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.rank, recommendation.account_id] }
else
[]
end
Expand All @@ -33,14 +33,14 @@ def perform

# Language-specific results should be above language-agnostic ones,
# otherwise language-agnostic ones will always overshadow them
recommendations.map! { |(account_id, rank)| [account_id, rank + max_fallback_rank] }
recommendations.map! { |(rank, account_id)| [rank + max_fallback_rank, account_id] }

added = 0

fallback_recommendations.each do |recommendation|
next if recommendations.any? { |(account_id, _)| account_id == recommendation.account_id }
next if recommendations.any? { |(_, account_id)| account_id == recommendation.account_id }

recommendations << [recommendation.account_id, recommendation.rank]
recommendations << [recommendation.rank, recommendation.account_id]
added += 1

break if added >= missing
Expand All @@ -49,10 +49,7 @@ def perform

redis.multi do |multi|
multi.del(key(locale))

recommendations.each do |(account_id, rank)|
multi.zadd(key(locale), rank, account_id)
end
multi.zadd(key(locale), recommendations)
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@
config.x.otp_secret = ENV.fetch('OTP_SECRET', '1fc2b87989afa6351912abeebe31ffc5c476ead9bf8b3d74cbc4a302c7b69a45b40b1bbef3506ddad73e942e15ed5ca4b402bf9a66423626051104f4b5f05109')
end

Redis.raise_deprecations = true

ActiveRecordQueryTrace.enabled = ENV['QUERY_TRACE_ENABLED'] == 'true'

module PrivateAddressCheck
Expand Down
2 changes: 2 additions & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,5 @@

# Catch serialization warnings early
Sidekiq.strict_args!

Redis.raise_deprecations = true
1 change: 1 addition & 0 deletions config/initializers/redis.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Redis.sadd_returns_boolean = false
2 changes: 1 addition & 1 deletion db/migrate/20170920032311_fix_reblogs_in_feeds.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class FixReblogsInFeeds < ActiveRecord::Migration[5.1]
def up
redis = Redis.current
redis = RedisConfiguration.pool.checkout
fm = FeedManager.instance

# Old scheme:
Expand Down
5 changes: 3 additions & 2 deletions db/migrate/20200407202420_migrate_unavailable_inboxes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ class MigrateUnavailableInboxes < ActiveRecord::Migration[5.2]
disable_ddl_transaction!

def up
urls = Redis.current.smembers('unavailable_inboxes')
redis = RedisConfiguration.pool.checkout
urls = redis.smembers('unavailable_inboxes')

hosts = urls.map do |url|
Addressable::URI.parse(url).normalized_host
Expand All @@ -14,7 +15,7 @@ def up
UnavailableDomain.create(domain: host)
end

Redis.current.del(*(['unavailable_inboxes'] + Redis.current.keys('exhausted_deliveries:*')))
redis.del(*(['unavailable_inboxes'] + redis.keys('exhausted_deliveries:*')))
end

def down; end
Expand Down
6 changes: 1 addition & 5 deletions lib/mastodon/feeds_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ def build(username = nil)
desc 'clear', 'Remove all home and list feeds from Redis'
def clear
keys = redis.keys('feed:*')

redis.pipelined do
keys.each { |key| redis.del(key) }
end

redis.del(keys)
say('OK', :green)
end
end
Expand Down

0 comments on commit 922837d

Please sign in to comment.