Skip to content

Commit

Permalink
Merge pull request #347 from kmycode/kb-draft-5.12-lts
Browse files Browse the repository at this point in the history
Release: 5.12 LTS
  • Loading branch information
kmycode authored Dec 15, 2023
2 parents 0dec7b4 + 38105df commit e227885
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 64 deletions.
10 changes: 10 additions & 0 deletions app/controllers/concerns/cache_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,16 @@ def enforce_cache_control!
def render_with_cache(**options)
raise ArgumentError, 'Only JSON render calls are supported' unless options.key?(:json) || block_given?

if options.delete(:cancel_cache)
if block_given?
options[:json] = yield
elsif options[:json].is_a?(Symbol)
options[:json] = send(options[:json])
end

return render(options)
end

key = options.delete(:key) || [[params[:controller], params[:action]].join('/'), options[:json].respond_to?(:cache_key) ? options[:json].cache_key : nil, options[:fields].nil? ? nil : options[:fields].join(',')].compact.join(':')
expires_in = options.delete(:expires_in) || 3.minutes
body = Rails.cache.read(key, raw: true)
Expand Down
31 changes: 27 additions & 4 deletions app/controllers/statuses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ def show
end

format.json do
expires_in 3.minutes, public: true if @status.distributable? && public_fetch_mode?
render_with_cache json: @status, content_type: 'application/activity+json', serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter
expires_in 3.minutes, public: true if @status.distributable? && public_fetch_mode? && !misskey_software?
render_with_cache json: @status, content_type: 'application/activity+json', serializer: status_activity_serializer, adapter: ActivityPub::Adapter, cancel_cache: misskey_software?
end
end
end

def activity
expires_in 3.minutes, public: @status.distributable? && public_fetch_mode?
render_with_cache json: ActivityPub::ActivityPresenter.from_status(@status), content_type: 'application/activity+json', serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter
expires_in 3.minutes, public: @status.distributable? && public_fetch_mode? && !misskey_software?
render_with_cache json: ActivityPub::ActivityPresenter.from_status(@status, for_misskey: misskey_software?), content_type: 'application/activity+json', serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter, cancel_cache: misskey_software?
end

def embed
Expand Down Expand Up @@ -76,6 +76,29 @@ def set_instance_presenter
@instance_presenter = InstancePresenter.new
end

def misskey_software?
return @misskey_software if defined?(@misskey_software)

@misskey_software = false

return false if !@status.local? || signed_request_account&.domain.blank?

info = InstanceInfo.find_by(domain: signed_request_account.domain)
return false if info.nil?

@misskey_software = %w(misskey calckey cherrypick sharkey).include?(info.software) &&
((@status.public_unlisted_visibility? && @status.account.user&.setting_reject_public_unlisted_subscription) ||
(@status.unlisted_visibility? && @status.account.user&.setting_reject_unlisted_subscription))
end

def status_activity_serializer
if misskey_software?
ActivityPub::NoteForMisskeySerializer
else
ActivityPub::NoteSerializer
end
end

def redirect_to_original
redirect_to(ActivityPub::TagManager.instance.url_for(@status.reblog), allow_other_host: true) if @status.reblog?
end
Expand Down
5 changes: 3 additions & 2 deletions app/services/activitypub/process_account_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def call(username, domain, json, options = {})
end

create_account
fetch_instance_info
end

update_account
Expand All @@ -66,6 +65,8 @@ def call(username, domain, json, options = {})
check_links! if @account.fields.any?(&:requires_verification?)
end

fetch_instance_info

@account
rescue Oj::ParseError
nil
Expand Down Expand Up @@ -211,7 +212,7 @@ def process_duplicate_accounts!
end

def fetch_instance_info
ActivityPub::FetchInstanceInfoWorker.perform_async(@account.domain) unless InstanceInfo.exists?(domain: @account.domain)
ActivityPub::FetchInstanceInfoWorker.perform_async(@account.domain) unless Rails.cache.exist?("fetch_instance_info:#{@account.domain}", expires_in: 1.day)
end

def actor_type
Expand Down
36 changes: 17 additions & 19 deletions app/workers/activitypub/fetch_instance_info_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,32 @@ class ActivityPub::FetchInstanceInfoWorker

sidekiq_options queue: 'push', retry: 2

class Error < StandardError; end
class RequestError < Error; end
class DeadError < Error; end

SUPPORTED_NOTEINFO_RELS = ['http://nodeinfo.diaspora.software/ns/schema/2.0', 'http://nodeinfo.diaspora.software/ns/schema/2.1'].freeze

