services 0.2.8 → 0.2.9

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: 7b3bc560efbbf48e28224e43a9b0c38a94c0e3e3
4
- data.tar.gz: 139c86d2e85f88781eb1999fb80123a18c66e009
3
+ metadata.gz: b6a69a25c27cff265025953ddd3dfaa6f04a4f7e
4
+ data.tar.gz: fd175797287181892a619c61dd195d1062919ad4
5
5
  SHA512:
6
- metadata.gz: 48140e2d271a70fba7de535c1ce8249937e25013c02640265f877e3f6d9f2e8c81ed4288abfd30ba3eeecdce0a76b5a0a1e2e2191825f54038fc62591281650c
7
- data.tar.gz: 94d5b1d545f3d3b72e1e343579f84452219f03ba6528380fbf8b9d635eaf944774ea127cd8f23dd67a116fef55a5d3972728e4afe35c847992ae59ac446e7fd6
6
+ metadata.gz: 1bb62070e8e679707ab12e04590a80a90e61895f02f2aca643248040f57d60257de7e29bc34dc306f89382f2fbf46c5e918a4e0055a52948f4e8a517c0bfe68c
7
+ data.tar.gz: 772463884aa0a6ddd64bd5ab83fa311c9881bd4e8156a5fb61253a4ed2c3d0529d5570d842ea99327a92d7adbc42e3f23239d6b05707fe200b8fdccad6a4de87
@@ -3,7 +3,7 @@ module Services
3
3
  module CallLogger
4
4
  def call(*args)
5
5
  log "START with args #{args}"
6
- log "CALLED BY #{caller}"
6
+ log "CALLED BY #{caller || '(not found)'}"
7
7
  start = Time.now
8
8
  begin
9
9
  result = super
@@ -38,10 +38,16 @@ module Services
38
38
  end
39
39
 
40
40
  def caller
