apisync-rails 0.0.2 → 0.0.3

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