def perform(domain)
@instance = Instance.find_by(domain: domain)
return if !@instance || @instance.unavailable_domain.present?

with_redis_lock("instance_info:#{domain}") do
link = nodeinfo_link
return if link.nil?

update_info!(link)
Rails.cache.fetch("fetch_instance_info:#{@instance.domain}", expires_in: 1.day, race_condition_ttl: 1.hour) do
fetch!
end
rescue ActivityPub::FetchInstanceInfoWorker::DeadError

true
end

private

def fetch!
link = nodeinfo_link
return if link.nil?

update_info!(link)

true
rescue Mastodon::UnexpectedResponseError
true
end

def nodeinfo_link
nodeinfo = fetch_json("https://#{@instance.domain}/.well-known/nodeinfo")
return nil if nodeinfo.nil? || !nodeinfo.key?('links')
Expand Down Expand Up @@ -63,15 +67,9 @@ def update_info!(url)

def fetch_json(url)
build_request(url).perform do |response|
if [200, 203].include?(response.code)
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response)

body_to_json(response.body_with_limit)
elsif [400, 401, 403, 404, 410].include?(response.code)
raise ActivityPub::FetchInstanceInfoWorker::DeadError, "Request for #{@instance.domain} returned HTTP #{response.code}"
else
raise ActivityPub::FetchInstanceInfoWorker::RequestError, "Request for #{@instance.domain} returned HTTP #{response.code}"
end
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response)

body_to_json(response.body_with_limit)
end
end

Expand Down
15 changes: 0 additions & 15 deletions app/workers/scheduler/update_instance_info_scheduler.rb

This file was deleted.

4 changes: 0 additions & 4 deletions config/sidekiq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@
interval: 30 seconds
class: Scheduler::SidekiqHealthScheduler
queue: scheduler
update_instance_info_scheduler:
cron: '0 0 * * *'
class: Scheduler::UpdateInstanceInfoScheduler
queue: scheduler
software_update_check_scheduler:
interval: 30 minutes
class: Scheduler::SoftwareUpdateCheckScheduler
Expand Down
2 changes: 1 addition & 1 deletion lib/mastodon/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def kmyblue_major
end

def kmyblue_minor
11
12
end

def kmyblue_flag
Expand Down
1 change: 1 addition & 0 deletions spec/lib/activitypub/activity/update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
stub_request(:get, actor_json[:following]).to_return(status: 404)
stub_request(:get, actor_json[:featured]).to_return(status: 404)
stub_request(:get, actor_json[:featuredTags]).to_return(status: 404)
stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(status: 404)

subject.perform
end
Expand Down
4 changes: 4 additions & 0 deletions spec/services/activitypub/process_account_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
RSpec.describe ActivityPub::ProcessAccountService, type: :service do
subject { described_class.new }

before do
stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(status: 404)
end

context 'with searchability' do
subject { described_class.new.call('alice', 'example.com', payload) }

Expand Down
20 changes: 20 additions & 0 deletions spec/workers/activitypub/fetch_instance_info_worker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,22 @@
Instance.refresh
end

it 'does not update immediately' do
stub_request(:get, 'https://example.com/nodeinfo/2.0').to_return(status: 200, body: nodeinfo_json)
subject.perform('example.com')
stub_request(:get, 'https://example.com/nodeinfo/2.0').to_return(status: 200, body: new_nodeinfo_json)
subject.perform('example.com')

info = InstanceInfo.find_by(domain: 'example.com')
expect(info).to_not be_nil
expect(info.software).to eq 'mastodon'
expect(info.version).to eq '4.2.0-beta1'
end

it 'performs a mastodon instance' do
stub_request(:get, 'https://example.com/nodeinfo/2.0').to_return(status: 200, body: nodeinfo_json)
subject.perform('example.com')
Rails.cache.delete('fetch_instance_info:example.com')
stub_request(:get, 'https://example.com/nodeinfo/2.0').to_return(status: 200, body: new_nodeinfo_json)
subject.perform('example.com')

Expand All @@ -93,5 +106,12 @@
info = InstanceInfo.find_by(domain: 'example.com')
expect(info).to be_nil
end

it 'does not fetch again immediately' do
expect(subject.perform('example.com')).to be true
expect(subject.perform('example.com')).to be true

expect(a_request(:get, 'https://example.com/.well-known/nodeinfo')).to have_been_made.once
end
end
end
19 changes: 0 additions & 19 deletions spec/workers/scheduler/update_instance_info_scheduler_spec.rb

This file was deleted.

0 comments on commit e227885

Please sign in to comment.