cangaroo 1.2.0 → 1.3.0

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/app/controllers/cangaroo/endpoint_controller.rb +22 -28
  4. data/app/interactors/cangaroo/count_json_object.rb +2 -12
  5. data/app/interactors/cangaroo/perform_jobs.rb +2 -6
  6. data/app/interactors/cangaroo/run_polls.rb +0 -1
  7. data/app/interactors/cangaroo/validate_json_schema.rb +3 -8
  8. data/app/jobs/cangaroo/base_job.rb +35 -0
  9. data/app/jobs/cangaroo/job.rb +2 -36
  10. data/app/jobs/cangaroo/poll_job.rb +20 -44
  11. data/app/jobs/cangaroo/push_job.rb +15 -0
  12. data/app/models/cangaroo/connection.rb +3 -3
  13. data/app/models/cangaroo/poll_timestamp.rb +1 -2
  14. data/db/migrate/20151028172151_create_cangaroo_connections.rb +1 -1
  15. data/db/migrate/20151030140821_add_parameters_to_cangaroo_connection.rb +1 -1
  16. data/db/migrate/20160317020230_create_cangaroo_poll_timestamps.rb +2 -2
  17. data/lib/cangaroo.rb +9 -0
  18. data/lib/cangaroo/class_configuration.rb +7 -4
  19. data/lib/cangaroo/engine.rb +2 -0
  20. data/lib/cangaroo/logger.rb +13 -58
  21. data/lib/cangaroo/logger_helper.rb +13 -0
  22. data/lib/cangaroo/migration.rb +11 -0
  23. data/lib/cangaroo/version.rb +1 -1
  24. data/lib/cangaroo/webhook/client.rb +27 -15
  25. data/spec/factories/cangaroo_connections.rb +26 -2
  26. data/spec/features/push_flow_spec.rb +79 -0
  27. data/spec/fixtures/json_payload_ok.json +3 -1
  28. data/spec/interactors/cangaroo/count_json_object_spec.rb +4 -2
  29. data/spec/interactors/cangaroo/perform_jobs_spec.rb +2 -3
  30. data/spec/jobs/cangaroo/poll_job_spec.rb +15 -17
  31. data/spec/jobs/cangaroo/{job_spec.rb → push_job_spec.rb} +25 -17
  32. data/spec/lib/cangaroo/logger_helper_spec.rb +21 -0
  33. data/spec/lib/cangaroo/logger_spec.rb +83 -0
  34. data/spec/lib/cangaroo/webhook/client_spec.rb +39 -24
  35. data/spec/rails_helper.rb +4 -2
  36. data/spec/{controllers/cangaroo/endpoint_controller_spec.rb → requests/cangaroo/endpoint_spec.rb} +21 -30
  37. data/spec/support/jobs/confirm_order_mail_job.rb +10 -0
  38. data/spec/support/jobs/erp_job.rb +10 -0
  39. data/spec/support/jobs/fake_push_job.rb +5 -0
  40. data/spec/support/jobs/shipped_order_mail_job.rb +10 -0
  41. data/spec/support/jobs/store_job.rb +10 -0
  42. data/spec/support/jobs/warehouse_job.rb +10 -0
  43. data/spec/support/rails_app.rb +1 -0
  44. data/spec/support/spec_helpers.rb +23 -0
  45. metadata +53 -32
  46. data/app/controllers/cangaroo/application_controller.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56de926de5b5e5d494a4a1f132e854a171191543
4
- data.tar.gz: 94b41bce37f5b18794eabb1fa5a9cf623bb0087e
3
+ metadata.gz: 3896bc0334e02871b872a34472b292f0d4400970
4
+ data.tar.gz: d489f9fbfda6a5597107eecc7c0df1eb8ba32d64
5
5
  SHA512:
