Put Elasticsearch search queries behind a Stoplight (#39323)

This commit is contained in:
Claire 2026-06-09 10:30:43 +02:00 committed by GitHub
parent 4a5a915e86
commit 481e51b81e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 4 deletions

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
class AccountSearchService < BaseService
include SearchStoplight
attr_reader :query, :limit, :offset, :options, :account
MENTION_ONLY_RE = /\A#{Account::MENTION_RE}\z/i
@ -251,12 +253,12 @@ class AccountSearchService < BaseService
end
end
records = query_builder.build.limit(limit_for_non_exact_results).offset(offset).objects.compact
records = elastic_stoplight_wrapper.run { query_builder.build.limit(limit_for_non_exact_results).offset(offset).objects.compact }
ActiveRecord::Associations::Preloader.new(records: records, associations: [:account_stat, { user: :role }]).call
records
rescue Faraday::ConnectionFailed, Parslet::ParseFailed, Errno::ENETUNREACH
rescue Stoplight::Error::RedLight, Faraday::ConnectionFailed, Parslet::ParseFailed, Errno::ENETUNREACH, OpenSSL::SSL::SSLError, Elastic::Transport::Transport::Error
nil
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module SearchStoplight
STOPLIGHT_COOL_OFF_TIME = 5.minutes.seconds
STOPLIGHT_THRESHOLD = 10
def elastic_stoplight_wrapper
Stoplight(
'search:elasticsearch',
cool_off_time: STOPLIGHT_COOL_OFF_TIME,
threshold: STOPLIGHT_THRESHOLD,
tracked_errors: [Faraday::ConnectionFailed, Errno::ENETUNREACH, OpenSSL::SSL::SSLError, Elastic::Transport::Transport::Error]
)
end
end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
class StatusesSearchService < BaseService
include SearchStoplight
def call(query, account = nil, options = {})
MastodonOTELTracer.in_span('StatusesSearchService#call') do |span|
@query = query&.strip
@ -26,14 +28,14 @@ class StatusesSearchService < BaseService
def status_search_results
request = parsed_query.request
results = request.collapse(field: :id).order(id: { order: :desc }).limit(@limit).offset(@offset).objects.compact
results = elastic_stoplight_wrapper.run { request.collapse(field: :id).order(id: { order: :desc }).limit(@limit).offset(@offset).objects.compact }
account_ids = results.map(&:account_id)
account_domains = results.map(&:account_domain)
@account.preload_relations!(account_ids, account_domains)
results.reject { |status| StatusFilter.new(status, @account).filtered? }
rescue Faraday::ConnectionFailed, Parslet::ParseFailed, Errno::ENETUNREACH
rescue Stoplight::Error::RedLight, Faraday::ConnectionFailed, Parslet::ParseFailed, Errno::ENETUNREACH, OpenSSL::SSL::SSLError, Elastic::Transport::Transport::Error
[]
end