41
- caller_location = caller_locations(2, 1).first
42
- caller_path = caller_location.path
43
- caller_path = caller_path.sub(%r(\A#{Regexp.escape Rails.root.to_s}/), '') if defined?(Rails)
44
- [caller_path, caller_location.lineno].join(':')
41
+ caller_location = caller_locations(1, 10).detect do |location|
42
+ location.path !~ /\A#{Regexp.escape File.expand_path('../..', __FILE__)}/
43
+ end
44
+ if caller_location.nil?
45
+ nil
46
+ else
47
+ caller_path = caller_location.path
48
+ caller_path = caller_path.sub(%r(\A#{Regexp.escape Rails.root.to_s}/), '') if defined?(Rails)
49
+ [caller_path, caller_location.lineno].join(':')
50
+ end
45
51
  end
46
52
  end
47
53
  end
@@ -6,35 +6,66 @@ module Services
6
6
  uniqueness
7
7
  ).join(':')
8
8
 
9
+ ON_ERROR = %i(
10
+ fail
11
+ ignore
12
+ reschedule
13
+ )
14
+
15
+ MAX_RETRIES = 10
16
+ ONE_HOUR = 60 * 60
17
+
9
18
  def self.prepended(mod)
10
19
  mod.const_set :NotUniqueError, Class.new(mod::Error)
11
20
  end
12
21
 
13
- def check_uniqueness!(*args)
14
- if args.empty?
15
- raise 'Could not find uniqueness args' unless defined?(@uniqueness_args)
16
- args = @uniqueness_args
17
- end
18
- new_uniqueness_key = uniqueness_key(args)
19
- if similar_service_id = Services.configuration.redis.get(new_uniqueness_key)
20
- raise self.class::NotUniqueError, "Service #{self.class} with uniqueness args #{args} is not unique, a similar service is already running: #{similar_service_id}"
22
+ def check_uniqueness!(*args, on_error: :fail)
23
+ raise "on_error must be one of #{ON_ERROR.join(', ')}, but was #{on_error}" unless ON_ERROR.include?(on_error.to_sym)
24
+ raise 'Service args not found.' if @service_args.nil?
25
+ @uniqueness_args = args.empty? ? @service_args : args
26
+ new_uniqueness_key = uniqueness_key(@uniqueness_args)
27
+ raise "A uniqueness key with args #{@uniqueness_args.inspect} already exists." if @uniqueness_keys && @uniqueness_keys.include?(new_uniqueness_key)
28
+ if @similar_service_id = Services.configuration.redis.get(new_uniqueness_key)
29
+ case on_error.to_sym
30
+ when :ignore
31
+ false
32
+ when :fail
33
+ raise_non_unique_error
34
+ when :reschedule
35
+ error_count = (Services.configuration.redis.get(error_count_key) || 0).to_i
36
+ if error_count >= MAX_RETRIES
37
+ raise_non_unique_error
38
+ else
39
+ error_count += 1
40
+ self.class.perform_in retry_delay(error_count), @service_args
41
+ Services.configuration.redis.setex error_count_key, retry_delay(error_count) + ONE_HOUR, error_count
42
+ false
43
+ end
44
+ end
21
45
  else
22
46
  @uniqueness_keys ||= []
23
- raise "A uniqueness key with args #{args.inspect} already exists." if @uniqueness_keys.include?(new_uniqueness_key)
24
47
  @uniqueness_keys << new_uniqueness_key
25
- Services.configuration.redis.setex new_uniqueness_key, 60 * 60, @id
48
+ Services.configuration.redis.setex new_uniqueness_key, ONE_HOUR, @id
49
+ true
26
50
  end
27
51
  end
28
52
 
29
53
  def call(*args)
30
- @uniqueness_args = args
54
+ @service_args = args
31
55
  super
32
56
  ensure
33
57
  Services.configuration.redis.del @uniqueness_keys unless @uniqueness_keys.nil? || @uniqueness_keys.empty?
58
+ Services.configuration.redis.del error_count_key
34
59
  end
35
60
 
36
61
  private
37
62
 
63
+ def raise_non_unique_error(retried = false)
64
+ message = "Service #{self.class} #{@id} with uniqueness args #{@uniqueness_args} is not unique, a similar service is already running: #{@similar_service_id}."
65
+ message << " The service has been retried #{MAX_RETRIES} times."
66
+ raise self.class::NotUniqueError, message
67
+ end
68
+
38
69
  def uniqueness_key(args)
39
70
  [
40
71
  KEY_PREFIX,
@@ -43,6 +74,20 @@ module Services
43
74
  key << Digest::MD5.hexdigest(args.to_s) unless args.empty?
44
75
  end.join(':')
45
76
  end
77
+
78
+ def error_count_key
79
+ [
80
+ KEY_PREFIX,
81
+ 'errors',
82
+ self.class.to_s
83
+ ].tap do |key|
84
+ key << Digest::MD5.hexdigest(@service_args.to_s) unless @service_args.empty?
85
+ end.join(':')
86
+ end
87
+
88
+ def retry_delay(error_count)
89
+ (error_count ** 3) + 5
90
+ end
46
91
  end
47
92
  end
48
93
  end
@@ -1,3 +1,3 @@
1
1
  module Services
2
- VERSION = '0.2.8'
2
+ VERSION = '0.2.9'
3
3
  end
@@ -58,172 +58,6 @@ describe Services::Base do
58
58
  end
59
59
  end
60
60
 
61
- if StandardError.new.respond_to?(:cause)
62
- context 'wrapping exceptions' do
63
- it 'does not wrap service errors or subclasses' do
64
- expect do
65
- ErrorService.call
66
- end.to raise_error do |error|
67
- expect(error).to be_a(ErrorService::Error)
68
- expect(error.message).to eq('I am a service error.')
69
- expect(error.cause).to be_nil
70
- end
71
-
72
- class ServiceWithCustomError < Services::Base
73
- CustomError = Class.new(self::Error)
74
- def call
75
- raise CustomError.new('I am a custom error.')
76
- end
77
- end
78
- expect do
79
- ServiceWithCustomError.call
80
- end.to raise_error do |error|
81
- expect(error).to be_a(ServiceWithCustomError::CustomError)
82
- expect(error.message).to eq('I am a custom error.')
83
- expect(error.cause).to be_nil
84
- end
85
- end
86
-
87
- it 'wraps all other exceptions' do
88
- class ServiceWithStandardError < Services::Base
89
- def call
90
- raise 'I am a StandardError.'
91
- end
92
- end
93
- expect do
94
- ServiceWithStandardError.call
95
- end.to raise_error do |error|
96
- expect(error).to be_a(ServiceWithStandardError::Error)
97
- expect(error.message).to eq('I am a StandardError.')
98
- expect(error.cause).to be_a(StandardError)
99
- expect(error.cause.message).to eq('I am a StandardError.')
100
- end
101
-
102
- class ServiceWithCustomStandardError < Services::Base
103
- CustomStandardError = Class.new(StandardError)
104
- def call
105
- raise CustomStandardError, 'I am a custom StandardError.'
106
- end
107
- end
108
- expect do
109
- ServiceWithCustomStandardError.call
110
- end.to raise_error do |error|
111
- expect(error).to be_a(ServiceWithCustomStandardError::Error)
112
- expect(error.message).to eq('I am a custom StandardError.')
113
- expect(error.cause).to be_a(ServiceWithCustomStandardError::CustomStandardError)
114
- expect(error.cause.message).to eq('I am a custom StandardError.')
115
- end
116
- end
117
- end
118
- end
119
-
120
- context 'checking for uniqueness' do
121
- context 'when the service checks for uniqueness with the default args' do
122
- it 'raises an error when the same job is executed multiple times' do
123
- wait_for_job_to_run UniqueService do
124
- 3.times do
125
- expect { UniqueService.call }.to raise_error(UniqueService::NotUniqueError)
126
- end
127
- end
128
- end
129
- end
130
-
131
- context 'when the service checks for uniqueness with custom args' do
132
- it 'raises an error when a job with the same custom args is executed multiple times' do
133
- wait_for_job_to_run UniqueWithCustomArgsService, 'foo', 'bar', 'baz' do
134
- 3.times do
135
- expect { UniqueWithCustomArgsService.call('foo', 'bar', 'pelle') }.to raise_error(UniqueWithCustomArgsService::NotUniqueError)
136
- end
137
- expect { UniqueWithCustomArgsService.call('foo', 'baz', 'pelle') }.to_not raise_error
138
- end
139
- end
140
- end
141
-
142
- context 'when the service checks for uniqueness multiple times' do
143
- let(:args) { %w(foo bar baz) }
144
-
145
- it 'raises an error when one of the checks fails' do
146
- wait_for_job_to_run UniqueMultipleService, *args do
147
- args.each do |arg|
148
- 3.times do
149
- expect { UniqueMultipleService.call(arg) }.to raise_error(UniqueMultipleService::NotUniqueError)
150
- end
151
- end
152
- expect { UniqueMultipleService.call('pelle') }.to_not raise_error
153
- end
154
- end
155
-
156
- it 'does not leave any Redis keys behind' do
157
- expect do
158
- wait_for_job_to_run_and_finish UniqueMultipleService, *args do
159
- args.each do |arg|
160
- UniqueMultipleService.call(arg) rescue nil
161
- end
162
- UniqueMultipleService.call('pelle')
163
- end
164
- end.to_not change {
165
- Services.configuration.redis.keys("*#{Services::Base::UniquenessChecker::KEY_PREFIX}*").count
166
- }
167
- end
168
- end
169
-
170
- context 'when the service was not set to check for uniqueness' do
171
- it 'does not raise an error when the same job is executed twice' do
172
- wait_for_job_to_run NonUniqueService do
173
- expect { NonUniqueService.call }.to_not raise_error
174
- end
175
- end
176
- end
177
- end
178
-
179
- context 'logging' do
180
- it 'logs start with args and end with duration' do
181
- service = EmptyService.new
182
- logs = []
183
- allow(service).to receive(:log) do |message, *|
184
- logs << message
185
- end
186
- service.call 'foo', 'bar'
187
- expect(logs.first).to eq('START with args ["foo", "bar"]')
188
- expect(logs.last).to eq('END after 0.0 seconds')
189
- end
190
-
191
- it 'logs the caller' do
192
- service_calling_service, called_service = ServiceCallingService.new, EmptyService.new
193
- logs = []
194
- allow(called_service).to receive(:log) do |message, *|
195
- logs << message
196
- end
197
-
198
- # When Rails is not defined, the complete caller path should be logged
199
- service_calling_service.call called_service
200
- expect(logs).to include(/\ACALLED BY #{Regexp.escape(PROJECT_ROOT.join(SERVICES_PATH).to_s)}:\d+/)
201
-
202
- # When Rails is defined, only the caller path relative to Rails.root is logged
203
- class Rails
204
- def self.root; PROJECT_ROOT; end
205
- end
206
- logs = []
207
- service_calling_service.call called_service
208
- expect(logs).to include(/\ACALLED BY #{Regexp.escape(SERVICES_PATH)}:\d+/)
209
- Object.send :remove_const, :Rails
210
- end
211
-
212
- if RUBY_VERSION > '2.1'
213
- it 'logs exceptions and exception causes' do
214
- service = NestedExceptionService.new
215
- logs = []
216
- allow(service).to receive(:log) do |message, *|
217
- logs << message
218
- end
219
- expect { service.call }.to raise_error(NestedExceptionService::Error)
220
- %w(NestedError1 NestedError2).each do |error|
221
- expect(logs).to include(/\Acaused by: NestedExceptionService::#{error}/)
222
- end
223
- end
224
- end
225
- end
226
-
227
61
  context 'when executed asynchronously' do
228
62
  it 'finds its own worker' do
229
63
  3.times { OwnWorkerService.perform_async }
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Services::Base::CallLogger do
4
+ it 'logs start with args and end with duration' do
5
+ service = EmptyService.new
6
+ logs = []
7
+ allow(service).to receive(:log) do |message, *|
8
+ logs << message
9
+ end
10
+ service.call 'foo', 'bar'
11
+ expect(logs.first).to eq('START with args ["foo", "bar"]')
12
+ expect(logs.last).to eq('END after 0.0 seconds')
13
+ end
14
+
15
+ it 'logs the caller' do
16
+ service_calling_service, called_service = ServiceCallingService.new, EmptyService.new
17
+ logs = []
18
+ allow(called_service).to receive(:log) do |message, *|
19
+ logs << message
20
+ end
21
+
22
+ # When Rails is not defined, the complete caller path should be logged
23
+ service_calling_service.call called_service
24
+ expect(logs).to include(/\ACALLED BY #{Regexp.escape PROJECT_ROOT.join(TEST_SERVICES_PATH).to_s}:\d+/)
25
+
26
+ # When Rails is defined, only the caller path relative to Rails.root is logged
27
+ class Rails
28
+ def self.root; PROJECT_ROOT; end
29
+ end
30
+ logs = []
31
+ service_calling_service.call called_service
32
+ expect(logs).to include(/\ACALLED BY #{Regexp.escape TEST_SERVICES_PATH.to_s}:\d+/)
33
+ Object.send :remove_const, :Rails
34
+
35
+ # Caller paths from services lib folder should be filtered
36
+ require 'services/call_proxy'
37
+ logs = []
38
+ Services::CallProxy.call(called_service, :call)
39
+ expect(logs).to include(/\ACALLED BY #{Regexp.escape __FILE__}:\d+/)
40
+ end
41
+
42
+ if RUBY_VERSION > '2.1'
43
+ it 'logs exceptions and exception causes' do
44
+ service = NestedExceptionService.new
45
+ logs = []
46
+ allow(service).to receive(:log) do |message, *|
47
+ logs << message
48
+ end
49
+ expect { service.call }.to raise_error(service.class::Error)
50
+ %w(NestedError1 NestedError2).each do |error|
51
+ expect(logs).to include(/\Acaused by: #{service.class}::#{error}/)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Services::Base::ExceptionWrapper do
4
+ if StandardError.new.respond_to?(:cause)
5
+ it 'does not wrap service errors or subclasses' do
6
+ expect do
7
+ ErrorService.call
8
+ end.to raise_error do |error|
9
+ expect(error).to be_a(ErrorService::Error)
10
+ expect(error.message).to eq('I am a service error.')
11
+ expect(error.cause).to be_nil
12
+ end
13
+
14
+ class ServiceWithCustomError < Services::Base
15
+ CustomError = Class.new(self::Error)
16
+ def call
17
+ raise CustomError.new('I am a custom error.')
18
+ end
19
+ end
20
+ expect do
21
+ ServiceWithCustomError.call
22
+ end.to raise_error do |error|
23
+ expect(error).to be_a(ServiceWithCustomError::CustomError)
24
+ expect(error.message).to eq('I am a custom error.')
25
+ expect(error.cause).to be_nil
26
+ end
27
+ end
28
+
29
+ it 'wraps all other exceptions' do
30
+ class ServiceWithStandardError < Services::Base
31
+ def call
32
+ raise 'I am a StandardError.'
33
+ end
34
+ end
35
+ expect do
36
+ ServiceWithStandardError.call
37
+ end.to raise_error do |error|
38
+ expect(error).to be_a(ServiceWithStandardError::Error)
39
+ expect(error.message).to eq('I am a StandardError.')
40
+ expect(error.cause).to be_a(StandardError)
41
+ expect(error.cause.message).to eq('I am a StandardError.')
42
+ end
43
+
44
+ class ServiceWithCustomStandardError < Services::Base
45
+ CustomStandardError = Class.new(StandardError)
46
+ def call
47
+ raise CustomStandardError, 'I am a custom StandardError.'
48
+ end
49
+ end
50
+ expect do
51
+ ServiceWithCustomStandardError.call
52
+ end.to raise_error do |error|
53
+ expect(error).to be_a(ServiceWithCustomStandardError::Error)
54
+ expect(error.message).to eq('I am a custom StandardError.')
55
+ expect(error.cause).to be_a(ServiceWithCustomStandardError::CustomStandardError)
56
+ expect(error.cause.message).to eq('I am a custom StandardError.')
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples 'checking the uniqueness properly' do
4
+ it 'notices when the same job is executed multiple times' do
5
+ # Check that error is raised when on_error is "fail"
6
+ wait_for_job_to_run_and_finish service, *args, 'fail', true do
7
+ if defined?(fail_args)
8
+ 3.times do
9
+ fail_args.each do |fail_arg_group|
10
+ expect { service.call(*fail_arg_group, 'fail', false) }.to raise_error(service::NotUniqueError)
11
+ end
12
+ end
13
+ end
14
+ if defined?(pass_args)
15
+ 3.times do
16
+ pass_args.each do |pass_arg_group|
17
+ expect { service.call(*pass_arg_group, 'fail', false) }.to_not raise_error
18
+ end
19
+ end
20
+ end
21
+
22
+ # Check that no error is raised when on_error is "ignore"
23
+ if defined?(fail_args)
24
+ 3.times do
25
+ fail_args.each do |fail_arg_group|
26
+ expect { service.call(*fail_arg_group, 'ignore', false) }.to_not raise_error
27
+ end
28
+ end
29
+ end
30
+ if defined?(pass_args)
31
+ 3.times do
32
+ pass_args.each do |pass_arg_group|
33
+ expect { service.call(*pass_arg_group, 'ignore', false) }.to_not raise_error
34
+ end
35
+ end
36
+ end
37
+
38
+ # Check that service is rescheduled when on_error is "reschedule"
39
+ if defined?(fail_args)
40
+ 3.times do
41
+ fail_args.each do |fail_arg_group|
42
+ expect(service).to receive(:perform_in).with(an_instance_of(Fixnum), fail_arg_group + (['reschedule', false]))
43
+ service.call(*fail_arg_group, 'reschedule', false)
44
+ end
45
+ end
46
+ end
47
+ if defined?(pass_args)
48
+ 3.times do
49
+ pass_args.each do |pass_arg_group|
50
+ expect { service.call(*pass_arg_group, 'reschedule', false) }.to_not raise_error
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ describe Services::Base::UniquenessChecker do
59
+ context 'when the service checks for uniqueness with the default args' do
60
+ it_behaves_like 'checking the uniqueness properly' do
61
+ let(:service) { UniqueService }
62
+ let(:args) { [] }
63
+ let(:fail_args) { [] }
64
+ let(:keys_after_start) { 1 }
65
+ end
66
+ end
67
+
68
+ context 'when the service checks for uniqueness with custom args' do
69
+ it_behaves_like 'checking the uniqueness properly' do
70
+ let(:service) { UniqueWithCustomArgsService }
71
+ let(:args) { %w(foo bar baz) }
72
+ let(:fail_args) { [%w(foo bar pelle)] }
73
+ let(:pass_args) { [%w(foo baz pelle)] }
74
+ let(:keys_after_start) { 1 }
75
+ end
76
+ end
77
+
78
+ context 'when the service checks for uniqueness multiple times' do
79
+ it_behaves_like 'checking the uniqueness properly' do
80
+ let(:service) { UniqueMultipleService }
81
+ let(:args) { %w(foo bar baz) }
82
+ let(:fail_args) { args.map { |arg| [arg] } }
83
+ let(:pass_args) { [%w(pelle)] }
84
+ let(:keys_after_start) { 3 }
85
+ end
86
+ end
87
+
88
+ context 'when the service does not check for uniqueness' do
89
+ it_behaves_like 'checking the uniqueness properly' do
90
+ let(:service) { NonUniqueService }
91
+ let(:args) { [] }
92
+ let(:pass_args) { [] }
93
+ let(:keys_after_start) { 0 }
94
+ end
95
+ end
96
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,15 +4,16 @@ require 'redis'
4
4
  require 'sidekiq'
5
5
 
6
6
  require_relative '../lib/services'
7
- require_relative 'support/helpers'
8
7
 
9
- SERVICES_PATH = File.join('support', 'test_services.rb')
10
- require_relative SERVICES_PATH
8
+ PROJECT_ROOT = Pathname.new(File.expand_path('../..', __FILE__))
9
+ TEST_SERVICES_PATH = Pathname.new(File.join('spec', 'support', 'test_services.rb'))
10
+ support_dir = Pathname.new(File.expand_path('../support', __FILE__))
11
+ log_dir = support_dir.join('log')
11
12
 
12
- PROJECT_ROOT = Pathname.new(File.expand_path('..', __FILE__))
13
+ CALL_PROXY_SOURCE = support_dir.join('call_proxy.rb')
14
+ CALL_PROXY_DESTINATION = PROJECT_ROOT.join('lib', 'services', 'call_proxy.rb')
13
15
 
14
- support_dir = Pathname.new(File.expand_path('../support', __FILE__))
15
- log_dir = support_dir.join('log')
16
+ Dir[support_dir.join('**', '*.rb')].each { |f| require f }
16
17
 
17
18
  redis_port = 6379
18
19
  redis_pidfile = support_dir.join('redis.pid')
@@ -65,9 +66,15 @@ RSpec.configure do |config|
65
66
  pidfile: sidekiq_pidfile
66
67
  }
67
68
  system "bundle exec sidekiq #{options_hash_to_string(sidekiq_options)}"
69
+
70
+ # Copy call proxy
71
+ FileUtils.cp CALL_PROXY_SOURCE, CALL_PROXY_DESTINATION
68
72
  end
69
73
 
70
74
  config.after :suite do
75
+ # Delete call proxy
76
+ FileUtils.rm CALL_PROXY_DESTINATION
77
+
71
78
  # Stop Sidekiq
72
79
  system "bundle exec sidekiqctl stop #{sidekiq_pidfile} #{sidekiq_timeout}"
73
80
  while File.exist?(sidekiq_pidfile)
@@ -0,0 +1,11 @@
1
+ # This is just a helper file to ensure that
2
+ # the services lib folder appears in the caller
3
+ # locations.
4
+
5
+ module Services
6
+ class CallProxy
7
+ def self.call(object, method)
8
+ object.public_send method
9
+ end
10
+ end
11
+ end
@@ -65,31 +65,31 @@ class ServiceCallingService < Services::Base
65
65
  end
66
66
 
67
67
  class UniqueService < Services::Base
68
- def call
69
- check_uniqueness!
70
- sleep 0.5
68
+ def call(on_error, sleep)
69
+ check_uniqueness! on_error: on_error
70
+ sleep 0.5 if sleep
71
71
  end
72
72
  end
73
73
 
74
74
  class UniqueWithCustomArgsService < Services::Base
75
- def call(uniqueness_arg1, uniqueness_arg2, ignore_arg)
76
- check_uniqueness! uniqueness_arg1, uniqueness_arg2
77
- sleep 0.5
75
+ def call(uniqueness_arg1, uniqueness_arg2, ignore_arg, on_error, sleep)
76
+ check_uniqueness! uniqueness_arg1, uniqueness_arg2, on_error: on_error
77
+ sleep 0.5 if sleep
78
78
  end
79
79
  end
80
80
 
81
81
  class UniqueMultipleService < Services::Base
82
- def call(*args)
82
+ def call(*args, on_error, sleep)
83
83
  args.each do |arg|
84
- check_uniqueness! arg
84
+ check_uniqueness! arg, on_error: on_error
85
85
  end
86
- sleep 0.5
86
+ sleep 0.5 if sleep
87
87
  end
88
88
  end
89
89
 
90
90
  class NonUniqueService < Services::Base
91
- def call
92
- sleep 0.5
91
+ def call(on_error, sleep)
92
+ sleep 0.5 if sleep
93
93
  end
94
94
  end
95
95
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: services
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.9
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-08-24 00:00:00.000000000 Z
11
+ date: 2014-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -146,7 +146,11 @@ files:
146
146
  - lib/services/version.rb
147
147
  - services.gemspec
148
148
  - spec/services/base_spec.rb
149
+ - spec/services/modules/call_logger_spec.rb
150
+ - spec/services/modules/exception_wrapper_spec.rb
151
+ - spec/services/modules/uniqueness_checker_spec.rb
149
152
  - spec/spec_helper.rb
153
+ - spec/support/call_proxy.rb
150
154
  - spec/support/helpers.rb
151
155
  - spec/support/log/.gitkeep
152
156
  - spec/support/redis-cli
@@ -178,7 +182,11 @@ specification_version: 4
178
182
  summary: ''
179
183
  test_files:
180
184
  - spec/services/base_spec.rb
185
+ - spec/services/modules/call_logger_spec.rb
186
+ - spec/services/modules/exception_wrapper_spec.rb
187
+ - spec/services/modules/uniqueness_checker_spec.rb
181
188
  - spec/spec_helper.rb
189
+ - spec/support/call_proxy.rb
182
190
  - spec/support/helpers.rb
183
191
  - spec/support/log/.gitkeep
184
192
  - spec/support/redis-cli