6
- metadata.gz: e927e1bf09605b62d8690aeed1c14599949fc5c3d7b5611626a23d67eb6006b0ba33a091e1dbbc23398f322119b0889b4e8fc170bb41b39977e011caa3e79d07
7
- data.tar.gz: 2f24253cc3a8a1f39f07ed74624963e59034c11da0d75d492367ee2642469622d6c8993a3dc1f150eca0df429875b48958444d36ee786f96b0ff7e82c02ec40a
6
+ metadata.gz: daab3c0a4a1a32e494f83bb2196e1037e9f223de107d810f546d224a8d2cff9b4d073c35282c82207f2d3e3b05ef4040ae094e082eaa74665ac0bbc077e2c829
7
+ data.tar.gz: a955392403bc2413366d76a7dd237cdfd009b75745dbbbe188a26de028ed8422b3f66cfbdf634aafa33badea145b4f1c4f392e7903d0a9041dabea123d3a5eaa
data/Rakefile CHANGED
@@ -28,7 +28,7 @@ desc 'Run Cangaroo specs.'
28
28
  RSpec::Core::RakeTask.new(:spec)
29
29
 
30
30
  if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
31
- task :default => :appraisal
31
+ task default: :appraisal
32
32
  end
33
33
 
34
34
  task default: :spec
@@ -1,7 +1,5 @@
1
- require_dependency 'cangaroo/application_controller'
2
-
3
1
  module Cangaroo
4
- class EndpointController < ApplicationController
2
+ class EndpointController < ActionController::Base
5
3
  before_action :ensure_json_request
6
4
  before_action :handle_request
7
5
 
@@ -19,51 +17,47 @@ module Cangaroo
19
17
  private
20
18
 
21
19
  def handle_error(exception)
22
- if Rails.env.development?
23
- raise(exception)
24
- else
25
- render json: { error: 'Something went wrong!' }, status: 500
26
- end
20
+ raise(exception) if Rails.env.development?
21
+ render json: { error: 'Something went wrong!' }, status: 500
27
22
  end
28
23
 
29
24
  def handle_request
30
25
  @command = HandleRequest.call(
31
26
  key: key,
32
27
  token: token,
33
- json_body: params[:endpoint].to_json,
28
+ json_body: JSON.parse(request.raw_post),
34
29
  jobs: Rails.configuration.cangaroo.jobs
35
30
  )
36
31
  end
37
32
 
38
33
  def ensure_json_request
39
34
  return if request.headers['Content-Type'] == 'application/json'
35
+
40
36
  render nothing: true, status: 406
41
37
  end
42
38
 
43
39
  def key
44
- if Rails.configuration.cangaroo.basic_auth
45
- if !ActionController::HttpAuthentication::Basic.has_basic_credentials?(request)
46
- return nil
47
- end
48
-
49
- user, pass = ActionController::HttpAuthentication::Basic::user_name_and_password(request)
50
- user
51
- else
52
- request.headers['X-Hub-Store']
53
- end
40
+ return user if Rails.configuration.cangaroo.basic_auth
41
+ request.headers['X-Hub-Store']
54
42
  end
55
43
 
56
44
  def token
57
- if Rails.configuration.cangaroo.basic_auth
58
- if !ActionController::HttpAuthentication::Basic.has_basic_credentials?(request)
59
- return nil
60
- end
45
+ return password if Rails.configuration.cangaroo.basic_auth
46
+ request.headers['X-Hub-Access-Token']
47
+ end
61
48
 
62
- user, pass = ActionController::HttpAuthentication::Basic::user_name_and_password(request)
63
- pass
64
- else
65
- request.headers['X-Hub-Access-Token']
66
- end
49
+ def user
50
+ user_and_password.try(:first)
51
+ end
52
+
53
+ def password
54
+ user_and_password.try(:last)
55
+ end
56
+
57
+ def user_and_password
58
+ return nil unless ActionController::HttpAuthentication::Basic.has_basic_credentials?(request)
59
+
60
+ ActionController::HttpAuthentication::Basic.user_name_and_password(request)
67
61
  end
