fix(captain-memory): wrap ExtractFromConversationJob persistence in transaction + hoist unit lookup
This commit is contained in:
parent
9d5e4c959f
commit
1646f66a97
@ -21,7 +21,9 @@ class Captain::ContactMemories::ExtractFromConversationJob < ApplicationJob
|
|||||||
facts = Captain::ContactMemories::ExtractionService.new(conversation: conversation).call
|
facts = Captain::ContactMemories::ExtractionService.new(conversation: conversation).call
|
||||||
return if facts.blank?
|
return if facts.blank?
|
||||||
|
|
||||||
facts.each { |fact| persist_fact(fact, conversation) }
|
unit_id = resolve_unit_id(conversation)
|
||||||
|
created_memory_ids = persist_all(facts, conversation, unit_id)
|
||||||
|
enqueue_embedding_jobs(created_memory_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -30,12 +32,23 @@ class Captain::ContactMemories::ExtractFromConversationJob < ApplicationJob
|
|||||||
Captain::ContactMemory.exists?(source_conversation_id: conversation.id)
|
Captain::ContactMemory.exists?(source_conversation_id: conversation.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def persist_fact(fact, conversation)
|
def persist_all(facts, conversation, unit_id)
|
||||||
memory = Captain::ContactMemory.create!(build_attributes(fact, conversation))
|
Captain::ContactMemory.transaction do
|
||||||
Captain::ContactMemories::UpdateEmbeddingJob.perform_later(memory.id, run_contradiction_check: true)
|
facts.map { |fact| persist_fact(fact, conversation, unit_id).id }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_attributes(fact, conversation)
|
def enqueue_embedding_jobs(memory_ids)
|
||||||
|
memory_ids.each do |id|
|
||||||
|
Captain::ContactMemories::UpdateEmbeddingJob.perform_later(id, run_contradiction_check: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def persist_fact(fact, conversation, unit_id)
|
||||||
|
Captain::ContactMemory.create!(build_attributes(fact, conversation, unit_id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_attributes(fact, conversation, unit_id)
|
||||||
ttl = TTL_BY_TYPE[fact[:memory_type]]
|
ttl = TTL_BY_TYPE[fact[:memory_type]]
|
||||||
{
|
{
|
||||||
account_id: conversation.account_id,
|
account_id: conversation.account_id,
|
||||||
@ -46,7 +59,7 @@ class Captain::ContactMemories::ExtractFromConversationJob < ApplicationJob
|
|||||||
confidence: fact[:confidence],
|
confidence: fact[:confidence],
|
||||||
scope: fact[:scope],
|
scope: fact[:scope],
|
||||||
source_conversation_id: conversation.id,
|
source_conversation_id: conversation.id,
|
||||||
source_unit_id: resolve_unit_id(conversation),
|
source_unit_id: unit_id,
|
||||||
source_inbox_id: conversation.inbox_id,
|
source_inbox_id: conversation.inbox_id,
|
||||||
last_verified_at: Time.current,
|
last_verified_at: Time.current,
|
||||||
expires_at: ttl&.from_now
|
expires_at: ttl&.from_now
|
||||||
|
|||||||
@ -64,4 +64,22 @@ RSpec.describe Captain::ContactMemories::ExtractFromConversationJob do
|
|||||||
described_class.perform_now(conversation.id)
|
described_class.perform_now(conversation.id)
|
||||||
expect(Captain::ContactMemory.last.expires_at).to be_nil
|
expect(Captain::ContactMemory.last.expires_at).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'rolls back all facts and does not enqueue jobs if any fact fails to persist' do
|
||||||
|
bad_facts = [
|
||||||
|
{ memory_type: 'preferencia', content: 'A', evidence: 'x', confidence: 0.9, scope: 'global' },
|
||||||
|
{ memory_type: 'invalid_type_not_in_enum', content: 'B', evidence: 'y', confidence: 0.9, scope: 'global' }
|
||||||
|
]
|
||||||
|
allow_any_instance_of(Captain::ContactMemories::ExtractionService) # rubocop:disable RSpec/AnyInstance
|
||||||
|
.to receive(:call).and_return(bad_facts)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
expect { described_class.perform_now(conversation.id) }.to raise_error(ActiveRecord::RecordInvalid)
|
||||||
|
end.not_to change(Captain::ContactMemory, :count)
|
||||||
|
|
||||||
|
embedding_jobs = ActiveJob::Base.queue_adapter.enqueued_jobs.select do |j|
|
||||||
|
j[:job] == Captain::ContactMemories::UpdateEmbeddingJob
|
||||||
|
end
|
||||||
|
expect(embedding_jobs).to be_empty
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user