218 lines
6.7 KiB
Ruby
218 lines
6.7 KiB
Ruby
module JamRuby
|
|
|
|
# describes what users have rights to which tracks
|
|
class JamTrackMixdownPackage < ActiveRecord::Base
|
|
include JamRuby::S3ManagerMixin
|
|
|
|
@@log = Logging.logger[JamTrackMixdownPackage]
|
|
|
|
# these are used as extensions for the files stored in s3
|
|
FILE_TYPE_OGG = 'ogg'
|
|
FILE_TYPE_AAC = 'aac'
|
|
FILE_TYPES = [FILE_TYPE_OGG, FILE_TYPE_AAC]
|
|
|
|
SAMPLE_RATE_44 = 44
|
|
SAMPLE_RATE_48 = 48
|
|
SAMPLE_RATES = [SAMPLE_RATE_44, SAMPLE_RATE_48]
|
|
|
|
ENCRYPT_TYPE_JKZ = 'jkz'
|
|
ENCRYPT_TYPES = [ENCRYPT_TYPE_JKZ, nil]
|
|
|
|
belongs_to :jam_track_mixdown, class_name: "JamRuby::JamTrackMixdown", dependent: :destroy
|
|
|
|
validates :jam_track_mixdown, presence: true
|
|
|
|
validates :file_type, inclusion: {in: FILE_TYPES}
|
|
validates :sample_rate, inclusion: {in: SAMPLE_RATES}
|
|
validates :encrypt_type, inclusion: {in: ENCRYPT_TYPES}
|
|
validates_uniqueness_of :file_type, scope: :sample_rate
|
|
validates :signing, presence: true
|
|
validates :signed, presence: true
|
|
|
|
validate :verify_download_count
|
|
before_destroy :delete_s3_files
|
|
|
|
|
|
MAX_JAM_TRACK_DOWNLOADS = 1000
|
|
|
|
|
|
|
|
def after_save
|
|
# try to catch major transitions:
|
|
|
|
# if just queue time changes, start time changes, or signed time changes, send out a notice
|
|
if signing_queued_at_was != signing_queued_at || signing_started_at_was != signing_started_at || last_signed_at_was != last_signed_at || current_packaging_step != current_packaging_step_was || packaging_steps != packaging_steps_was
|
|
SubscriptionMessage.mixdown_signing_job_change(self)
|
|
end
|
|
end
|
|
|
|
def self.create(mixdown, file_type, sample_rate, encrypt)
|
|
|
|
package = JamTrackMixdownPackage.new
|
|
package.jam_track_mixdown = mixdown
|
|
package.file_type = file_type
|
|
package.sample_rate = sample_rate
|
|
package.save
|
|
package
|
|
end
|
|
|
|
|
|
def verify_download_count
|
|
if (self.download_count < 0 || self.download_count > MAX_JAM_TRACK_DOWNLOADS) && !@current_user.admin
|
|
errors.add(:download_count, "must be less than or equal to #{MAX_JAM_TRACK_DOWNLOADS}")
|
|
end
|
|
end
|
|
|
|
|
|
def finish_errored(error_reason, error_detail)
|
|
self.last_signed_at = Time.now
|
|
self.error_count = self.error_count + 1
|
|
self.error_reason = error_reason
|
|
self.error_detail = error_detail
|
|
self.should_retry = self.error_count < 5
|
|
self.signing = false
|
|
|
|
if save
|
|
Notification.send_mixdown_sign_failed(self)
|
|
else
|
|
raise "Error sending notification #{self.errors}"
|
|
end
|
|
end
|
|
|
|
def finish_sign(url, private_key, length, md5)
|
|
self.url = url
|
|
self.private_key = private_key
|
|
self.signing_queued_at = nil # if left set, throws off signing_state on subsequent signing attempts
|
|
self.downloaded_since_sign = false
|
|
self.last_signed_at = Time.now
|
|
self.length = length
|
|
self.md5 = md5
|
|
self.signed = true
|
|
self.signing = false
|
|
self.error_count = 0
|
|
self.error_reason = nil
|
|
self.error_detail = nil
|
|
self.should_retry = false
|
|
save!
|
|
end
|
|
|
|
def store_dir
|
|
"jam_track_mixdowns/#{created_at.strftime('%m-%d-%Y')}/#{self.jam_track_mixdown.user_id}"
|
|
end
|
|
|
|
def filename
|
|
if encrypt_type
|
|
"#{id}.#{encrypt_type}"
|
|
else
|
|
"#{id}.#{file_type}"
|
|
end
|
|
end
|
|
|
|
|
|
# creates a short-lived URL that has access to the object.
|
|
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
|
|
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
|
|
# but the url is short lived enough so that it wouldn't be easily shared
|
|
def sign_url(expiration_time = 120)
|
|
s3_manager.sign_url(self['url'], {:expires => expiration_time, :secure => true})
|
|
end
|
|
|
|
|
|
def enqueue
|
|
begin
|
|
JamTrackMixdownPackager.where(:id => self.id).update_all(:signing_queued_at => Time.now, :signing_started_at => nil, :last_signed_at => nil)
|
|
Resque.enqueue(JamTrackMixdownPackager, self.id)
|
|
true
|
|
rescue Exception => e
|
|
puts "e: #{e}"
|
|
# implies redis is down. we don't update started_at by bailing out here
|
|
false
|
|
end
|
|
end
|
|
|
|
# if the job is already signed, just queued up for signing, or currently signing, then don't enqueue... otherwise fire it off
|
|
def enqueue_if_needed
|
|
state = signing_state
|
|
if state == 'SIGNED' || state == 'SIGNING' || state == 'QUEUED'
|
|
false
|
|
else
|
|
enqueue
|
|
true
|
|
end
|
|
end
|
|
|
|
def ready?
|
|
self.signed && self.url.present?
|
|
end
|
|
|
|
# returns easy to digest state field
|
|
# SIGNED - the package is ready to be downloaded
|
|
# ERROR - the package was built unsuccessfully
|
|
# SIGNING_TIMEOUT - the package was kicked off to be signed, but it seems to have hung
|
|
# SIGNING - the package is currently signing
|
|
# QUEUED_TIMEOUT - the package signing job (JamTrackBuilder) was queued, but never executed
|
|
# QUEUED - the package is queued to sign
|
|
# QUIET - the jam_track_right exists, but no job has been kicked off; a job needs to be enqueued
|
|
def signing_state
|
|
state = nil
|
|
|
|
if signed
|
|
state = 'SIGNED'
|
|
elsif signing_started_at
|
|
# the maximum amount of time the packaging job can take is 10 seconds * num steps. For a 10 track song, this will be 110 seconds. It's a bit long.
|
|
# TODO: base this on the settings of the mix
|
|
signing_job_run_max_time = 100 # packaging_steps * 10
|
|
if Time.now - signing_started_at > signing_job_run_max_time
|
|
state = 'SIGNING_TIMEOUT'
|
|
elsif Time.now - last_step_at > APP_CONFIG.signing_step_max_time
|
|
state = 'SIGNING_TIMEOUT'
|
|
else
|
|
state = 'SIGNING'
|
|
end
|
|
elsif signing_queued_at
|
|
if Time.now - signing_queued_at > APP_CONFIG.signing_job_queue_max_time
|
|
state = 'QUEUED_TIMEOUT'
|
|
else
|
|
state = 'QUEUED'
|
|
end
|
|
elsif error_count > 0
|
|
state = 'ERROR'
|
|
else
|
|
state = 'QUIET' # needs to be poked to go build
|
|
end
|
|
state
|
|
end
|
|
|
|
def signed?
|
|
signed
|
|
end
|
|
|
|
def update_download_count(count=1)
|
|
self.download_count = self.download_count + count
|
|
self.last_downloaded_at = Time.now
|
|
|
|
if self.signed
|
|
self.downloaded_since_sign = true
|
|
end
|
|
end
|
|
|
|
|
|
def self.stats
|
|
stats = {}
|
|
|
|
result = JamTrackMixdownPackage.select('count(id) as total, count(CASE WHEN signing THEN 1 ELSE NULL END) as signing_count').first
|
|
|
|
stats['count'] = result['total'].to_i
|
|
stats['signing_count'] = result['signing_count'].to_i
|
|
stats
|
|
end
|
|
|
|
|
|
def delete_s3_files
|
|
s3_manager.delete(self.url) if self.url && s3_manager.exists?(self.url)
|
|
end
|
|
|
|
end
|
|
end
|
|
|