active_encode 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -2
  4. data/Gemfile +35 -0
  5. data/README.md +15 -14
  6. data/Rakefile +5 -10
  7. data/active_encode.gemspec +8 -5
  8. data/app/jobs/active_encode/polling_job.rb +20 -0
  9. data/app/models/active_encode/encode_record.rb +5 -0
  10. data/db/migrate/20180822021048_create_active_encode_encode_records.rb +13 -0
  11. data/lib/active_encode.rb +1 -0
  12. data/lib/active_encode/base.rb +6 -2
  13. data/lib/active_encode/callbacks.rb +18 -35
  14. data/lib/active_encode/core.rb +64 -20
  15. data/lib/active_encode/engine.rb +7 -0
  16. data/lib/active_encode/engine_adapter.rb +2 -2
  17. data/lib/active_encode/engine_adapters/active_job_adapter.rb +7 -3
  18. data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +15 -15
  19. data/lib/active_encode/engine_adapters/inline_adapter.rb +6 -1
  20. data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +18 -18
  21. data/lib/active_encode/engine_adapters/shingoncoder_adapter.rb +13 -9
  22. data/lib/active_encode/engine_adapters/test_adapter.rb +19 -12
  23. data/lib/active_encode/engine_adapters/zencoder_adapter.rb +10 -10
  24. data/lib/active_encode/global_id.rb +16 -0
  25. data/lib/active_encode/input.rb +9 -0
  26. data/lib/active_encode/output.rb +9 -0
  27. data/lib/active_encode/persistence.rb +45 -0
  28. data/lib/active_encode/polling.rb +24 -0
  29. data/lib/active_encode/status.rb +2 -6
  30. data/lib/active_encode/technical_metadata.rb +16 -1
  31. data/lib/active_encode/version.rb +1 -1
  32. data/spec/fixtures/elastic_transcoder/job_canceled.json +1 -1
  33. data/spec/fixtures/elastic_transcoder/job_completed.json +1 -1
  34. data/spec/fixtures/elastic_transcoder/job_created.json +1 -1
  35. data/spec/fixtures/elastic_transcoder/job_failed.json +1 -1
  36. data/spec/fixtures/elastic_transcoder/job_progressing.json +1 -1
  37. data/spec/integration/elastic_transcoder_adapter_spec.rb +87 -167
  38. data/spec/integration/matterhorn_adapter_spec.rb +34 -79
  39. data/spec/integration/shingoncoder_adapter_spec.rb +1 -1
  40. data/spec/integration/zencoder_adapter_spec.rb +1 -1
  41. data/spec/rails_helper.rb +22 -0
  42. data/spec/shared_specs/engine_adapter_specs.rb +124 -0
  43. data/spec/test_app_templates/lib/generators/test_app_generator.rb +15 -0
  44. data/spec/units/callbacks_spec.rb +16 -17
  45. data/spec/units/core_spec.rb +121 -2
  46. data/spec/units/engine_adapter_spec.rb +0 -12
  47. data/spec/units/global_id_spec.rb +49 -0
  48. data/spec/units/input_spec.rb +12 -0
  49. data/spec/units/output_spec.rb +12 -0
  50. data/spec/units/persistence_spec.rb +57 -0
  51. data/spec/units/polling_job_spec.rb +86 -0
  52. data/spec/units/polling_spec.rb +22 -0
  53. data/spec/units/status_spec.rb +21 -2
  54. metadata +89 -20
@@ -7,17 +7,13 @@ module ActiveEncode
7
7
  included do
8
8
  # Current state of the encoding process
9
9
  attr_accessor :state
10
- attr_accessor :current_operations
11
- attr_accessor :percent_complete
12
10
  attr_accessor :errors
13
11
 
14
12
  attr_accessor :created_at
15
- attr_accessor :finished_at
16
13
  attr_accessor :updated_at
17
- end
18
14
 
19
- def created?
20
- !id.nil?
15
+ # @deprecated
16
+ attr_accessor :finished_at
21
17
  end
22
18
 
23
19
  def cancelled?
