April 26, 2022
Active Job with huge payload
Today's problem involves active job with sidekiq. We have to enqueue a job with a huge payload (more than 10MB). Remember that when you create a job in sidekiq you actually put a new element in a Redis queue and if the params are big you will put that very large payload in the Redis. Is it a problem? Depends, in our case yes because we just have Redis in RAM, and it will increase the RAM. (It's possible to have different strategies for Redis)
The solution we developed for this situation is to put the payload on Amazon S3 and create a job with just the S3 file key.
Class to use the Ruby AWS SDK:
The solution we developed for this situation is to put the payload on Amazon S3 and create a job with just the S3 file key.
Class to use the Ruby AWS SDK:
class AwsS3Client
BUCKET = ENV.fetch('S3_BUCKET')
ACCESS_KEY_ID = ENV.fetch('S3_ACCESS_KEY_ID')
SECRET_ACCESS_KEY = ENV.fetch('S3_SECRET_ACCESS_KEY')
REGION = ENV.fetch('S3_REGION')
attr_reader :bucket
def initialize(bucket: BUCKET)
@bucket = bucket
end
def put(name:, content:)
client.put_object(
bucket: bucket,
body: content,
key: name
)
end
def delete(name)
client.delete_object(
bucket: bucket,
key: name
)
end
def download(name:, path:)
client.get_object(
response_target: path,
bucket: bucket,
key: name
)
end
private
def client
@client ||= Aws::S3::Client.new(sdk_options)
end
def sdk_options
{
credentials: Aws::Credentials.new(
ACCESS_KEY_ID,
SECRET_ACCESS_KEY
),
region: REGION
}
end
endCreating a job:
s3_key = "#{SecureRandom.uuid}.to_json"
AwsS3Client.new.put(name: s3_key, content: my_big_payload.to_json)
MyCoolJob.perform_late(s3_key)The job:
... def perform(s3_key) client = AwsS3Client.new data = JSON.parse(client.download(s3_key)) ... client.delete(s3_key) end ...
Thas all :)