Files
MatchLiveTv/backend/app/services/recordings/storage.rb
Emiliano Frascaro 13390d8a3c Replay fuori da Puma, fix ops cron e firma release Android.
Dopo auth Rails redirect a URL presigned su /media/ (edge → Garage); aumenta
RAILS_MAX_THREADS, corregge ingest log ops via stdin e keystore Play Console.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 22:59:15 +02:00

129 lines
3.4 KiB
Ruby

require "open-uri"
require "aws-sdk-s3"
module Recordings
class Storage
class Error < StandardError; end
def initialize
@backend = MatchLiveTv.replay_storage_local? ? LocalBackend.new : S3Backend.new
end
def upload(local_path:, key:, content_type: "video/mp4")
@backend.upload(local_path: local_path, key: key, content_type: content_type)
end
def delete(key:)
@backend.delete(key: key)
end
def download_to_temp(key:)
local = local_path_for_key(key)
return local if local && File.exist?(local)
url = presigned_get_url(key: key, expires_in: 600)
raise Error, "Impossibile scaricare file dallo storage" if url.blank?
dest = File.join(Dir.tmpdir, "replay-dl-#{SecureRandom.hex(8)}.mp4")
URI.open(url) do |remote|
File.binwrite(dest, remote.read)
end
dest
end
def presigned_get_url(key:, expires_in: MatchLiveTv.replay_presigned_url_ttl_seconds, response_content_disposition: nil)
@backend.presigned_get_url(
key: key,
expires_in: expires_in,
response_content_disposition: response_content_disposition
)
end
def local_path_for_key(key)
@backend.local_path_for_key(key)
end
def backend_name
@backend.name
end
class LocalBackend
def name
"local"
end
def upload(local_path:, key:, content_type:)
dest = local_path_for_key(key)
FileUtils.mkdir_p(File.dirname(dest))
FileUtils.cp(local_path, dest)
File.size(dest)
end
def delete(key:)
path = local_path_for_key(key)
FileUtils.rm_f(path)
true
end
def presigned_get_url(key:, expires_in:, response_content_disposition: nil)
nil
end
def local_path_for_key(key)
File.join(MatchLiveTv.recordings_local_path, "replays", key)
end
end
class S3Backend
def name
"s3"
end
def upload(local_path:, key:, content_type:)
client.put_object(
bucket: MatchLiveTv.replay_storage_bucket,
key: key,
body: File.open(local_path, "rb"),
content_type: content_type
)
File.size(local_path)
end
def delete(key:)
client.delete_object(bucket: MatchLiveTv.replay_storage_bucket, key: key)
true
rescue Aws::S3::Errors::ServiceError => e
raise Error, e.message
end
def presigned_get_url(key:, expires_in:, response_content_disposition: nil)
signer = Aws::S3::Presigner.new(client: client)
params = {
bucket: MatchLiveTv.replay_storage_bucket,
key: key,
expires_in: expires_in
}
params[:response_content_disposition] = response_content_disposition if response_content_disposition.present?
signer.presigned_url(:get_object, **params)
end
def local_path_for_key(_key)
nil
end
private
def client
@client ||= Aws::S3::Client.new(
access_key_id: MatchLiveTv.replay_storage_access_key_id,
secret_access_key: MatchLiveTv.replay_storage_secret_access_key,
endpoint: MatchLiveTv.replay_storage_endpoint,
region: MatchLiveTv.replay_storage_region,
force_path_style: MatchLiveTv.replay_storage_force_path_style?,
response_checksum_validation: "WHEN_REQUIRED"
)
end
end
end
end