@@ -5,7 +5,22 @@ module ActiveEncode
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- attr_accessor :tech_metadata
8
+ attr_accessor :width
9
+ attr_accessor :height
10
+ attr_accessor :frame_rate
11
+
12
+ # In milliseconds
13
+ attr_accessor :duration
14
+
15
+ # In bytes
16
+ attr_accessor :file_size
17
+
18
+ attr_accessor :checksum
19
+
20
+ attr_accessor :audio_codec
21
+ attr_accessor :video_codec
22
+ attr_accessor :audio_bitrate
23
+ attr_accessor :video_bitrate
9
24
  end
10
25
  end
11
26
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveEncode
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.2'.freeze
3
3
  end
@@ -1 +1 @@
1
- {"id":"1471963629141-kmcocm","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Canceled","timing":{"submit_time_millis":1471963629189,"finish_time_millis":1471975185271}}
1
+ {"id":"cancelled-id","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Canceled","timing":{"submit_time_millis":1471963629189,"finish_time_millis":1471975185271}}
@@ -1 +1 @@
1
- {"id":"1471963629141-kmcocm","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Complete","timing":{"submit_time_millis":1471963629189,"start_time_millis":1471975169865,"finish_time_millis":1471975185271}}
1
+ {"id":"completed-id","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Complete","timing":{"submit_time_millis":1471963629189,"start_time_millis":1471975169865,"finish_time_millis":1471975185271}}
@@ -1 +1 @@
1
- {"id":"1471963629141-kmcocm","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","input":{"key":"somefile.mp4"},"output":{"id":"1","key":"hlsAudio/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a","preset_id":"1351620000001-200071","segment_duration":"2.0","status":"Submitted","watermarks":[]},"output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Submitted","timing":{"submit_time_millis":1471963629189}}
1
+ {"id":"1471963629141-kmcocm-created","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","input":{"key":"somefile.mp4"},"output":{"id":"1","key":"hlsAudio/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a","preset_id":"1351620000001-200071","segment_duration":"2.0","status":"Submitted","watermarks":[]},"output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Submitted","timing":{"submit_time_millis":1471963629189}}
@@ -1 +1 @@
1
- {"id":"1471963629141-kmcocm","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Error","timing":{"submit_time_millis":1471963629189,"start_time_millis":1471975169865,"finish_time_millis":1471975185271}}
1
+ {"id":"failed-id","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Error","timing":{"submit_time_millis":1471963629189,"start_time_millis":1471975169865,"finish_time_millis":1471975185271}}
@@ -1 +1 @@
1
- {"id":"1471963629141-kmcocm","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Progressing","timing":{"submit_time_millis":1471963629189,"start_time_millis":1471975169865}}
1
+ {"id":"running-id","arn":"arn:aws:elastictranscoder:us-west-2:039358184980:job/1471963629141-kmcocm","pipeline_id":"1470797373927-1ukxrn","output_key_prefix":"elastic-transcoder-samples/output/hls/","playlists":[],"status":"Progressing","timing":{"submit_time_millis":1471963629189,"start_time_millis":1471975169865}}
@@ -1,207 +1,127 @@
1
1
  require 'spec_helper'
2
2
  require 'aws-sdk'
3
3
  require 'json'
4
+ require 'shared_specs/engine_adapter_specs'
4
5
 
5
6
  describe ActiveEncode::EngineAdapters::ElasticTranscoderAdapter do
6
- before(:all) do
7
+ around(:example) do |example|
8
+ # Setting this before each test works around a stubbing + memoization limitation
7
9
  ActiveEncode::Base.engine_adapter = :elastic_transcoder
8
- end
9
- after(:all) do
10
- ActiveEncode::Base.engine_adapter = :inline
10
+ example.run
11
+ ActiveEncode::Base.engine_adapter = :test
11
12
  end
12
13
 
13
- let(:client) { double(Aws::ElasticTranscoder::Client) }
14
+ let(:client) { Aws::ElasticTranscoder::Client.new(stub_responses: true) }
14
15
 
15
16
  before do
16
- allow_any_instance_of(ActiveEncode::EngineAdapters::ElasticTranscoderAdapter).to receive(:client).and_return(client)
17
- allow(client).to receive(:read_job).and_return(Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: job))
18
- allow(client).to receive(:create_job).and_return(Aws::ElasticTranscoder::Types::CreateJobResponse.new(job: job_created))
17
+ allow(Aws::ElasticTranscoder::Client).to receive(:new).and_return(client)
19
18
  end
20
19
 
