FIX: properly cache user locale (#593)

This blob is localized according to user locale, so we can end up
bleeding incorrect data in the cache
This commit is contained in:
Sam 2024-04-26 22:28:35 +10:00 committed by GitHub
parent 283445cf81
commit 85734fef52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 88 additions and 36 deletions

View File

@ -31,38 +31,8 @@ class AiPersona < ActiveRecord::Base
before_update :regenerate_rag_fragments before_update :regenerate_rag_fragments
class MultisiteHash
def initialize(id)
@hash = Hash.new { |h, k| h[k] = {} }
@id = id
MessageBus.subscribe(channel_name) { |message| @hash[message.data] = {} }
end
def channel_name
"/multisite-hash-#{@id}"
end
def current_db
RailsMultisite::ConnectionManagement.current_db
end
def [](key)
@hash.dig(current_db, key)
end
def []=(key, val)
@hash[current_db][key] = val
end
def flush!
@hash[current_db] = {}
MessageBus.publish(channel_name, current_db)
end
end
def self.persona_cache def self.persona_cache
@persona_cache ||= MultisiteHash.new("persona_cache") @persona_cache ||= ::DiscourseAi::MultisiteHash.new("persona_cache")
end end
scope :ordered, -> { order("priority DESC, lower(name) ASC") } scope :ordered, -> { order("priority DESC, lower(name) ASC") }

View File

@ -3,16 +3,20 @@
module DiscourseAi module DiscourseAi
module AiHelper module AiHelper
class Assistant class Assistant
AI_HELPER_PROMPTS_CACHE_KEY = "ai_helper_prompts" def self.prompt_cache
@prompt_cache ||= ::DiscourseAi::MultisiteHash.new("prompt_cache")
end
def self.clear_prompt_cache! def self.clear_prompt_cache!
Discourse.cache.delete(AI_HELPER_PROMPTS_CACHE_KEY) prompt_cache.flush!
end end
def available_prompts def available_prompts
Discourse key = "prompt_cache_#{I18n.locale}"
.cache self
.fetch(AI_HELPER_PROMPTS_CACHE_KEY, expires_in: 30.minutes) do .class
.prompt_cache
.fetch(key) do
prompts = CompletionPrompt.where(enabled: true) prompts = CompletionPrompt.where(enabled: true)
# Hide illustrate_post if disabled # Hide illustrate_post if disabled

39
lib/multisite_hash.rb Normal file
View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
module DiscourseAi
class MultisiteHash
def initialize(id)
@hash = Hash.new { |h, k| h[k] = {} }
@id = id
MessageBus.subscribe(channel_name) { |message| @hash[message.data] = {} }
end
def channel_name
"/multisite-hash-#{@id}"
end
def current_db
RailsMultisite::ConnectionManagement.current_db
end
def fetch(key)
@hash[current_db][key] ||= yield
end
def [](key)
@hash.dig(current_db, key)
end
def []=(key, val)
@hash[current_db][key] = val
end
def flush!
@hash[current_db] = {}
MessageBus.publish(channel_name, current_db)
end
# TODO implement a GC so we don't retain too much memory
end
end

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
describe DiscourseAi::AiHelper::EntryPoint do
fab!(:english_user) { Fabricate(:user) }
fab!(:french_user) { Fabricate(:user, locale: "fr") }
it "will correctly localize available prompts" do
SiteSetting.ai_helper_model = "fake:fake"
SiteSetting.default_locale = "en"
SiteSetting.allow_user_locale = true
SiteSetting.composer_ai_helper_enabled = true
SiteSetting.ai_helper_allowed_groups = "10" # tl0
DiscourseAi::AiHelper::Assistant.clear_prompt_cache!
Group.refresh_automatic_groups!
serializer = CurrentUserSerializer.new(english_user, scope: Guardian.new(english_user))
parsed = JSON.parse(serializer.to_json)
translate_prompt =
parsed["current_user"]["ai_helper_prompts"].find { |prompt| prompt["name"] == "translate" }
expect(translate_prompt["translated_name"]).to eq(
I18n.t("discourse_ai.ai_helper.prompts.translate"),
)
I18n.with_locale("fr") do
serializer = CurrentUserSerializer.new(french_user, scope: Guardian.new(french_user))
parsed = JSON.parse(serializer.to_json)
translate_prompt =
parsed["current_user"]["ai_helper_prompts"].find { |prompt| prompt["name"] == "translate" }
expect(translate_prompt["translated_name"]).to eq(
I18n.t("discourse_ai.ai_helper.prompts.translate", locale: "fr"),
)
end
end
end