68
62
  end
69
63
  end
@@ -1,23 +1,13 @@
1
1
  module Cangaroo
2
2
  class CountJsonObject
3
- include Cangaroo::Log
4
3
  include Interactor
5
4
 
6
- before :prepare_context
7
-
8
5
  def call
9
- context.object_count = context.data.inject({}) do |o, (k, v)|
6
+ context.object_count = context.json_body.each_with_object({}) do |(k, v), o|
10
7
  o[k] = v.size
11
- o
12
8
  end
13
9
 
14
- log.info 'total consumed payloads', count: context.object_count
15
- end
16
-
17
- private
18
-
19
- def prepare_context
20
- context.data = JSON.parse(context.json_body)
10
+ Cangaroo.logger.info 'total consumed payloads', count: context.object_count
21
11
  end
22
12
  end
23
13
  end
@@ -3,17 +3,13 @@ module Cangaroo
3
3
  include Interactor
4
4
 
5
5
  def call
6
- data.each do |type, payloads|
6
+ context.json_body.each do |type, payloads|
7
7
  payloads.each { |payload| enqueue_jobs(type, payload) }
8
8
  end
9
9
  end
10
10
 
11
11
  private
12
12
 
13
- def data
14
- @data ||= JSON.parse(context.json_body)
15
- end
16
-
17
13
  def enqueue_jobs(type, payload)
18
14
  initialize_jobs(type, payload).select(&:perform?).each(&:enqueue)
19
15
  end
@@ -21,7 +17,7 @@ module Cangaroo
21
17
  def initialize_jobs(type, payload)
22
18
  context.jobs.map do |klass|
23
19
  klass.new(
24
- connection: context.source_connection,
20
+ source_connection: context.source_connection,
25
21
  type: type,
26
22
  payload: payload
27
23
  )
@@ -7,6 +7,5 @@ module Cangaroo
7
7
  poll_job.new.enqueue
8
8
  end
9
9
  end
10
-
11
10
  end
12
11
  end
@@ -8,16 +8,11 @@ module Cangaroo
8
8
  'minProperties': 1,
9
9
  'additionalProperties': false,