21
- let(:job_created) do
20
+ let(:created_job) do
22
21
  j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_created.json'))
23
22
  j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
24
23
  j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_submitted.json')))]
25
- j
24
+
25
+ client.stub_responses(:create_job, Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j))
26
+
27
+ ActiveEncode::Base.create(
28
+ "somefile.mp4",
29
+ pipeline_id: "1471963629141-kmcocm",
30
+ output_key_prefix: "elastic-transcoder-samples/output/hls/",
31
+ outputs: [{
32
+ key: 'hls0400k/' + "e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a",
33
+ preset_id: "1351620000001-200050",
34
+ segment_duration: "2"
35
+ }])
36
+ end
37
+
38
+ let(:running_job) do
39
+ j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_progressing.json'))
40
+ j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_progressing.json')))
41
+ j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_progressing.json')))]
42
+
43
+ client.stub_responses(:read_job, Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j))
44
+ ActiveEncode::Base.find('running-id')
45
+ end
46
+
47
+ let(:canceled_job) do
48
+ j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_canceled.json'))
49
+ j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
50
+ j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_canceled.json')))]
51
+
52
+ client.stub_responses(:read_job, Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j))
53
+
54
+ ActiveEncode::Base.find('cancelled-id')
55
+ end
56
+
57
+ let(:cancelling_job) do
58
+ j1 = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_progressing.json'))
59
+ j1.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_progressing.json')))
60
+ j1.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_progressing.json')))]
61
+
62
+ j2 = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_canceled.json'))
63
+ j2.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
64
+ j2.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_canceled.json')))]
65
+
66
+ client.stub_responses(:read_job, [Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j1), Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j2)])
67
+
68
+ cancel_response = double(Aws::ElasticTranscoder::Types::CancelJobResponse)
69
+ allow(cancel_response).to receive(:successful?).and_return(true)
70
+ allow(client).to receive(:cancel_job).and_return(cancel_response)
71
+
72
+ ActiveEncode::Base.find('cancelled-id')
73
+ end
74
+
75
+ let(:completed_job) do
76
+ j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_completed.json'))
77
+ j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_completed.json')))
78
+ j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_completed.json')))]
79
+
80
+ client.stub_responses(:read_job, Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j))
81
+ ActiveEncode::Base.find('completed-id')
82
+ end
83
+
84
+ let(:failed_job) do
85
+ j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_failed.json'))
86
+ j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
87
+ j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_failed.json')))]
88
+
89
+ client.stub_responses(:read_job, Aws::ElasticTranscoder::Types::ReadJobResponse.new(job: j))
90
+ ActiveEncode::Base.find('failed-id')
26
91
  end
27
92
 
