cangaroo 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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