We’ve been watching Sidekiq workers climb from ~600 MB at boot to 1.4–1.5 GB after an hour whenever attachment-heavy jobs run. This PR is an experiment to curb that growth by streaming attachments instead of loading the whole blob into Ruby: reply-mailer inline attachments, Telegram uploads, and audio transcriptions now read/write in chunks. If this keeps RSS stable in production we’ll keep it; otherwise we’ll roll it back and keep digging
60 lines
2.1 KiB
Ruby
60 lines
2.1 KiB
Ruby
require 'rails_helper'
|
|
require 'custom_exceptions/pdf_processing_error'
|
|
|
|
RSpec.describe Captain::Llm::PdfProcessingService do
|
|
let(:document) { create(:captain_document) }
|
|
let(:service) { described_class.new(document) }
|
|
|
|
before do
|
|
# Mock OpenAI configuration
|
|
installation_config = instance_double(InstallationConfig, value: 'test-api-key')
|
|
allow(InstallationConfig).to receive(:find_by!)
|
|
.with(name: 'CAPTAIN_OPEN_AI_API_KEY')
|
|
.and_return(installation_config)
|
|
end
|
|
|
|
describe '#process' do
|
|
context 'when document already has OpenAI file ID' do
|
|
before do
|
|
allow(document).to receive(:openai_file_id).and_return('existing-file-id')
|
|
end
|
|
|
|
it 'skips upload' do
|
|
expect(document).not_to receive(:store_openai_file_id)
|
|
service.process
|
|
end
|
|
end
|
|
|
|
context 'when uploading PDF to OpenAI' do
|
|
let(:mock_client) { instance_double(OpenAI::Client) }
|
|
let(:pdf_content) { 'PDF content' }
|
|
let(:blob_double) { instance_double(ActiveStorage::Blob) }
|
|
let(:pdf_file) { instance_double(ActiveStorage::Attachment) }
|
|
|
|
before do
|
|
allow(document).to receive(:openai_file_id).and_return(nil)
|
|
allow(document).to receive(:pdf_file).and_return(pdf_file)
|
|
allow(pdf_file).to receive(:blob).and_return(blob_double)
|
|
allow(blob_double).to receive(:open).and_yield(StringIO.new(pdf_content))
|
|
|
|
allow(OpenAI::Client).to receive(:new).and_return(mock_client)
|
|
# Use a simple double for OpenAI::Files as it may not be loaded
|
|
files_api = double('files_api') # rubocop:disable RSpec/VerifiedDoubles
|
|
allow(files_api).to receive(:upload).and_return({ 'id' => 'file-abc123' })
|
|
allow(mock_client).to receive(:files).and_return(files_api)
|
|
end
|
|
|
|
it 'uploads PDF and stores file ID' do
|
|
expect(document).to receive(:store_openai_file_id).with('file-abc123')
|
|
service.process
|
|
end
|
|
|
|
it 'raises error when upload fails' do
|
|
allow(mock_client.files).to receive(:upload).and_return({ 'id' => nil })
|
|
|
|
expect { service.process }.to raise_error(CustomExceptions::PdfUploadError)
|
|
end
|
|
end
|
|
end
|
|
end
|