10
10
  'patternProperties': {
11
- '^[a-z]*$': {
11
+ '^[a-z\-_]*$': {
12
12
  'type': 'array',
13
13
  'items': {
14
14
  'type': 'object',
15
- 'required': ['id'],
16
- 'properties': {
17
- 'id': {
18
- 'type': 'string'
19
- }
20
- }
15
+ 'required': ['id']
21
16
  }
22
17
  }
23
18
  }
@@ -26,7 +21,7 @@ module Cangaroo
26
21
  before :prepare_context
27
22
 
28
23
  def call
29
- validation_response = JSON::Validator.fully_validate(SCHEMA, context.json_body)
24
+ validation_response = JSON::Validator.fully_validate(SCHEMA, context.json_body.to_json)
30
25
 
31
26
  if validation_response.empty?
32
27
  return true
@@ -0,0 +1,35 @@
1
+ module Cangaroo
2
+ class BaseJob < Job
3
+ include Cangaroo::ClassConfiguration
4
+
5
+ class_configuration :connection
6
+ class_configuration :path, ''
7
+ class_configuration :parameters, {}
8
+ class_configuration :process_response, true
9
+
10
+ protected
11
+
12
+ def connection_request
13
+ Cangaroo::Webhook::Client.new(destination_connection, path).post(transform, job_id, parameters)
14
+ end
15
+
16
+ def restart_flow(response)
17
+ # if no json was returned, the response should be discarded
18
+ return if response.blank?
19
+
20
+ return unless process_response
21
+
22
+ command = Cangaroo::PerformFlow.call(
23
+ source_connection: destination_connection,
24
+ json_body: response,
25
+ jobs: Rails.configuration.cangaroo.jobs.reject{ |job| job == self.class }
26
+ )
27
+
28
+ fail Cangaroo::Webhook::Error, command.message unless command.success?
29
+ end
30
+
31
+ def destination_connection
32
+ @destination_connection ||= Cangaroo::Connection.find_by!(name: connection)
33
+ end
34
+ end
35
+ end
@@ -1,45 +1,15 @@
1
1
  module Cangaroo
2
2
  class Job < ActiveJob::Base
3
- include Cangaroo::ClassConfiguration
3
+ include Cangaroo::LoggerHelper
4
4
 
5
5
  queue_as :cangaroo
6
6
 
7
- class_configuration :connection
8
- class_configuration :path, ''
9
- class_configuration :parameters, {}
10
-
11
- def perform(*)
12
- restart_flow(connection_request)
13
- end
14
-
15
7
  def perform?
16
8
  fail NotImplementedError
17
9
  end
18
10
 
19
- def transform
20
- { type.singularize => payload }
21
- end
22
-
23
- protected
24
-
25
- def connection_request
26
- Cangaroo::Webhook::Client.new(destination_connection, path)
27
- .post(transform, @job_id, parameters)
28
- end
29
-
30
- def restart_flow(response)
31
- # if no json was returned, the response should be discarded
32
- return if response.blank?
33
-
34
- PerformFlow.call(
35
- source_connection: destination_connection,
36
- json_body: response.to_json,
37
- jobs: Rails.configuration.cangaroo.jobs
38
- )
39
- end
40
-
41
11
  def source_connection
42
- arguments.first.fetch(:connection)
12
+ arguments.first.fetch(:source_connection)
43
13
  end
44
14
 
45
15
  def type
@@ -49,9 +19,5 @@ module Cangaroo
49
19
  def payload
50
20
  arguments.first.fetch(:payload)
51
21
  end
52
-
53
- def destination_connection
54
- @connection ||= Cangaroo::Connection.find_by!(name: connection)
55
- end
56
22
  end
57
23
  end
@@ -1,67 +1,43 @@
1
1
  module Cangaroo
2
- class PollJob < ActiveJob::Base
3
- include Cangaroo::Log
4
- include Cangaroo::ClassConfiguration
2
+ class PollJob < BaseJob
3
+ class_configuration :frequency, 1.day
5
4
 
6
- queue_as :cangaroo
5
+ attr_reader :current_time
7
6
 
8
- class_configuration :connection
9
- class_configuration :frequency, 1.day
10
- class_configuration :path, ''
11
- class_configuration :parameters, {}
7
+ def transform
8
+ { last_poll: last_poll_timestamp.to_i }
9
+ end
12
10
 
13
11
  def perform(*)
14
- log.set_context(self)
15
-
16
- last_poll = Time.at(arguments.first.fetch(:last_poll)).to_datetime
17
- current_time = DateTime.now
12
+ @current_time = DateTime.now
18
13
 
19
14
  if !perform?(current_time)
20
- log.info 'skipping poll'
15
+ Cangaroo.logger.info 'skipping poll', job_tags
21
16
  return
22
17
  end
23
18
 
24
- log.info 'initiating poll', last_poll: last_poll.to_i
25
-
26
- response = Cangaroo::Webhook::Client.new(destination_connection, path)
27
- .post({ last_poll: last_poll_timestamp.to_i }, @job_id, parameters)
28
-
29
- log.info 'processing poll results'
19
+ restart_flow(connection_request)
30
20
 
31
- command = HandleRequest.call(
32
- key: destination_connection.key,
33
- token: destination_connection.token,
34
- json_body: response.to_json,
35
- jobs: Rails.configuration.cangaroo.jobs
36
- )
37
-
38
- if !command.success?
39
- fail Cangaroo::Webhook::Error, command.message
40
- end
41
-
42
- log.info 'updating last poll', last_poll: current_time
43
-
44
- last_job_poll = Cangaroo::PollTimestamp.for_class(self.class)
45
- last_job_poll.value = current_time
46
- last_job_poll.save!
47
-
48
- log.reset_context!
21
+ update_last_poll_timestamp
49
22
  end
50
23
 
51
24
  def perform?(execution_time)
52
25
  last_poll_timestamp.nil? ||
53
- execution_time.to_i - last_poll_timestamp.to_i > self.class.frequency
26
+ execution_time.to_i - last_poll_timestamp.to_i > self.class.frequency
54
27
  end
55
28
 
56
29
  protected
57
30
 
58
- def last_poll_timestamp
59
- @last_poll_timestamp ||= Cangaroo::PollTimestamp.for_class(self.class).value
60
- end
31
+ def update_last_poll_timestamp
32
+ Cangaroo.logger.info 'updating last poll', job_tags(last_poll: current_time)
61
33
 
62
- def destination_connection
63
- @connection ||= Cangaroo::Connection.find_by!(name: connection)
64
- end
34
+ last_job_poll = Cangaroo::PollTimestamp.for_class(self.class)
35
+ last_job_poll.value = current_time
36
+ last_job_poll.save!
37
+ end
65
38
 
39
+ def last_poll_timestamp
40
+ @last_poll_timestamp ||= Cangaroo::PollTimestamp.for_class(self.class).value
41
+ end
66
42
  end
67
43
  end
@@ -0,0 +1,15 @@
1
+ module Cangaroo
2
+ class PushJob < BaseJob
3
+ def perform(*)
4
+ restart_flow(connection_request)
5
+ end
6
+
7
+ def perform?
8
+ fail NotImplementedError
9
+ end
10
+
11
+ def transform
12
+ { type.singularize => payload }
13
+ end
14
+ end
15
+ end
@@ -13,8 +13,8 @@ module Cangaroo
13
13
 
14
14
  private
15
15
 
16
- def set_default_parameters
17
- self.parameters ||= {}
18
- end
16
+ def set_default_parameters
17
+ self.parameters ||= {}
18
+ end
19
19
  end
20
20
  end
@@ -7,11 +7,10 @@ module Cangaroo
7
7
  validates_uniqueness_of :job, scope: :connection
8
8
 
9
9
  def self.for_class(klass)
10
- self.where(
10
+ where(
11
11
  job: klass.to_s,
12
12
  connection: Cangaroo::Connection.find_by!(name: klass.connection)
13
13
  ).first_or_initialize
14
14
  end
15
-
16
15
  end
17
16
  end
@@ -1,4 +1,4 @@
1
- class CreateCangarooConnections < ActiveRecord::Migration
1
+ class CreateCangarooConnections < Cangaroo::Migration[4.2]
2
2
  def change
3
3
  create_table :cangaroo_connections do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class AddParametersToCangarooConnection < ActiveRecord::Migration
1
+ class AddParametersToCangarooConnection < Cangaroo::Migration[4.2]
2
2
  def change
3
3
  add_column :cangaroo_connections, :parameters, :text
4
4
  end
@@ -1,4 +1,4 @@
1
- class CreateCangarooPollTimestamps < ActiveRecord::Migration
1
+ class CreateCangarooPollTimestamps < Cangaroo::Migration[4.2]
2
2
  def change
3
3
  create_table :cangaroo_poll_timestamps do |t|
4
4
  t.string :job
@@ -7,6 +7,6 @@ class CreateCangarooPollTimestamps < ActiveRecord::Migration
7
7
  t.timestamps
8
8
  end
9
9
 
10
- add_index :cangaroo_poll_timestamps, [:job], :name => 'index_cangaroo_poll_timestamps_on_job'
10
+ add_index :cangaroo_poll_timestamps, [:job], name: 'index_cangaroo_poll_timestamps_on_job'
11
11
  end
12
12
  end