services 0.1.7 → 0.2.1
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/.gitignore +1 -1
- data/lib/services.rb +3 -3
- data/lib/services/base.rb +1 -1
- data/lib/services/{base → modules}/call_logger.rb +9 -2
- data/lib/services/{base → modules}/exception_wrapper.rb +0 -0
- data/lib/services/modules/uniqueness_checker.rb +40 -0
- data/lib/services/version.rb +1 -1
- data/spec/services/base_spec.rb +14 -16
- data/spec/spec_helper.rb +1 -1
- data/spec/support/{logs → log}/.gitkeep +0 -0
- data/spec/support/test_services.rb +8 -2
- metadata +27 -27
- data/lib/services/base/uniqueness_checker.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5351a6064b1da2a70dd0ce2fba47810bd7deb0f5
|
4
|
+
data.tar.gz: d73f3b3835195a720b4c370d15a67a017ca49a2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdeb74e291c384e338a04acf1c0036788a84bf87813ff25cae0c19b83d3157cb2b749fb09949f4f14a413fe6e90d6c1045516f86f776c176c45a52bbb147e310
|
7
|
+
data.tar.gz: 1ef404e5414c1fb352336b038861884404fac189dece2ce97d2261b81aee00453341e64ad85f1cb256e79e2adffcc0759ca9758de3aa2d1772877a10dd03d23c
|
data/.gitignore
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
Gemfile.lock
|
2
|
-
spec/support/
|
2
|
+
spec/support/log/**/*.log
|
data/lib/services.rb
CHANGED
@@ -18,8 +18,8 @@ begin
|
|
18
18
|
require_relative 'services/asyncable'
|
19
19
|
rescue Services::BackgroundProcessorNotFound
|
20
20
|
end
|
21
|
-
require_relative 'services/
|
22
|
-
require_relative 'services/
|
23
|
-
require_relative 'services/
|
21
|
+
require_relative 'services/modules/call_logger'
|
22
|
+
require_relative 'services/modules/exception_wrapper'
|
23
|
+
require_relative 'services/modules/uniqueness_checker'
|
24
24
|
require_relative 'services/base'
|
25
25
|
require_relative 'services/railtie' if defined?(Rails)
|
data/lib/services/base.rb
CHANGED
@@ -9,7 +9,7 @@ module Services
|
|
9
9
|
subclass.const_set :Error, Class.new(StandardError)
|
10
10
|
subclass.send :include, Rails.application.routes.url_helpers if defined?(Rails)
|
11
11
|
subclass.send :include, Asyncable if defined?(Asyncable)
|
12
|
-
subclass.send :prepend, CallLogger, UniquenessChecker
|
12
|
+
subclass.send :prepend, CallLogger, ExceptionWrapper, UniquenessChecker
|
13
13
|
end
|
14
14
|
|
15
15
|
delegate :call, to: :new
|
@@ -8,8 +8,15 @@ module Services
|
|
8
8
|
result = super
|
9
9
|
rescue StandardError => e
|
10
10
|
log "#{e.class}: #{e.message}"
|
11
|
-
e.
|
12
|
-
log
|
11
|
+
if e.respond_to?(:cause) && !e.cause.nil?
|
12
|
+
log "caused by: #{e.cause.class}: #{e.cause.message}"
|
13
|
+
e.cause.backtrace.each do |line|
|
14
|
+
log line
|
15
|
+
end
|
16
|
+
else
|
17
|
+
e.backtrace.each do |line|
|
18
|
+
log line
|
19
|
+
end
|
13
20
|
end
|
14
21
|
raise e
|
15
22
|
ensure
|
File without changes
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Services
|
2
|
+
class Base
|
3
|
+
module UniquenessChecker
|
4
|
+
def self.prepended(mod)
|
5
|
+
mod.const_set :NotUniqueError, Class.new(mod::Error)
|
6
|
+
end
|
7
|
+
|
8
|
+
def check_uniqueness!(*args)
|
9
|
+
raise 'A variable named @uniqueness_key is already defined. Have you called `check_uniqueness!` twice?' if defined?(@uniqueness_key)
|
10
|
+
raise 'Could not find @uniqueness_all_args' unless defined?(@uniqueness_all_args)
|
11
|
+
args = @uniqueness_all_args if args.empty?
|
12
|
+
@uniqueness_key = uniqueness_key(args)
|
13
|
+
if similar_service_id = Services.configuration.redis.get(@uniqueness_key)
|
14
|
+
raise self.class::NotUniqueError, "Service #{self.class} with args #{args} is not unique, a similar service is already running: #{similar_service_id}"
|
15
|
+
else
|
16
|
+
Services.configuration.redis.setex @uniqueness_key, 60 * 60, @id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(*args)
|
21
|
+
@uniqueness_all_args = args
|
22
|
+
super
|
23
|
+
ensure
|
24
|
+
Services.configuration.redis.del @uniqueness_key if defined?(@uniqueness_key)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def uniqueness_key(args)
|
30
|
+
[
|
31
|
+
'services',
|
32
|
+
'uniqueness',
|
33
|
+
self.class.to_s
|
34
|
+
].tap do |key|
|
35
|
+
key << Digest::MD5.hexdigest(args.to_s) unless args.empty?
|
36
|
+
end.join(':')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/services/version.rb
CHANGED
data/spec/services/base_spec.rb
CHANGED
@@ -66,30 +66,32 @@ describe Services::Base do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
context 'checking for uniqueness' do
|
69
|
-
context 'when the service was set to check for uniqueness' do
|
69
|
+
context 'when the service was set to check for uniqueness with the default args' do
|
70
70
|
it 'raises an error when the same job is executed twice' do
|
71
71
|
wait_for_job_to_run UniqueService.perform_async
|
72
|
-
expect
|
73
|
-
|
74
|
-
|
72
|
+
expect { UniqueService.call }.to raise_error(UniqueService::NotUniqueError)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when the service was set to check for uniqueness with custom args' do
|
77
|
+
it 'raises an error when a job with the same custom args is executed twice' do
|
78
|
+
wait_for_job_to_run UniqueWithCustomArgsService.perform_async('foo', 'bar', 'baz')
|
79
|
+
expect { UniqueWithCustomArgsService.call('foo', 'bar', 'pelle') }.to raise_error(UniqueWithCustomArgsService::NotUniqueError)
|
80
|
+
expect { UniqueWithCustomArgsService.call('foo', 'baz', 'pelle') }.to_not raise_error
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
78
84
|
context 'when the service was not set to check for uniqueness' do
|
79
85
|
it 'does not raise an error when the same job is executed twice' do
|
80
86
|
wait_for_job_to_run NonUniqueService.perform_async
|
81
|
-
expect
|
82
|
-
NonUniqueService.call
|
83
|
-
end.to_not raise_error
|
87
|
+
expect { NonUniqueService.call }.to_not raise_error
|
84
88
|
end
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
88
92
|
context 'when executed asynchronously' do
|
89
93
|
it 'finds its own worker' do
|
90
|
-
3.times
|
91
|
-
OwnWorkerService.perform_async
|
92
|
-
end
|
94
|
+
3.times { OwnWorkerService.perform_async }
|
93
95
|
jid = OwnWorkerService.perform_async
|
94
96
|
own_worker_data = wait_for { Services.configuration.redis.get(jid) }
|
95
97
|
own_worker_json = JSON.parse(own_worker_data)
|
@@ -97,16 +99,12 @@ describe Services::Base do
|
|
97
99
|
end
|
98
100
|
|
99
101
|
it 'finds its sibling workers' do
|
100
|
-
sibling_worker_jids = (1..3).map
|
101
|
-
SiblingWorkersService.perform_async
|
102
|
-
end
|
102
|
+
sibling_worker_jids = (1..3).map { SiblingWorkersService.perform_async }
|
103
103
|
jid = SiblingWorkersService.perform_async
|
104
104
|
sibling_worker_data = wait_for { Services.configuration.redis.get(jid) }
|
105
105
|
sibling_worker_json = JSON.parse(sibling_worker_data)
|
106
106
|
expect(sibling_worker_json.size).to eq(3)
|
107
|
-
expected_sibling_worker_jids = sibling_worker_json.map
|
108
|
-
work['payload']['jid']
|
109
|
-
end
|
107
|
+
expected_sibling_worker_jids = sibling_worker_json.map { |_, _, work| work['payload']['jid'] }
|
110
108
|
expect(expected_sibling_worker_jids).to match_array(sibling_worker_jids)
|
111
109
|
end
|
112
110
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,7 +7,7 @@ require_relative 'support/test_services'
|
|
7
7
|
require_relative 'support/helpers'
|
8
8
|
|
9
9
|
support_dir = Pathname.new(File.expand_path('../support', __FILE__))
|
10
|
-
log_dir = support_dir.join('
|
10
|
+
log_dir = support_dir.join('log')
|
11
11
|
|
12
12
|
redis_port = 6379
|
13
13
|
redis_pidfile = support_dir.join('redis.pid')
|
File without changes
|
@@ -1,7 +1,13 @@
|
|
1
1
|
class UniqueService < Services::Base
|
2
|
-
check_uniqueness!
|
3
|
-
|
4
2
|
def call
|
3
|
+
check_uniqueness!
|
4
|
+
sleep 0.5
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class UniqueWithCustomArgsService < Services::Base
|
9
|
+
def call(uniqueness_arg1, uniqueness_arg2, ignore_arg)
|
10
|
+
check_uniqueness! uniqueness_arg1, uniqueness_arg2
|
5
11
|
sleep 0.5
|
6
12
|
end
|
7
13
|
end
|
metadata
CHANGED
@@ -1,125 +1,125 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: services
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Meurer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: guard-rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '4.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '3.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: sidekiq
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '3.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: redis
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '3.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: tries
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - ~>
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - ~>
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rails
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: 3.0.0
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 3.0.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: gem_config
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - ~>
|
115
|
+
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0.3'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - ~>
|
122
|
+
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.3'
|
125
125
|
description: ''
|
@@ -128,8 +128,8 @@ executables: []
|
|
128
128
|
extensions: []
|
129
129
|
extra_rdoc_files: []
|
130
130
|
files:
|
131
|
-
- .gitignore
|
132
|
-
- .travis.yml
|
131
|
+
- ".gitignore"
|
132
|
+
- ".travis.yml"
|
133
133
|
- Gemfile
|
134
134
|
- Guardfile
|
135
135
|
- LICENSE.txt
|
@@ -138,17 +138,17 @@ files:
|
|
138
138
|
- lib/services.rb
|
139
139
|
- lib/services/asyncable.rb
|
140
140
|
- lib/services/base.rb
|
141
|
-
- lib/services/base/call_logger.rb
|
142
|
-
- lib/services/base/exception_wrapper.rb
|
143
|
-
- lib/services/base/uniqueness_checker.rb
|
144
141
|
- lib/services/logger.rb
|
142
|
+
- lib/services/modules/call_logger.rb
|
143
|
+
- lib/services/modules/exception_wrapper.rb
|
144
|
+
- lib/services/modules/uniqueness_checker.rb
|
145
145
|
- lib/services/railtie.rb
|
146
146
|
- lib/services/version.rb
|
147
147
|
- services.gemspec
|
148
148
|
- spec/services/base_spec.rb
|
149
149
|
- spec/spec_helper.rb
|
150
150
|
- spec/support/helpers.rb
|
151
|
-
- spec/support/
|
151
|
+
- spec/support/log/.gitkeep
|
152
152
|
- spec/support/redis-cli
|
153
153
|
- spec/support/redis-server
|
154
154
|
- spec/support/test_services.rb
|
@@ -162,12 +162,12 @@ require_paths:
|
|
162
162
|
- lib
|
163
163
|
required_ruby_version: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
|
-
- -
|
165
|
+
- - ">="
|
166
166
|
- !ruby/object:Gem::Version
|
167
167
|
version: '0'
|
168
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
169
|
requirements:
|
170
|
-
- -
|
170
|
+
- - ">="
|
171
171
|
- !ruby/object:Gem::Version
|
172
172
|
version: '0'
|
173
173
|
requirements: []
|
@@ -180,7 +180,7 @@ test_files:
|
|
180
180
|
- spec/services/base_spec.rb
|
181
181
|
- spec/spec_helper.rb
|
182
182
|
- spec/support/helpers.rb
|
183
|
-
- spec/support/
|
183
|
+
- spec/support/log/.gitkeep
|
184
184
|
- spec/support/redis-cli
|
185
185
|
- spec/support/redis-server
|
186
186
|
- spec/support/test_services.rb
|
@@ -1,49 +0,0 @@
|
|
1
|
-
module Services
|
2
|
-
class Base
|
3
|
-
module UniquenessChecker
|
4
|
-
def self.prepended(mod)
|
5
|
-
mod.instance_eval do
|
6
|
-
def check_uniqueness?
|
7
|
-
@check_uniqueness
|
8
|
-
end
|
9
|
-
|
10
|
-
def check_uniqueness!
|
11
|
-
@check_uniqueness = true
|
12
|
-
end
|
13
|
-
end
|
14
|
-
mod.const_set :NotUniqueError, Class.new(mod::Error)
|
15
|
-
end
|
16
|
-
|
17
|
-
def call(*args)
|
18
|
-
if self.class.check_uniqueness?
|
19
|
-
key = unique_key(args)
|
20
|
-
if Services.configuration.redis.exists(key)
|
21
|
-
raise self.class::NotUniqueError
|
22
|
-
else
|
23
|
-
Services.configuration.redis.setex key, 60 * 60, Time.now
|
24
|
-
begin
|
25
|
-
super
|
26
|
-
ensure
|
27
|
-
Services.configuration.redis.del key
|
28
|
-
end
|
29
|
-
end
|
30
|
-
else
|
31
|
-
super
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def unique_key(args)
|
38
|
-
# TODO: symbolize keys in hashes in args and sort hashes by key
|
39
|
-
args = args.dup
|
40
|
-
key = [
|
41
|
-
'services',
|
42
|
-
'uniqueness',
|
43
|
-
self.class.to_s,
|
44
|
-
Digest::MD5.hexdigest(args.to_s)
|
45
|
-
].join(':')
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|