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 +4 -4
- data/README.md +12 -0
- data/apisync-rails.gemspec +1 -2
- data/lib/apisync/active_record_extension.rb +4 -8
- data/lib/apisync/rails.rb +8 -1
- data/lib/apisync/rails/extensions.rb +21 -0
- data/lib/apisync/rails/http.rb +23 -2
- data/lib/apisync/rails/model.rb +29 -4
- data/lib/apisync/rails/sync_model_job/sidekiq.rb +43 -0
- data/lib/apisync/rails/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ea28569d7864193a7d68b89a0a7429e0e7e8d9a
|
4
|
+
data.tar.gz: ed8b404b84538f8095d64e83362b1edddcd2fb8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/apisync-rails.gemspec
CHANGED
@@ -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
|
-
|
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
|
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
|
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 :
|
31
|
-
after_commit :
|
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
|
data/lib/apisync/rails.rb
CHANGED
@@ -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
|
data/lib/apisync/rails/http.rb
CHANGED
@@ -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
|
data/lib/apisync/rails/model.rb
CHANGED
@@ -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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
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.
|
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-
|
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:
|
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:
|
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:
|