apisync-rails 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 38f143e80f7eeefc8f80b710b319435f7fc6c0bf
4
- data.tar.gz: c7f569963767bc579f2545de3ab68bf6b25900ac
3
+ metadata.gz: 3ea28569d7864193a7d68b89a0a7429e0e7e8d9a
4
+ data.tar.gz: ed8b404b84538f8095d64e83362b1edddcd2fb8b
5
5
  SHA512:
6
- metadata.gz: cb369dff486a556acfd6de4ed212a60c06bdf545b73eeed32969caf8a8e49246e1c5463d4ad3010b53b628d3da17d9d2ee0ae1fdb7f42a2c0ee376b85dd8b155
7
- data.tar.gz: 75eaa44a224a335a72b94c484ea09feca8a1ebfad2f8647c2d74cf4a31d9a05b645e401a77a4e859e2e77aeeba77e37ae168b8863759e690993a268d3ab0af6e
6
+ metadata.gz: acb463131a3e52f011ed585fc22f290285bb8903f73fdb53f8850830d3d1b6af3626f8fe18a94d5841b347e6219edc3e8e56bc15e0251fed197eec333a755471
7
+ data.tar.gz: c8f715e69ee47ba68cec1d456972f0142f53e395595405f2bf0b961712fe1a6db543b10a6cfcadf38173085a4f5a78a9a2f0cea7e040c68aa7fb9ffde31c9a5b
data/README.md CHANGED
@@ -41,6 +41,10 @@ the [API reference](https://docs.apisync.io/api/) for details.
41
41
  ```ruby
42
42
  class Product < ActiveRecord::Base
43
43
  apisync do
44
+ # should the current item be synchronized?
45
+ # remove it to always sync all items
46
+ sync_if :should_sync?
47
+
44
48
  # required attributes
45
49
  attribute :ad_template_type, from: :category
46
50
  attribute :available, from: :active?
@@ -64,6 +68,10 @@ class Product < ActiveRecord::Base
64
68
 
65
69
  private
66
70
 
71
+ def should_sync?
72
+ true
73
+ end
74
+
67
75
  # required format (see reference docs)
68
76
  def images
69
77
  [{
@@ -93,6 +101,10 @@ end
93
101
 
94
102
  **Explanation**
95
103
 
104
+ **sync_if** defines if the item should be synchronized. The method with the
105
+ name of the symbol will be called. When `true`, the item will be saved on
106
+ ApiSync. Remove this if you always want to push to ApiSync (recommended).
107
+
96
108
  **attribute** specifies one value to be sent to ApiSync. Pass the
97
109
  attribute name as parameter, e.g `attribute :brand`.
98
110
 
@@ -23,8 +23,7 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_dependency "activesupport", ">= 4.2"
25
25
  spec.add_dependency "activerecord", ">= 4.2"
26
- # in dev mode
27
- spec.add_dependency "apisync"
26
+ spec.add_dependency "apisync", ">= 0.1.4"
28
27
 
29
28
  spec.add_development_dependency "bundler", "~> 1.15"
30
29
  spec.add_development_dependency "rake", "~> 10.0"
@@ -10,13 +10,13 @@ class Apisync
10
10
 
11
11
  private
12
12
 
13
- def start_apisync
13
+ def apisync_on_after_initialize
14
14
  @apisync = Apisync::Rails::Model.new(self)
15
15
  @apisync.instance_eval(&self.class.apisync_block)
16
16
  @apisync.validate!
17
17
  end
18
18
 
19
- def save_to_apisync
19
+ def apisync_on_after_commit
20
20
  @apisync.sync
21
21
  end
22
22
  end
@@ -27,15 +27,11 @@ class Apisync
27
27
  end
28
28
 
29
29
  def apisync(&block)
30
- after_initialize :start_apisync
31
- after_commit :save_to_apisync
30
+ after_initialize :apisync_on_after_initialize
31
+ after_commit :apisync_on_after_commit
32
32
 
33
33
  @apisync_block = block
34
34
  end
35
35
  end
36
36
  end
37
37
  end
38
-
39
- ActiveSupport.on_load(:active_record) do
40
- ::ActiveRecord::Base.send(:include, Apisync::ActiveRecordExtension)
41
- end
@@ -6,9 +6,16 @@ require "apisync/rails/version"
6
6
  require "apisync/rails/model"
7
7
  require "apisync/rails/http"
8
8
  require "apisync/active_record_extension"
9
+ require "apisync/rails/sync_model_job/sidekiq"
10
+ require "apisync/rails/extensions"
9
11
 
10
12
  class Apisync
11
13
  module Rails
12
- # Your code goes here...
13
14
  end
14
15
  end
16
+
17
+ # This class, Extensions, is responsible for including extensions into
18
+ # our own classes (and ActiveRecord::Base). For example, if Sidekiq is defined
19
+ # then we include it into our worker classes. That way we don't need to load
20
+ # the Sidekiq gem and force it into client codebases.
21
+ Apisync::Rails::Extensions.setup
@@ -0,0 +1,21 @@
1
+ class Apisync
2
+ module Rails
3
+ class Extensions
4
+ def self.setup
5
+
6
+ ActiveSupport.on_load(:active_record) do
7
+ ::ActiveRecord::Base.send(:include, Apisync::ActiveRecordExtension)
8
+ end
9
+
10
+ if defined?(::Sidekiq)
11
+ sidekiq_klass = ::Apisync::Rails::SyncModelJob::Sidekiq
12
+
13
+ # Don't include twice the same module
14
+ unless sidekiq_klass.included_modules.include?(::Sidekiq::Worker)
15
+ sidekiq_klass.send(:include, ::Sidekiq::Worker)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,9 +1,30 @@
1
1
  class Apisync
2
2
  module Rails
3
3
  class Http
4
- def self.post(attrs)
4
+ def self.post(attrs, request_concurrency:, too_many_requests_attempts: nil, concurrency_lib: nil)
5
+ headers = {}
6
+ headers["X-Request-Concurrency"] = request_concurrency.to_s
7
+
8
+ if ::Rails.respond_to?(:gem_version)
9
+ rails_version = ::Rails.gem_version.to_s
10
+ elsif Rails::VERSION.is_a?(String)
11
+ rails_version = Rails::VERSION
12
+ elsif Rails::VERSION::STRING
13
+ rails_version = Rails::VERSION::STRING
14
+ end
15
+
16
+ headers["X-Framework"] = "Ruby on Rails #{rails_version}"
17
+ headers["X-Client-Library"] = "apisync-rails #{Apisync::Rails::VERSION}"
18
+
19
+ if concurrency_lib
20
+ headers["X-Concurrency-Lib"] = concurrency_lib.to_s
21
+ end
22
+ if too_many_requests_attempts
23
+ headers["X-TooManyRequests-Attempts"] = too_many_requests_attempts.to_s
24
+ end
25
+
5
26
  client = Apisync.new
6
- client.inventory_items.save(attributes: attrs)
27
+ client.inventory_items.save(attributes: attrs, headers: headers)
7
28
  end
8
29
  end
9
30
  end
@@ -18,6 +18,11 @@ class Apisync
18
18
  def initialize(model)
19
19
  @model = model
20
20
  @attributes = {}
21
+ @should_sync = true
22
+ end
23
+
24
+ def sync_if(method_name)
25
+ @should_sync = @model.send(method_name.to_sym)
21
26
  end
22
27
 
23
28
  def attribute(attr_name, from: nil, value: nil)
@@ -35,13 +40,29 @@ class Apisync
35
40
  end
36
41
 
37
42
  def sync
38
- set_reference_id
39
- validate!
40
- log_warnings
41
- Apisync::Rails::Http.post(@attributes)
43
+ if sync?
44
+ set_reference_id
45
+ validate!
46
+ log_warnings
47
+
48
+ if defined?(::Sidekiq)
49
+ Apisync::Rails::SyncModelJob::Sidekiq.perform_async(
50
+ @model.class.name,
51
+ @model.id,
52
+ @attributes
53
+ )
54
+ else
55
+ Apisync::Rails::Http.post(
56
+ @attributes,
57
+ request_concurrency: :synchronous
58
+ )
59
+ end
60
+ end
42
61
  end
43
62
 
44
63
  def validate!
64
+ return unless sync?
65
+
45
66
  REQUIRED_ATTRS.each do |attr, message|
46
67
  if @attributes[attr].blank?
47
68
  raise MissingAttribute, "Please specify #{attr}. #{message}"
@@ -59,6 +80,10 @@ class Apisync
59
80
 
60
81
  private
61
82
 
83
+ def sync?
84
+ @should_sync
85
+ end
86
+
62
87
  def set_reference_id
63
88
  if @attributes[:reference_id].blank? && @model.id.present?
64
89
  @attributes[:reference_id] = @model.id.to_s
@@ -0,0 +1,43 @@
1
+ class Apisync
2
+ module Rails
3
+ module SyncModelJob
4
+ class Sidekiq
5
+ # include ::Sidekiq::Worker (deferred)
6
+ #
7
+ # Sidekiq module is included in the Extensions class. We don't do it here
8
+ # because we don't know if Sidekiq is loaded or not. If it is not, we
9
+ # don't want to include it in this class.
10
+
11
+ def perform(model_name, id, attributes, attempt = 1)
12
+ unless defined?(::Sidekiq)
13
+ raise ArgumentError,
14
+ "Sidekiq is not defined but an ApiSync job is being spun up."
15
+ end
16
+
17
+ begin
18
+ Apisync::Rails::Http.post(
19
+ attributes,
20
+ request_concurrency: :asynchronous,
21
+ concurrency_lib: "Sidekiq #{::Sidekiq::VERSION}",
22
+ too_many_requests_attempts: attempt.to_s
23
+ )
24
+
25
+ # When there are too many requests and ApiSync's API cannot take it,
26
+ # this algorithm will push this job to be retried in the future.
27
+ rescue Apisync::TooManyRequests
28
+ ::Rails.logger.warn "[apisync] Too many simultaneous HTTP requests. Requests are being automatically throttled to solve this problem. Contact ApiSync support for details."
29
+
30
+ retry_in = Random.new.rand(270) + 30 # 30 seconds - 5 minutes
31
+ self.class.perform_in(
32
+ retry_in,
33
+ model_name,
34
+ id,
35
+ attributes,
36
+ attempt.to_i + 1
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,5 @@
1
1
  class Apisync
2
2
  module Rails
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apisync-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre de Oliveira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-10 00:00:00.000000000 Z
11
+ date: 2017-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.1.4
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.1.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -200,8 +200,10 @@ files:
200
200
  - bin/setup
201
201
  - lib/apisync/active_record_extension.rb
202
202
  - lib/apisync/rails.rb
203
+ - lib/apisync/rails/extensions.rb
203
204
  - lib/apisync/rails/http.rb
204
205
  - lib/apisync/rails/model.rb
206
+ - lib/apisync/rails/sync_model_job/sidekiq.rb
205
207
  - lib/apisync/rails/version.rb
206
208
  homepage: https://github.com/apisync/apisync-rails
207
209
  licenses: