active_encode 0.1.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -2
- data/Gemfile +35 -0
- data/README.md +15 -14
- data/Rakefile +5 -10
- data/active_encode.gemspec +8 -5
- data/app/jobs/active_encode/polling_job.rb +20 -0
- data/app/models/active_encode/encode_record.rb +5 -0
- data/db/migrate/20180822021048_create_active_encode_encode_records.rb +13 -0
- data/lib/active_encode.rb +1 -0
- data/lib/active_encode/base.rb +6 -2
- data/lib/active_encode/callbacks.rb +18 -35
- data/lib/active_encode/core.rb +64 -20
- data/lib/active_encode/engine.rb +7 -0
- data/lib/active_encode/engine_adapter.rb +2 -2
- data/lib/active_encode/engine_adapters/active_job_adapter.rb +7 -3
- data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +15 -15
- data/lib/active_encode/engine_adapters/inline_adapter.rb +6 -1
- data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +18 -18
- data/lib/active_encode/engine_adapters/shingoncoder_adapter.rb +13 -9
- data/lib/active_encode/engine_adapters/test_adapter.rb +19 -12
- data/lib/active_encode/engine_adapters/zencoder_adapter.rb +10 -10
- data/lib/active_encode/global_id.rb +16 -0
- data/lib/active_encode/input.rb +9 -0
- data/lib/active_encode/output.rb +9 -0
- data/lib/active_encode/persistence.rb +45 -0
- data/lib/active_encode/polling.rb +24 -0
- data/lib/active_encode/status.rb +2 -6
- data/lib/active_encode/technical_metadata.rb +16 -1
- data/lib/active_encode/version.rb +1 -1
- data/spec/fixtures/elastic_transcoder/job_canceled.json +1 -1
- data/spec/fixtures/elastic_transcoder/job_completed.json +1 -1
- data/spec/fixtures/elastic_transcoder/job_created.json +1 -1
- data/spec/fixtures/elastic_transcoder/job_failed.json +1 -1
- data/spec/fixtures/elastic_transcoder/job_progressing.json +1 -1
- data/spec/integration/elastic_transcoder_adapter_spec.rb +87 -167
- data/spec/integration/matterhorn_adapter_spec.rb +34 -79
- data/spec/integration/shingoncoder_adapter_spec.rb +1 -1
- data/spec/integration/zencoder_adapter_spec.rb +1 -1
- data/spec/rails_helper.rb +22 -0
- data/spec/shared_specs/engine_adapter_specs.rb +124 -0
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +15 -0
- data/spec/units/callbacks_spec.rb +16 -17
- data/spec/units/core_spec.rb +121 -2
- data/spec/units/engine_adapter_spec.rb +0 -12
- data/spec/units/global_id_spec.rb +49 -0
- data/spec/units/input_spec.rb +12 -0
- data/spec/units/output_spec.rb +12 -0
- data/spec/units/persistence_spec.rb +57 -0
- data/spec/units/polling_job_spec.rb +86 -0
- data/spec/units/polling_spec.rb +22 -0
- data/spec/units/status_spec.rb +21 -2
- metadata +89 -20
@@ -10,7 +10,7 @@ module ActiveEncode
|
|
10
10
|
|
11
11
|
included do
|
12
12
|
class_attribute :_engine_adapter, instance_accessor: false, instance_predicate: false
|
13
|
-
self.engine_adapter = :
|
13
|
+
self.engine_adapter = :test
|
14
14
|
end
|
15
15
|
|
16
16
|
# Includes the setter method for changing the active engine adapter.
|
@@ -38,7 +38,7 @@ module ActiveEncode
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
ENGINE_ADAPTER_METHODS = %i[create find
|
41
|
+
ENGINE_ADAPTER_METHODS = %i[create find cancel].freeze
|
42
42
|
|
43
43
|
def engine_adapter?(object)
|
44
44
|
ENGINE_ADAPTER_METHODS.all? { |meth| object.respond_to?(meth) }
|
@@ -1,13 +1,17 @@
|
|
1
1
|
module ActiveEncode
|
2
2
|
module EngineAdapters
|
3
3
|
class ActiveJobAdapter
|
4
|
-
def
|
4
|
+
def initialize
|
5
|
+
ActiveSupport::Deprecation.warn("The ActiveJobAdapter is deprecated and will be removed in ActiveEncode 0.3.")
|
6
|
+
end
|
5
7
|
|
6
|
-
def
|
8
|
+
def create(_input_url, _options) end
|
9
|
+
|
10
|
+
def find(_id) end
|
7
11
|
|
8
12
|
def list(*_filters) end
|
9
13
|
|
10
|
-
def cancel(
|
14
|
+
def cancel(_id end
|
11
15
|
|
12
16
|
def purge(_encode) end
|
13
17
|
|
@@ -2,20 +2,20 @@ module ActiveEncode
|
|
2
2
|
module EngineAdapters
|
3
3
|
class ElasticTranscoderAdapter
|
4
4
|
# TODO: add a stub for an input helper (supplied by an initializer) that transforms encode.input into a zencoder accepted url
|
5
|
-
def create(
|
5
|
+
def create(input_url, options = {})
|
6
6
|
job = client.create_job(
|
7
|
-
input: { key:
|
8
|
-
pipeline_id:
|
9
|
-
output_key_prefix:
|
10
|
-
outputs:
|
11
|
-
user_metadata:
|
7
|
+
input: { key: input_url },
|
8
|
+
pipeline_id: options[:pipeline_id],
|
9
|
+
output_key_prefix: options[:output_key_prefix],
|
10
|
+
outputs: options[:outputs],
|
11
|
+
user_metadata: options[:user_metadata]
|
12
12
|
).job
|
13
13
|
|
14
|
-
build_encode(
|
14
|
+
build_encode(job)
|
15
15
|
end
|
16
16
|
|
17
17
|
def find(id, opts = {})
|
18
|
-
build_encode(get_job_details(id)
|
18
|
+
build_encode(get_job_details(id))
|
19
19
|
end
|
20
20
|
|
21
21
|
# TODO: implement list_jobs_by_pipeline and list_jobs_by_status
|
@@ -24,9 +24,9 @@ module ActiveEncode
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Can only cancel jobs with status = "Submitted"
|
27
|
-
def cancel(
|
28
|
-
response = client.cancel_job(id:
|
29
|
-
build_encode(get_job_details(
|
27
|
+
def cancel(id)
|
28
|
+
response = client.cancel_job(id: id)
|
29
|
+
build_encode(get_job_details(id)) if response.successful?
|
30
30
|
end
|
31
31
|
|
32
32
|
def purge(_encode)
|
@@ -48,9 +48,9 @@ module ActiveEncode
|
|
48
48
|
client.read_job(id: job_id).job
|
49
49
|
end
|
50
50
|
|
51
|
-
def build_encode(job
|
51
|
+
def build_encode(job)
|
52
52
|
return nil if job.nil?
|
53
|
-
encode =
|
53
|
+
encode = ActiveEncode::Base.new(convert_input(job), convert_options(job))
|
54
54
|
encode.id = job.id
|
55
55
|
encode.state = convert_state(job)
|
56
56
|
encode.current_operations = convert_current_operations(job)
|
@@ -66,7 +66,7 @@ module ActiveEncode
|
|
66
66
|
|
67
67
|
def convert_time(time_millis)
|
68
68
|
return nil if time_millis.nil?
|
69
|
-
Time.at(time_millis / 1000)
|
69
|
+
Time.at(time_millis / 1000)
|
70
70
|
end
|
71
71
|
|
72
72
|
def convert_state(job)
|
@@ -91,7 +91,7 @@ module ActiveEncode
|
|
91
91
|
case job.status
|
92
92
|
when "Submitted"
|
93
93
|
10
|
94
|
-
when "Progressing"
|
94
|
+
when "Progressing", "Canceled", "Error"
|
95
95
|
50
|
96
96
|
when "Complete"
|
97
97
|
100
|
@@ -4,7 +4,12 @@ module ActiveEncode
|
|
4
4
|
class_attribute :encodes, instance_accessor: false, instance_predicate: false
|
5
5
|
InlineAdapter.encodes ||= {}
|
6
6
|
|
7
|
-
def
|
7
|
+
def initialize
|
8
|
+
ActiveSupport::Deprecation.warn("The InlineAdapter is deprecated and will be removed in ActiveEncode 0.3.")
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(input_url, options = {})
|
12
|
+
encode = ActiveEncode::Base.new(input_url, options)
|
8
13
|
encode.id = SecureRandom.uuid
|
9
14
|
self.class.encodes[encode.id] = encode
|
10
15
|
# start encode
|
@@ -5,27 +5,27 @@ module ActiveEncode
|
|
5
5
|
class MatterhornAdapter
|
6
6
|
DEFAULT_ARGS = { 'flavor' => 'presenter/source' }.freeze
|
7
7
|
|
8
|
-
def create(
|
9
|
-
workflow_id =
|
10
|
-
workflow_om = if encode.input.is_a? Hash
|
11
|
-
|
12
|
-
|
13
|
-
Rubyhorn.client.addMediaPackageWithUrl(DEFAULT_ARGS.merge('workflow' => workflow_id, 'url' =>
|
14
|
-
end
|
15
|
-
build_encode(get_workflow(workflow_om)
|
8
|
+
def create(input_url, options = {})
|
9
|
+
workflow_id = options[:preset] || "full"
|
10
|
+
# workflow_om = if encode.input.is_a? Hash
|
11
|
+
# create_multiple_files(encode.input, workflow_id)
|
12
|
+
# else
|
13
|
+
workflow_om = Rubyhorn.client.addMediaPackageWithUrl(DEFAULT_ARGS.merge('workflow' => workflow_id, 'url' => input_url, 'filename' => File.basename(input_url), 'title' => File.basename(input_url)))
|
14
|
+
# end
|
15
|
+
build_encode(get_workflow(workflow_om))
|
16
16
|
end
|
17
17
|
|
18
18
|
def find(id, opts = {})
|
19
|
-
build_encode(fetch_workflow(id)
|
19
|
+
build_encode(fetch_workflow(id))
|
20
20
|
end
|
21
21
|
|
22
22
|
def list(*_filters)
|
23
23
|
raise NotImplementedError # TODO: implement this
|
24
24
|
end
|
25
25
|
|
26
|
-
def cancel(
|
27
|
-
workflow_om = Rubyhorn.client.stop(
|
28
|
-
build_encode(get_workflow(workflow_om)
|
26
|
+
def cancel(id)
|
27
|
+
workflow_om = Rubyhorn.client.stop(id)
|
28
|
+
build_encode(get_workflow(workflow_om))
|
29
29
|
end
|
30
30
|
|
31
31
|
def purge(encode)
|
@@ -41,7 +41,7 @@ module ActiveEncode
|
|
41
41
|
end
|
42
42
|
purged_workflow = purge_outputs(get_workflow(workflow_om))
|
43
43
|
# Rubyhorn.client.delete_instance(encode.id) #Delete is not working so workflow instances can always be retrieved later!
|
44
|
-
build_encode(purged_workflow
|
44
|
+
build_encode(purged_workflow)
|
45
45
|
end
|
46
46
|
|
47
47
|
def remove_output(encode, output_id)
|
@@ -79,9 +79,9 @@ module ActiveEncode
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
def build_encode(workflow
|
82
|
+
def build_encode(workflow)
|
83
83
|
return nil if workflow.nil?
|
84
|
-
encode =
|
84
|
+
encode = ActiveEncode::Base.new(convert_input(workflow), convert_options(workflow))
|
85
85
|
encode.id = convert_id(workflow)
|
86
86
|
encode.state = convert_state(workflow)
|
87
87
|
encode.current_operations = convert_current_operations(workflow)
|
@@ -146,17 +146,17 @@ module ActiveEncode
|
|
146
146
|
|
147
147
|
def convert_created_at(workflow)
|
148
148
|
created_at = workflow.xpath('mediapackage/@start').last.to_s
|
149
|
-
created_at.present? ? Time.parse(created_at)
|
149
|
+
created_at.present? ? Time.parse(created_at) : nil
|
150
150
|
end
|
151
151
|
|
152
152
|
def convert_updated_at(workflow)
|
153
153
|
updated_at = workflow.xpath('//operation[@state!="INSTANTIATED"]/completed/text()').last.to_s
|
154
|
-
updated_at.present? ? Time.strptime(updated_at, "%Q")
|
154
|
+
updated_at.present? ? Time.strptime(updated_at, "%Q") : nil
|
155
155
|
end
|
156
156
|
|
157
157
|
def convert_finished_at(workflow)
|
158
158
|
finished_at = workflow.xpath('//operation[@state!="INSTANTIATED"]/completed/text()').last.to_s
|
159
|
-
finished_at.present? ? Time.strptime(finished_at, "%Q")
|
159
|
+
finished_at.present? ? Time.strptime(finished_at, "%Q") : nil
|
160
160
|
end
|
161
161
|
|
162
162
|
def convert_options(workflow)
|
@@ -4,23 +4,27 @@ require 'active_support/core_ext'
|
|
4
4
|
module ActiveEncode
|
5
5
|
module EngineAdapters
|
6
6
|
class ShingoncoderAdapter < ZencoderAdapter
|
7
|
+
def initialize
|
8
|
+
ActiveSupport::Deprecation.warn("The ShingoncoderAdapter is deprecated and will be removed in ActiveEncode 0.3.")
|
9
|
+
end
|
10
|
+
|
7
11
|
# @param [ActiveEncode::Base] encode
|
8
|
-
def create(
|
9
|
-
response = Shingoncoder::Job.create(input:
|
10
|
-
build_encode(job_details(response.body["id"])
|
12
|
+
def create(input_url, options = {})
|
13
|
+
response = Shingoncoder::Job.create(input: input_url)
|
14
|
+
build_encode(job_details(response.body["id"]))
|
11
15
|
end
|
12
16
|
|
13
17
|
# @param [Fixnum] id
|
14
18
|
# @param [Hash] opts
|
15
19
|
# @option opts :cast the class to cast the encoding job to.
|
16
20
|
def find(id, opts = {})
|
17
|
-
build_encode(job_details(id)
|
21
|
+
build_encode(job_details(id))
|
18
22
|
end
|
19
23
|
|
20
24
|
# @param [ActiveEncode::Base] encode
|
21
|
-
def cancel(
|
22
|
-
response = Shingoncoder::Job.cancel(
|
23
|
-
build_encode(job_details(
|
25
|
+
def cancel(id)
|
26
|
+
response = Shingoncoder::Job.cancel(id)
|
27
|
+
build_encode(job_details(id)) if response.success?
|
24
28
|
end
|
25
29
|
|
26
30
|
private
|
@@ -38,9 +42,9 @@ module ActiveEncode
|
|
38
42
|
|
39
43
|
# @param [Shingoncoder::Response] job_details
|
40
44
|
# @param [Class] cast the class of object to instantiate and return
|
41
|
-
def build_encode(job_details
|
45
|
+
def build_encode(job_details)
|
42
46
|
return nil if job_details.nil?
|
43
|
-
encode =
|
47
|
+
encode = ActiveEncode::Base.new(convert_input(job_details), convert_options(job_details))
|
44
48
|
encode.id = job_details.body["job"]["id"].to_s
|
45
49
|
encode.state = convert_state(job_details)
|
46
50
|
progress = job_progress(encode.id)
|
@@ -5,25 +5,32 @@ module ActiveEncode
|
|
5
5
|
@encodes = {}
|
6
6
|
end
|
7
7
|
|
8
|
-
def create(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
def create(input_url, options = {})
|
9
|
+
new_encode = ActiveEncode::Base.new(input_url, options)
|
10
|
+
new_encode.id = SecureRandom.uuid
|
11
|
+
new_encode.state = :running
|
12
|
+
new_encode.created_at = Time.now
|
13
|
+
new_encode.updated_at = Time.now
|
14
|
+
@encodes[new_encode.id] = new_encode
|
15
|
+
new_encode
|
13
16
|
end
|
14
17
|
|
15
18
|
def find(id, _opts = {})
|
16
|
-
@encodes[id]
|
19
|
+
new_encode = @encodes[id]
|
20
|
+
# Update the updated_at time to simulate changes
|
21
|
+
new_encode.updated_at = Time.now
|
22
|
+
new_encode
|
17
23
|
end
|
18
24
|
|
19
|
-
def
|
20
|
-
|
25
|
+
def cancel(id)
|
26
|
+
new_encode = @encodes[id]
|
27
|
+
new_encode.state = :cancelled
|
28
|
+
new_encode.updated_at = Time.now
|
29
|
+
new_encode
|
21
30
|
end
|
22
31
|
|
23
|
-
def
|
24
|
-
|
25
|
-
e.state = :cancelled
|
26
|
-
e
|
32
|
+
def list(*_filters)
|
33
|
+
raise NotImplementedError
|
27
34
|
end
|
28
35
|
|
29
36
|
def purge(encode)
|
@@ -1,23 +1,23 @@
|
|
1
1
|
module ActiveEncode
|
2
2
|
module EngineAdapters
|
3
3
|
class ZencoderAdapter
|
4
|
-
# TODO: add a stub for an input helper (supplied by an initializer) that transforms encode.input into a zencoder accepted url
|
5
|
-
def create(
|
6
|
-
response = Zencoder::Job.create(input:
|
7
|
-
build_encode(get_job_details(response.body["id"])
|
4
|
+
# TODO: add a stub for an input helper (supplied by an initializer) that transforms encode.input.url into a zencoder accepted url
|
5
|
+
def create(input_url, options = {})
|
6
|
+
response = Zencoder::Job.create(input: input_url.to_s)
|
7
|
+
build_encode(get_job_details(response.body["id"]))
|
8
8
|
end
|
9
9
|
|
10
10
|
def find(id, opts = {})
|
11
|
-
build_encode(get_job_details(id)
|
11
|
+
build_encode(get_job_details(id))
|
12
12
|
end
|
13
13
|
|
14
14
|
def list(*_filters)
|
15
15
|
raise NotImplementedError
|
16
16
|
end
|
17
17
|
|
18
|
-
def cancel(
|
19
|
-
response = Zencoder::Job.cancel(
|
20
|
-
build_encode(get_job_details(
|
18
|
+
def cancel(id)
|
19
|
+
response = Zencoder::Job.cancel(id)
|
20
|
+
build_encode(get_job_details(id)) if response.success?
|
21
21
|
end
|
22
22
|
|
23
23
|
def purge(_encode)
|
@@ -38,9 +38,9 @@ module ActiveEncode
|
|
38
38
|
Zencoder::Job.progress(job_id)
|
39
39
|
end
|
40
40
|
|
41
|
-
def build_encode(job_details
|
41
|
+
def build_encode(job_details)
|
42
42
|
return nil if job_details.nil?
|
43
|
-
encode =
|
43
|
+
encode = ActiveEncode::Base.new(convert_input(job_details), convert_options(job_details))
|
44
44
|
encode.id = job_details.body["job"]["id"].to_s
|
45
45
|
encode.state = convert_state(job_details)
|
46
46
|
job_progress = get_job_progress(encode.id)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'globalid'
|
2
|
+
|
3
|
+
module ActiveEncode
|
4
|
+
module GlobalID
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include ::GlobalID::Identification
|
7
|
+
|
8
|
+
def ==(other)
|
9
|
+
other.is_a?(ActiveEncode::Base) && to_global_id == other.to_global_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_global_id(options = {})
|
13
|
+
super(app: 'ActiveEncode')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module ActiveEncode
|
4
|
+
module Persistence
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
after_find do |encode|
|
9
|
+
persist(persistence_model_attributes(encode))
|
10
|
+
end
|
11
|
+
|
12
|
+
after_create do |encode|
|
13
|
+
persist(persistence_model_attributes(encode))
|
14
|
+
end
|
15
|
+
|
16
|
+
after_cancel do |encode|
|
17
|
+
persist(persistence_model_attributes(encode))
|
18
|
+
end
|
19
|
+
|
20
|
+
after_reload do |encode|
|
21
|
+
persist(persistence_model_attributes(encode))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def persist(encode_attributes)
|
28
|
+
model = ActiveEncode::EncodeRecord.find_or_initialize_by(global_id: encode_attributes[:global_id])
|
29
|
+
model.update(encode_attributes) # Don't fail if persisting doesn't succeed?
|
30
|
+
end
|
31
|
+
|
32
|
+
def persistence_model_attributes(encode)
|
33
|
+
{
|
34
|
+
global_id: encode.to_global_id.to_s,
|
35
|
+
state: encode.state,
|
36
|
+
adapter: encode.class.engine_adapter.class.name,
|
37
|
+
title: encode.input.url.to_s,
|
38
|
+
# FIXME: Need to ensure that these values come through or else validations will fail
|
39
|
+
created_at: encode.created_at,
|
40
|
+
updated_at: encode.updated_at,
|
41
|
+
raw_object: encode.to_json
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_model/callbacks'
|
3
|
+
|
4
|
+
module ActiveEncode
|
5
|
+
module Polling
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
POLLING_WAIT_TIME = 10.seconds.freeze
|
9
|
+
|
10
|
+
CALLBACKS = [
|
11
|
+
:after_status_update, :after_error, :after_cancelled, :after_complete
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
included do
|
15
|
+
extend ActiveModel::Callbacks
|
16
|
+
|
17
|
+
define_model_callbacks :status_update, :error, :cancelled, :complete, only: :after
|
18
|
+
|
19
|
+
after_create do |encode|
|
20
|
+
ActiveEncode::PollingJob.set(wait: POLLING_WAIT_TIME).perform_later(encode)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|