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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4cc9a23af554f70fe254b6c08dd9422e0799c5e
4
- data.tar.gz: 7c4ba992d65bd57c36767cbcd386b35a645a0b8c
3
+ metadata.gz: 3346c9f9ae44a17bf60b9f71dbf6a3bd8b951883
4
+ data.tar.gz: 8f228d1184a1f61629bbed814176d131bc98de40
5
5
  SHA512:
6
- metadata.gz: 07f0ac6c7f1f0bd3a794ca21ae31ecacd311dbd2cba15b6e878706fe6c7a11b4c481fd538391d8564b28f4de37bc5d4ff91dd14125f64b642f2b4e166b721d9d
7
- data.tar.gz: 5fd817093bab2eb625ac4098f256fb4597ac316b8d747fb003e64f7aeafc6faa2f79d74c50c5692bcb611339dc9d605b646286bd3c8bb6fbbe465d9124b850dd
6
+ metadata.gz: 47fde2ffc94ad11ef0b8ab3af29672f3c8707128d887d2dd48249f0e13346b66b5450434ab1d79f1b840bf2ac695c05f5cd6f1ef11ce697d16bbd63193a5ad8e
7
+ data.tar.gz: 74073edc357c19e84fb51c80044684dceae704dcb8bef6061a49b62b269c78aa60fb47563db691d00fe798e76bfd7af88467290a4c135438beff51efbc2989b7
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ mkmf.log
15
15
  coverage
16
16
  .ruby-version
17
17
  .byebug_history
18
+ .internal_test_app
@@ -2,8 +2,9 @@ language: ruby
2
2
  cache: bundler
3
3
  sudo: false
4
4
  rvm:
5
- - 2.2.5
6
- - 2.3.1
5
+ - 2.3.7
6
+ - 2.4.4
7
+ - 2.5.1
7
8
  env:
8
9
  global:
9
10
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
data/Gemfile CHANGED
@@ -10,3 +10,38 @@ gem 'rubocop-rspec', require: false
10
10
  gem 'rubyhorn', git: "https://github.com/avalonmediasystem/rubyhorn.git"
11
11
  gem 'shingoncoder'
12
12
  gem 'zencoder'
13
+
14
+ # BEGIN ENGINE_CART BLOCK
15
+ # engine_cart: 2.0.1
16
+ # engine_cart stanza: 0.10.0
17
+ # the below comes from engine_cart, a gem used to test this Rails engine gem in the context of a Rails app.
18
+ file = File.expand_path('Gemfile', ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path('.internal_test_app', File.dirname(__FILE__)))
19
+ if File.exist?(file)
20
+ begin
21
+ eval_gemfile file
22
+ rescue Bundler::GemfileError => e
23
+ Bundler.ui.warn '[EngineCart] Skipping Rails application dependencies:'
24
+ Bundler.ui.warn e.message
25
+ end
26
+ else
27
+ Bundler.ui.warn "[EngineCart] Unable to find test application dependencies in #{file}, using placeholder dependencies"
28
+
29
+ if ENV['RAILS_VERSION']
30
+ if ENV['RAILS_VERSION'] == 'edge'
31
+ gem 'rails', github: 'rails/rails'
32
+ ENV['ENGINE_CART_RAILS_OPTIONS'] = '--edge --skip-turbolinks'
33
+ else
34
+ gem 'rails', ENV['RAILS_VERSION']
35
+ end
36
+ end
37
+
38
+ case ENV['RAILS_VERSION']
39
+ when /^4.2/
40
+ gem 'responders', '~> 2.0'
41
+ gem 'sass-rails', '>= 5.0'
42
+ gem 'coffee-rails', '~> 4.1.0'
43
+ when /^4.[01]/
44
+ gem 'sass-rails', '< 5.0'
45
+ end
46
+ end
47
+ # END ENGINE_CART BLOCK
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ActiveEncode
2
2
 
