services 0.2.8 → 0.2.9

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: 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