93
+ let(:completed_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", :width=>400, :height=>224, :video_framerate=>"25", :file_size=>6901104, :duration=>"117353", :segment_duration=> "2.0"}] }
94
+ let(:completed_tech_metadata) { {:width=>1280, :height=>720, :video_framerate=>"25", :file_size=>21069678, :duration=>"117312"} }
95
+ let(:failed_tech_metadata) { {} }
96
+
97
+ it_behaves_like "an ActiveEncode::EngineAdapter"
98
+
28
99
  describe "#create" do
29
- let(:job) { job_created }
30
100
  let(:create_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", segment_duration: "2.0"}] }
31
101
 
32
- subject { ActiveEncode::Base.create(
33
- "somefile.mp4",
34
- pipeline_id: "1471963629141-kmcocm",
35
- output_key_prefix: "elastic-transcoder-samples/output/hls/",
36
- outputs: [{
37
- key: 'hls0400k/' + "e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a",
38
- preset_id: "1351620000001-200050",
39
- segment_duration: "2"
40
- }])
41
- }
42
-
43
- it { is_expected.to be_a ActiveEncode::Base }
44
- its(:id) { is_expected.not_to be_empty }
102
+ subject { created_job }
103
+
45
104
  it { is_expected.to be_running }
46
105
  its(:output) { is_expected.to eq create_output }
47
106
  its(:current_operations) { is_expected.to be_empty }
48
- its(:percent_complete) { is_expected.to eq 10 }
49
- its(:errors) { is_expected.to be_empty }
50
- its(:created_at) { is_expected.to be_the_same_time_as '2016-08-23T10:47:09-04:00' }
51
- its(:updated_at) { is_expected.to be_nil }
52
- its(:finished_at) { is_expected.to be_nil }
53
- its(:tech_metadata) { is_expected.to be_empty }
54
107
  end
55
108
 
56
109
  describe "#find" do
57
110
  context "a running encode" do
58
- let(:job) do
59
- j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_progressing.json'))
60
- j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_progressing.json')))
61
- j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_progressing.json')))]
62
- j
63
- end
64
-
65
111
  let(:running_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", :segment_duration=>"2.0"}] }
66
112
  let(:running_tech_metadata) { {:width=>1280, :height=>720, :video_framerate=>"25", :file_size=>21069678, :duration=>"117312"} }
67
113
 
68
- subject { ActiveEncode::Base.find('1471963629141-kmcocm') }
69
- it { is_expected.to be_a ActiveEncode::Base }
70
- its(:id) { is_expected.to eq '1471963629141-kmcocm' }
71
- it { is_expected.to be_running }
114
+ subject { running_job }
115
+
72
116
  its(:output) { is_expected.to eq running_output }
73
117
  its(:current_operations) { is_expected.to be_empty }
74
- its(:percent_complete) { is_expected.to eq 50 }
75
- its(:errors) { is_expected.to be_empty }
76
- its(:created_at) { is_expected.to be_the_same_time_as '2016-08-23T10:47:09-04:00' }
77
- its(:updated_at) { is_expected.to be_the_same_time_as '2016-08-23T13:59:29-04:00' }
78
- its(:finished_at) { is_expected.to be_nil }
79
118
  its(:tech_metadata) { is_expected.to eq running_tech_metadata }
80
119
  end
81
120
 
82
121
  context "a canceled encode" do
83
- let(:job) do
84
- j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_canceled.json'))
85
- j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
86
- j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_canceled.json')))]
87
- j
88
- end
89
-
90
- subject { ActiveEncode::Base.find('1471963629141-kmcocm') }
91
- it { is_expected.to be_a ActiveEncode::Base }
92
- its(:id) { is_expected.to eq '1471963629141-kmcocm' }
93
- it { is_expected.to be_cancelled }
94
- its(:current_operations) { is_expected.to be_empty }
95
- its(:percent_complete) { is_expected.to eq 0 }
96
- its(:errors) { is_expected.to be_empty }
97
- its(:created_at) { is_expected.to be_the_same_time_as '2016-08-23T10:47:09-04:00' }
98
- its(:updated_at) { is_expected.to be_nil }
99
- its(:finished_at) { is_expected.to be_the_same_time_as '2016-08-23T13:59:45-04:00' }
100
- its(:tech_metadata) { is_expected.to be_empty }
101
- end
102
-
103
- context "a completed encode" do
104
- let(:job) do
105
- j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_completed.json'))
106
- j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_completed.json')))
107
- j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_completed.json')))]
108
- j
109
- end
110
- let(:completed_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", :width=>400, :height=>224, :video_framerate=>"25", :file_size=>6901104, :duration=>"117353", :segment_duration=> "2.0"}] }
111
- let(:completed_tech_metadata) { {:width=>1280, :height=>720, :video_framerate=>"25", :file_size=>21069678, :duration=>"117312"} }
112
-
113
- subject { ActiveEncode::Base.find('1471963629141-kmcocm') }
114
- it { is_expected.to be_a ActiveEncode::Base }
115
- its(:id) { is_expected.to eq '1471963629141-kmcocm' }
116
- it { is_expected.to be_completed }
117
- its(:output) { is_expected.to eq completed_output }
118
- its(:current_operations) { is_expected.to be_empty }
119
- its(:percent_complete) { is_expected.to eq 100 }
120
- its(:errors) { is_expected.to be_empty }
121
- its(:created_at) { is_expected.to be_the_same_time_as '2016-08-23T10:47:09-04:00' }
122
- its(:updated_at) { is_expected.to be_the_same_time_as '2016-08-23T13:59:29-04:00' }
123
- its(:finished_at) { is_expected.to be_the_same_time_as '2016-08-23T13:59:45-04:00' }
124
- its(:tech_metadata) { is_expected.to eq completed_tech_metadata }
125
- end
122
+ subject { canceled_job }
126
123
 
127
- context "a failed encode" do
128
- let(:job) do
129
- j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_failed.json'))
130
- j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
131
- j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_failed.json')))]
132
- j
133
- end
134
- let(:failed_tech_metadata) { {} }
135
-
136
- subject { ActiveEncode::Base.find('1471963629141-kmcocm') }
137
- it { is_expected.to be_a ActiveEncode::Base }
138
- its(:id) { is_expected.to eq '1471963629141-kmcocm' }
139
- it { is_expected.to be_failed }
140
- its(:current_operations) { is_expected.to be_empty }
141
- its(:percent_complete) { is_expected.to eq 0 }
142
- its(:errors) { is_expected.not_to be_empty }
143
- its(:created_at) { is_expected.to be_the_same_time_as '2016-08-23T10:47:09-04:00' }
144
- its(:updated_at) { is_expected.to be_the_same_time_as '2016-08-23T13:59:29-04:00' }
145
- its(:finished_at) { is_expected.to be_the_same_time_as '2016-08-23T13:59:45-04:00' }
146
- its(:tech_metadata) { is_expected.to be_empty }
147
- end
148
- end
149
-
150
- describe "#cancel!" do
151
- before do
152
- allow(client).to receive(:cancel_job).and_return(cancel_response)
153
- end
154
-
155
- let(:cancel_response) do
156
- res = double(Aws::ElasticTranscoder::Types::CancelJobResponse)
157
- allow(res).to receive(:successful?).and_return(true)
158
- res
159
- end
160
-
161
- let(:job) do
162
- j = Aws::ElasticTranscoder::Types::Job.new JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_canceled.json'))
163
- j.input = Aws::ElasticTranscoder::Types::JobInput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/input_generic.json')))
164
- j.outputs = [ Aws::ElasticTranscoder::Types::JobOutput.new(JSON.parse(File.read('spec/fixtures/elastic_transcoder/output_canceled.json')))]
165
- j
124
+ its(:updated_at) { is_expected.to be_nil }
166
125
  end
167
-
168
- let(:encode) { ActiveEncode::Base.create(
169
- "somefile.mp4",
170
- pipeline_id: "1471963629141-kmcocm",
171
- output_key_prefix: "elastic-transcoder-samples/output/hls/",
172
- outputs: [{
173
- key: 'hls0400k/' + "e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a",
174
- preset_id: "1351620000001-200050",
175
- segment_duration: "2"
176
- }]) }
177
- subject { encode.cancel! }
178
- it { is_expected.to be_a ActiveEncode::Base }
179
- its(:id) { is_expected.to eq '1471963629141-kmcocm' }
180
- it { is_expected.to be_cancelled }
181
126
  end
182
-
183
- # describe "reload" do
184
- # before do
185
- # allow(ElasticTranscoder::Job).to receive(:details).and_return(details_response)
186
- # allow(ElasticTranscoder::Job).to receive(:progress).and_return(progress_response)
187
- # end
188
- #
189
- # let(:details_response) { ElasticTranscoder::Response.new(body: JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_details_running.json'))) }
190
- # let(:progress_response) { ElasticTranscoder::Response.new(body: JSON.parse(File.read('spec/fixtures/elastic_transcoder/job_progress_running.json'))) }
191
- # let(:reload_output) { [{ id: "510582971", url: "https://elastic_transcoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150609/48a6907086c012f68b9ca43461280515/1726d7ec3e24f2171bd07b2abb807b6c.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=vSvlxU94wlQLEbpG3Zs8ibp4MoY%3D&Expires=1433953106", label: nil }] }
192
- # let(:reload_tech_metadata) { { audio_bitrate: "52", audio_codec: "aac", audio_channels: "2", duration: "57992", mime_type: "mpeg4", video_framerate: "29.97", height: "240", video_bitrate: "535", video_codec: "h264", width: "320" } }
193
- #
194
- # subject { ActiveEncode::Base.find('166019107').reload }
195
- # it { is_expected.to be_a ActiveEncode::Base }
196
- # its(:id) { is_expected.to eq '166019107' }
197
- # it { is_expected.to be_running }
198
- # its(:output) { is_expected.to eq reload_output }
199
- # its(:current_operations) { is_expected.to be_empty }
200
- # its(:percent_complete) { is_expected.to eq 30.0 }
201
- # its(:errors) { is_expected.to be_empty }
202
- # its(:created_at) { is_expected.to eq '2015-06-09T16:18:26Z' }
203
- # its(:updated_at) { is_expected.to eq '2015-06-09T16:18:28Z' }
204
- # its(:finished_at) { is_expected.to be_nil }
205
- # its(:tech_metadata) { is_expected.to eq reload_tech_metadata }
206
- # end
207
127
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'rubyhorn'
3
+ require 'shared_specs/engine_adapter_specs'
3
4
 
4
5
  describe ActiveEncode::EngineAdapters::MatterhornAdapter do
5
6
  before(:all) do
@@ -7,119 +8,79 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
7
8
  ActiveEncode::Base.engine_adapter = :matterhorn
8
9
  end
9
10
  after(:all) do
10
- ActiveEncode::Base.engine_adapter = :inline
11
+ ActiveEncode::Base.engine_adapter = :test
11
12
  end
12
13
 
13
14
  before do
14
15
  # Stub out all Matterhorn interactions
15
16
  allow(Rubyhorn).to receive(:client).and_return(double("Rubyhorn::MatterhornClient"))
16
17
  allow(Rubyhorn.client).to receive(:addMediaPackageWithUrl).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/create_response.xml')))
18
+ allow(Rubyhorn.client).to receive(:instance_xml).with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
19
+ allow(Rubyhorn.client).to receive(:instance_xml).with('cancelled-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
20
+ allow(Rubyhorn.client).to receive(:instance_xml).with('completed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/completed_response.xml')))
21
+ allow(Rubyhorn.client).to receive(:instance_xml).with('failed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/failed_response.xml')))
22
+ allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
17
23
  end
18
24
 
19
25
  let(:file) { "file://#{File.absolute_path('spec/fixtures/Bars_512kb.mp4')}" }
26
+ let(:created_job) { ActiveEncode::Base.create(file) }
27
+ let(:running_job) { ActiveEncode::Base.find('running-id') }
28
+ let(:canceled_job) { ActiveEncode::Base.find('cancelled-id') }
29
+ let(:cancelling_job) { ActiveEncode::Base.find('running-id')}
30
+ let(:completed_job) { ActiveEncode::Base.find('completed-id') }
31
+ let(:failed_job) { ActiveEncode::Base.find('failed-id') }
32
+
33
+ let(:completed_output) { [{ id: "track-7", mime_type: "video/mp4", checksum: "77de9765545ef63d2c21f7557ead6176", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "2000000.0", video_framerate: "30.0", width: "1308", height: "720", url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/b09c765f-b64e-4725-a863-736af66b688c/videoshort.mp4", label: "quality-high" }, { id: "track-8", mime_type: "video/mp4", checksum: "10e13cf51bf8a973011eec6a17ea47ff", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "500000.0", video_framerate: "30.0", width: "654", height: "360", url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/8d5cd8a9-ad0e-484a-96f0-05e26a84a8f0/videoshort.mp4", label: "quality-low" }, { id: "track-9", mime_type: "video/mp4", checksum: "f2b16a2606dc76cb53c7017f0e166204", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "1000000.0", video_framerate: "30.0", width: "872", height: "480", url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/0f81d426-0e26-4496-8f58-c675c86e6f4e/videoshort.mp4", label: "quality-medium" }] }
34
+ let(:completed_tech_metadata) { { } }
35
+ let(:failed_tech_metadata) { { mime_type: "video/mp4", checksum: "7ae24368ccb7a6c6422a14ff73f33c9a", duration: "6314", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "171030.0", video_codec: "AVC", video_bitrate: "74477.0", video_framerate: "23.719", width: "200", height: "110" } }
36
+ let(:failed_errors) { "org.opencastproject.workflow.api.WorkflowOperationException: org.opencastproject.workflow.api.WorkflowOperationException: One of the encoding jobs did not complete successfully" }
37
+
38
+ # Enforce generic behavior
39
+ it_behaves_like "an ActiveEncode::EngineAdapter"
20
40
 
21
41
  describe "#create" do
22
- subject { ActiveEncode::Base.create(file) }
23
- it { is_expected.to be_a ActiveEncode::Base }
24
- its(:id) { is_expected.not_to be_empty }
25
- it { is_expected.to be_running }
42
+ subject { created_job }
43
+
26
44
  its(:output) { is_expected.to be_empty }
27
45
  its(:options) { is_expected.to include(preset: 'full') }
28
- its(:current_operations) { is_expected.to be_empty }
29
- its(:percent_complete) { is_expected.to eq 0 }
30
- its(:errors) { is_expected.to be_empty }
31
- its(:created_at) { is_expected.to eq '2015-04-24T15:44:47Z' }
32
- its(:updated_at) { is_expected.to be_nil }
33
- its(:finished_at) { is_expected.to be_nil }
34
- its(:tech_metadata) { is_expected.to be_empty }
35
46
  end
36
47
 
37
48
  describe "#find" do
38
49
  context "a running encode" do
39
- before do
40
- allow(Rubyhorn.client).to receive(:instance_xml).with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
41
- end
50
+ subject { running_job }
42
51
 
43
- subject { ActiveEncode::Base.find('running-id') }
44
- it { is_expected.to be_a ActiveEncode::Base }
45
- its(:id) { is_expected.to eq 'running-id' }
46
- it { is_expected.to be_running }
47
- its(:output) { is_expected.to be_empty }
48
52
  its(:options) { is_expected.to include(preset: 'full') }
53
+ its(:output) { is_expected.to be_empty }
49
54
  its(:current_operations) { is_expected.to include("Hold for workflow selection") }
50
- its(:percent_complete) { is_expected.to eq 0.43478260869565216 }
51
- its(:errors) { is_expected.to be_empty }
52
- its(:created_at) { is_expected.to eq '2015-04-20T17:58:43Z' }
53
- its(:updated_at) { is_expected.to eq '2015-04-21T18:38:50Z' }
54
- its(:finished_at) { is_expected.to be_nil }
55
55
  its(:tech_metadata) { is_expected.to be_empty }
56
56
  end
57
57
  context "a cancelled encode" do
58
- before do
59
- allow(Rubyhorn.client).to receive(:instance_xml).with('cancelled-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
60
- end
58
+ subject { canceled_job }
61
59
 
62
- subject { ActiveEncode::Base.find('cancelled-id') }
63
- it { is_expected.to be_a ActiveEncode::Base }
64
- its(:id) { is_expected.to eq 'cancelled-id' }
65
- it { is_expected.to be_cancelled }
66
60
  its(:options) { is_expected.to include(preset: 'full') }
61
+ its(:current_operations) { is_expected.not_to be_empty }
67
62
  its(:current_operations) { is_expected.to include("Tagging dublin core catalogs for publishing") }
68
- its(:percent_complete) { is_expected.to eq 1.7391304347826086 }
69
- its(:errors) { is_expected.to be_empty }
70
- its(:created_at) { is_expected.to eq '2015-04-20T18:01:57Z' }
71
- its(:updated_at) { is_expected.to eq '2015-04-21T18:46:05Z' }
72
- its(:finished_at) { is_expected.to eq '2015-04-21T18:46:05Z' }
73
- its(:tech_metadata) { is_expected.to be_empty }
63
+ its(:updated_at) { is_expected.to be > subject.created_at }
74
64
  end
65
+
75
66
  context "a completed encode" do
76
- before do
77
- allow(Rubyhorn.client).to receive(:instance_xml).with('completed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/completed_response.xml')))
78
- end
79
- let(:completed_output) { [{ id: "track-7", mime_type: "video/mp4", checksum: "77de9765545ef63d2c21f7557ead6176", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "2000000.0", video_framerate: "30.0", width: "1308", height: "720", url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/b09c765f-b64e-4725-a863-736af66b688c/videoshort.mp4", label: "quality-high" }, { id: "track-8", mime_type: "video/mp4", checksum: "10e13cf51bf8a973011eec6a17ea47ff", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "500000.0", video_framerate: "30.0", width: "654", height: "360", url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/8d5cd8a9-ad0e-484a-96f0-05e26a84a8f0/videoshort.mp4", label: "quality-low" }, { id: "track-9", mime_type: "video/mp4", checksum: "f2b16a2606dc76cb53c7017f0e166204", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "1000000.0", video_framerate: "30.0", width: "872", height: "480", url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/0f81d426-0e26-4496-8f58-c675c86e6f4e/videoshort.mp4", label: "quality-medium" }] }
67
+ subject { completed_job }
80
68
 
81
- subject { ActiveEncode::Base.find('completed-id') }
82
- it { is_expected.to be_a ActiveEncode::Base }
83
- its(:id) { is_expected.to eq 'completed-id' }
84
- it { is_expected.to be_completed }
85
- its(:output) { is_expected.to eq completed_output }
86
69
  its(:options) { is_expected.to include(preset: 'avalon') }
87
70
  its(:current_operations) { is_expected.to include("Cleaning up") }
88
- its(:percent_complete) { is_expected.to eq 100 }
89
- its(:errors) { is_expected.to be_empty }
90
- its(:created_at) { is_expected.to eq '2015-04-21T18:08:00Z' }
91
- its(:updated_at) { is_expected.to eq '2015-04-21T18:14:18Z' }
92
- its(:finished_at) { is_expected.to eq '2015-04-21T18:14:18Z' }
93
- its(:tech_metadata) { is_expected.to be_empty }
94
71
  end
95
72
  context "a failed encode" do
96
- before do
97
- allow(Rubyhorn.client).to receive(:instance_xml).with('failed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/failed_response.xml')))
98
- end
99
- let(:failed_tech_metadata) { { mime_type: "video/mp4", checksum: "7ae24368ccb7a6c6422a14ff73f33c9a", duration: "6314", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "171030.0", video_codec: "AVC", video_bitrate: "74477.0", video_framerate: "23.719", width: "200", height: "110" } }
100
- let(:failed_errors) { "org.opencastproject.workflow.api.WorkflowOperationException: org.opencastproject.workflow.api.WorkflowOperationException: One of the encoding jobs did not complete successfully" }
73
+ subject { failed_job }
101
74
 
102
- subject { ActiveEncode::Base.find('failed-id') }
103
- it { is_expected.to be_a ActiveEncode::Base }
104
- its(:id) { is_expected.to eq 'failed-id' }
105
- it { is_expected.to be_failed }
106
75
  its(:options) { is_expected.to include(preset: 'error') }
107
76
  its(:current_operations) { is_expected.to include("Cleaning up after failure") }
108
- its(:percent_complete) { is_expected.to eq 56.666666666666664 }
109
- its(:errors) { is_expected.to include failed_errors }
110
- its(:created_at) { is_expected.to eq '2015-04-09T16:12:00Z' }
111
- its(:updated_at) { is_expected.to eq '2015-04-09T16:14:06Z' }
112
- its(:finished_at) { is_expected.to eq '2015-04-09T16:14:06Z' }
113
- its(:tech_metadata) { is_expected.to include failed_tech_metadata }
114
77
  end
115
78
  end
116
79
 
117
80
  describe "#cancel!" do
118
- before do
119
- allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
120
- end
121
81
  let(:encode) { ActiveEncode::Base.create(file) }
122
82
  subject { encode.cancel! }
83
+
123
84
  it { is_expected.to be_a ActiveEncode::Base }
124
85
  its(:id) { is_expected.to eq 'cancelled-id' }
125
86
  it { is_expected.to be_cancelled }
@@ -172,18 +133,12 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
172
133
  expect(Rubyhorn.client).to receive(:instance_xml).twice.with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
173
134
  end
174
135
 
175
- subject { ActiveEncode::Base.find('running-id').reload }
176
- it { is_expected.to be_a ActiveEncode::Base }
177
- its(:id) { is_expected.to eq 'running-id' }
178
- it { is_expected.to be_running }
136
+ subject { running_job.reload }
137
+
179
138
  its(:output) { is_expected.to be_empty }
180
139
  its(:options) { is_expected.to include(preset: 'full') }
181
140
  its(:current_operations) { is_expected.to include("Hold for workflow selection") }
182
141
  its(:percent_complete) { is_expected.to eq 0.43478260869565216 }
183
- its(:errors) { is_expected.to be_empty }
184
- its(:created_at) { is_expected.to eq '2015-04-20T17:58:43Z' }
185
- its(:updated_at) { is_expected.to eq '2015-04-21T18:38:50Z' }
186
- its(:finished_at) { is_expected.to be_nil }
187
142
  its(:tech_metadata) { is_expected.to be_empty }
188
143
  end
189
144