3
- This gem serves as the basis for the interface between a Ruby (Rails) application and a provider of transcoding services such as [Opencast Matterhorn](http://opencast.org), [Zencoder](http://zencoder.com), [Shingoncoder](http://github.com/jcoyne/shingoncoder), and [Amazon Elastic Transcoder](http://aws.amazon.com/elastictranscoder/).
3
+ This gem serves as the basis for the interface between a Ruby (Rails) application and a provider of transcoding services such as [Opencast Matterhorn](http://opencast.org), [Zencoder](http://zencoder.com), and [Amazon Elastic Transcoder](http://aws.amazon.com/elastictranscoder/).
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,7 +20,7 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- Set the engine adapter (default: inline), configure it (if neccessary), then submit encoding jobs!
23
+ Set the engine adapter (default: test), configure it (if neccessary), then submit encoding jobs!
24
24
 
25
25
  ```ruby
26
26
  ActiveEncode::Base.engine_adapter = :matterhorn
@@ -52,6 +52,8 @@ encode.cancel!
52
52
  encode.cancelled? # true
53
53
  ```
54
54
 
55
+ > `#purge!` and `#remove_output!` and the following documentation have been deprecated and will be removed in ActiveEncode 0.3.
56
+
55
57
  If the encoding job should be deleted, call purge:
56
58
  ```ruby
57
59
  encode.purge!
@@ -67,7 +69,7 @@ An encoding job is meant to be the record of the work of the encoding engine and
67
69
 
68
70
  ### Custom jobs
69
71
 
70
- Subclass ActiveEncode::Base to add custom callbacks or default options. Available callbacks are before, after, and around the create, cancel, and purge actions.
72
+ Subclass ActiveEncode::Base to add custom callbacks or default options. Available callbacks are before, after, and around the create and cancel actions.
71
73
 
72
74
  ```ruby
73
75
  class CustomEncode < ActiveEncode::Base
@@ -83,17 +85,16 @@ end
83
85
 
84
86
  ### Engine Adapters
85
87
 
86
- Engine adapters are shims between ActiveEncode and the back end encoding service. Each service has its own API and idiosyncracies so consult the table below to see what features are supported by each adapter. Add an additional engines by creating an engine adapter class that implements :create, :find, :list, :cancel, :purge, and :remove_output.
87
-
88
- | Adapter/Feature | Create | Find | List | Cancel | Purge | Remove Output | Preset | Multiple Outputs |
89
- |--------------------------|--------|------|------|--------|-------|---------------|--------|------------------|
90
- | Matterhorn | X | X | | X | X | X | X | X |
91
- | Zencoder | X | X | | X | | | | |
92
- | Shingoncoder (prototype) | X | X | | | | | | |
93
- | Shingoncoder | X | X | | | | | | |
94
- | AWS Elastic Transcoder | X | X | | X | | | | |
95
- | Inline | X | X | | | | | | |
96
- | Test | X | X | | X | | X | | |
88
+ Engine adapters are shims between ActiveEncode and the back end encoding service. Each service has its own API and idiosyncracies so consult the table below to see what features are supported by each adapter. Add an additional engines by creating an engine adapter class that implements :create, :find, and :cancel.
89
+
90
+ | Adapter/Feature | Create | Find | Cancel | Preset | Multiple Outputs |
91
+ |--------------------------|--------|------|--------|--------|------------------|
92
+ | Test | X | X | X | | |
93
+ | AWS Elastic Transcoder | X | X | X | | |
94
+ | Zencoder | X | X | X | | |
95
+ | Matterhorn | X | X | X | X | X |
96
+
97
+ > The Inline and Shingoncoder adapters are deprecated and will be removed in ActiveEncode 0.3.
97
98
 
98
99
  ## Contributing
99
100
 
data/Rakefile CHANGED
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake/clean'
2
4
  require 'bundler'
3
5
  require 'rubocop/rake_task'
6
+ require 'engine_cart/rake_task'
4
7
 
5
8
  Bundler::GemHelper.install_tasks
6
9
 
7
10
  desc "CI build"
8
- task ci: ["active_encode:adapters:clean", "active_encode:ci"]
11
+ task ci: ["active_encode:ci"]
9
12
  desc "Rspec"
10
13
  task spec: ["active_encode:ci"]
11
14
 
@@ -23,16 +26,8 @@ namespace 'active_encode' do
23
26
  end
24
27
 
25
28
  desc "CI build"
26
- task ci: [:rubocop, "active_encode:environment", "active_encode:adapters:start", "active_encode:spec"]
29
+ task ci: [:rubocop, "active_encode:environment", "engine_cart:generate", "active_encode:spec"]
27
30
 
28
31
  require 'rspec/core/rake_task'
29
32
  RSpec::Core::RakeTask.new(:spec)
30
-
31
- namespace 'adapters' do
32
- desc "Clean any local services needed by the adapters"
33
- task 'clean' => []
34
-
35
- desc "Start any local services needed by the adapters"
36
- task 'start' => []
37
- end
38
33
  end
@@ -19,11 +19,14 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "activesupport"
22
+ spec.add_dependency "rails"
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.7"
24
+ spec.add_development_dependency "bundler"
25
25
  spec.add_development_dependency "coveralls"
26
- spec.add_development_dependency "rake", "~> 10.0"
27
- spec.add_development_dependency "rspec", "~> 3.0"
28
- spec.add_development_dependency "rspec-its", "~> 1.2"
26
+ spec.add_development_dependency "database_cleaner"
27
+ spec.add_development_dependency "engine_cart"
28
+ spec.add_development_dependency "rake"
29
+ spec.add_development_dependency "rspec"
30
+ spec.add_development_dependency "rspec-its"
31
+ spec.add_development_dependency "rspec-rails"
29
32
  end
@@ -0,0 +1,20 @@
1
+ module ActiveEncode
2
+ class PollingJob < ActiveJob::Base
3
+
4
+ def perform(encode)
5
+ encode.run_callbacks(:status_update) { encode }
6
+ case encode.state
7
+ when :error
8
+ encode.run_callbacks(:error) { encode }
9
+ when :cancelled
10
+ encode.run_callbacks(:cancelled) { encode }
11
+ when :complete
12
+ encode.run_callbacks(:complete) { encode }
13
+ when :running
14
+ ActiveEncode::PollingJob.set(wait: ActiveEncode::Polling::POLLING_WAIT_TIME).perform_later(encode)
15
+ else # other states are illegal and ignored
16
+ raise StandardError, "Illegal state #{encode.state} in encode #{encode.id}!"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveEncode
2
+ class EncodeRecord < ActiveRecord::Base
3
+ # sql id, globalid, state, adapter, input filename/job title, timestamps
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class CreateActiveEncodeEncodeRecords < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :active_encode_encode_records do |t|
4
+ t.string :global_id
5
+ t.string :state
6
+ t.string :adapter
7
+ t.string :title
8
+ t.text :raw_object
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -1,2 +1,3 @@
1
1
  require 'active_encode/version'
2
2
  require 'active_encode/base'
3
+ require 'active_encode/engine'
@@ -2,16 +2,20 @@ require 'active_encode/core'
2
2
  require 'active_encode/engine_adapter'
3
3
  require 'active_encode/status'
4
4
  require 'active_encode/technical_metadata'
5
+ require 'active_encode/input'
6
+ require 'active_encode/output'
5
7
  require 'active_encode/callbacks'
6
- # require 'active_encode/logging'
8
+ require 'active_encode/global_id'
9
+ require 'active_encode/persistence'
10
+ require 'active_encode/polling'
7
11
 
8
12
  module ActiveEncode #:nodoc:
9
13
  class Base
10
14
  include Core
11
15
  include Status
12
- include TechnicalMetadata
13
16
  include EngineAdapter
14
17
  include Callbacks
18
+ include GlobalID
15
19
  end
16
20
 
17
21
  class NotFound < RuntimeError; end
@@ -1,4 +1,4 @@
1
- require 'active_support/callbacks'
1
+ require 'active_model/callbacks'
2
2
 
3
3
  module ActiveEncode
4
4
  # = Active Encode Callbacks
@@ -6,6 +6,8 @@ module ActiveEncode
6
6
  # Active Encode provides hooks during the life cycle of an encode. Callbacks allow you
7
7
  # to trigger logic during the life cycle of an encode. Available callbacks are:
8
8
  #
9
+ # * <tt>after_find</tt>
10
+ # * <tt>after_reload</tt>
9
11
  # * <tt>before_create</tt>
10
12
  # * <tt>around_create</tt>
11
13
  # * <tt>after_create</tt>
@@ -18,50 +20,31 @@ module ActiveEncode
18
20
  #
19
21
  module Callbacks
20
22
  extend ActiveSupport::Concern
21
- include ActiveSupport::Callbacks
22
23
 
23
- included do
24
- define_callbacks :create
25
- define_callbacks :cancel
26
- define_callbacks :purge
27
- end
28
-
29
- # These methods will be included into any Active Encode object, adding
30
- # callbacks for +create+, +cancel+, and +purge+ methods.
31
- module ClassMethods
32
- def before_create(*filters, &blk)
33
- set_callback(:create, :before, *filters, &blk)
34
- end
24
+ CALLBACKS = [
25
+ :after_find, :after_reload, :before_create, :around_create,
26
+ :after_create, :before_cancel, :around_cancel, :after_cancel,
27
+ :before_purge, :around_purge, :after_purge
28
+ ].freeze
35
29
 
36
- def after_create(*filters, &blk)
37
- set_callback(:create, :after, *filters, &blk)
38
- end
39
-
40
- def around_create(*filters, &blk)
41
- set_callback(:create, :around, *filters, &blk)
42
- end
43
-
44
- def before_cancel(*filters, &blk)
45
- set_callback(:cancel, :before, *filters, &blk)
46
- end
47
-
48
- def after_cancel(*filters, &blk)
49
- set_callback(:cancel, :after, *filters, &blk)
50
- end
30
+ included do
31
+ extend ActiveModel::Callbacks
51
32
 
52
- def around_cancel(*filters, &blk)
53
- set_callback(:cancel, :around, *filters, &blk)
54
- end
33
+ define_model_callbacks :find, :reload, only: :after
34
+ define_model_callbacks :create, :cancel, :purge
55
35
 
56
- def before_purge(*filters, &blk)
36
+ def self.before_purge(*filters, &blk)
37
+ ActiveSupport::Deprecation.warn("before_purge will be removed without replacement in ActiveEncode 0.3")
57
38
  set_callback(:purge, :before, *filters, &blk)
58
39
  end
59
40
 
60
- def after_purge(*filters, &blk)
41
+ def self.after_purge(*filters, &blk)
42
+ ActiveSupport::Deprecation.warn("after_purge will be removed without replacement in ActiveEncode 0.3")
61
43
  set_callback(:purge, :after, *filters, &blk)
62
44
  end
63
45
 
64
- def around_purge(*filters, &blk)
46
+ def self.around_purge(*filters, &blk)
47
+ ActiveSupport::Deprecation.warn("around_purge will be removed without replacement in ActiveEncode 0.3")
65
48
  set_callback(:purge, :around, *filters, &blk)
66
49
  end
67
50
  end
@@ -10,71 +10,115 @@ module ActiveEncode
10
10
  attr_accessor :id
11
11
 
12
12
  # Encode input
13
+ # @return ActiveEncode::Input
13
14
  attr_accessor :input
14
15
 
15
16
  # Encode output(s)
17
+ # @return Array[ActiveEncode::Output]
16
18
  attr_accessor :output
17
19
 
18
20
  # Encode options
19
21
  attr_accessor :options
22
+
23
+ attr_accessor :current_operations
24
+ attr_accessor :percent_complete
25
+
26
+ # @deprecated
27
+ attr_accessor :tech_metadata
20
28
  end
21
29
 
22
30
  module ClassMethods
23
- def default_options(_input)
31
+ def default_options(_input_url)
24
32
  {}
25
33
  end
26
34
 
27
- def create(input, options = nil)
28
- object = new(input, options)
35
+ def create(input_url, options = {})
36
+ object = new(input_url, options)
29
37
  object.create!
30
38
  end
31
39
 
32
40
  def find(id)
33
41
  raise ArgumentError, 'id cannot be nil' unless id
34
- engine_adapter.find(id, cast: self)
42
+ encode = new(nil)
43
+ encode.run_callbacks :find do
44
+ encode.send(:merge!, engine_adapter.find(id))
45
+ end
35
46
  end
36
47
 
37
- delegate :list, to: :engine_adapter
48
+ def list(*args)
49
+ ActiveSupport::Deprecation.warn("#list will be removed without replacement in ActiveEncode 0.3")
50
+ engine_adapter.list(args)
51
+ end
38
52
  end
39
53
 
40
- def initialize(input, options = nil)
41
- @input = input
42
- @options = options || self.class.default_options(input)
54
+ def initialize(input_url, options = nil)
55
+ @input = Input.new.tap{ |input| input.url = input_url }
56
+ @options = options || self.class.default_options(input_url)
43
57
  end
44
58
 
45
59
  def create!
60
+ # TODO: Raise ArgumentError if self has an id?
46
61
  run_callbacks :create do
47
- self.class.engine_adapter.create self
62
+ merge!(self.class.engine_adapter.create(self.input.url, self.options))
48
63
  end
49
64
  end
50
65
 
51
66
  def cancel!
52
67
  run_callbacks :cancel do
53
- self.class.engine_adapter.cancel self
68
+ merge!(self.class.engine_adapter.cancel(self.id))
54
69
  end
55
70
  end
56
71
 
57
72
  def purge!
73
+ ActiveSupport::Deprecation.warn("#purge! will be removed without replacement in ActiveEncode 0.3")
58
74
  run_callbacks :purge do
59
75
  self.class.engine_adapter.purge self
60
76
  end
61
77
  end
62
78
 
63
79
  def remove_output!(output_id)
80
+ ActiveSupport::Deprecation.warn("#remove_output will be removed without replacement in ActiveEncode 0.3")
64
81
  self.class.engine_adapter.remove_output self, output_id
65
82
  end
66
83
 
67
84
  def reload
68
- fresh_encode = self.class.engine_adapter.find(id, cast: self.class)
69
- @id = fresh_encode.id
70
- @input = fresh_encode.input
71
- @output = fresh_encode.output
72
- @state = fresh_encode.state
73
- @current_operations = fresh_encode.current_operations
74
- @errors = fresh_encode.errors
75
- @tech_metadata = fresh_encode.tech_metadata
76
-
77
- self
85
+ run_callbacks :reload do
86
+ merge!(self.class.engine_adapter.find(id))
87
+ end
88
+ end
89
+
90
+ def created?
91
+ !id.nil?
78
92
  end
93
+
94
+ # @deprecated
95
+ def tech_metadata
96
+ metadata = {}
97
+ [:width, :height, :frame_rate, :duration, :file_size,
98
+ :audio_codec, :video_codec, :audio_bitrate, :video_bitrate, :checksum].each do |key|
99
+ metadata[key] = input.send(key)
100
+ end
101
+ end
102
+
103
+ protected
104
+
105
+ def merge!(encode)
106
+ @id = encode.id
107
+ @input = encode.input
108
+ @output = encode.output
109
+ @options = encode.options
110
+ @state = encode.state
111
+ @errors = encode.errors
112
+ @created_at = encode.created_at
113
+ @updated_at = encode.updated_at
114
+ @current_operations = encode.current_operations
115
+ @percent_complete = encode.percent_complete
116
+
117
+ # deprecated
118
+ @tech_metadata = encode.tech_metadata
119
+ @finished_at = encode.finished_at
120
+
121
+ self
122
+ end
79
123
  end
80
124
  end