expeditor 0.4.0 → 0.5.0

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: 2380a72a4938ad53fc206f4e155805d90568477f
4
- data.tar.gz: e5ee71ae7e689318b764c47e969e16983330846a
3
+ metadata.gz: 5ee9877b9a720af63ec3a4163d680e43d734c4b7
4
+ data.tar.gz: 8707da47bb651151d0c9a2306dcbe237e165cfe5
5
5
  SHA512:
6
- metadata.gz: 157aeae73bb32ab82848b7a97f8fa38a7c3a3f56419e59c3b2d71002c5194d5fcd2b7dce86ad7be4cad1406f2844dacf2c8f630ecf3f5e0245b018c6717beb7f
7
- data.tar.gz: 575962fba75f61364cf1f998c01c7636d100a10e0e345d68488871c6a9735ee371251e332f33221c3780987719cd8fdf725454bac56d268f1405c562934864dd
6
+ metadata.gz: 7889e85b9081df0c1aecc1039e0b2193224effe67d5169c6c100027714909b4616cb5c913a02d808bdf0e21669cdfd36ea22829dea1eb4bdc09df8dc0a8e95b5
7
+ data.tar.gz: c36f0c9b174b2043de7da8628afa6379f655d38a57538d99669e5124e24eff5e067ed96ad209e0a25ddc70cdcdaf7171c3de21c9ffbcb99e85ef78c6015b3864
@@ -2,7 +2,6 @@ language: ruby
2
2
  sudo: false
3
3
  cache: bundler
4
4
  rvm:
5
- - 2.0.0
6
5
  - 2.1
7
6
  - 2.2
8
7
  - 2.3.0
@@ -1,3 +1,12 @@
1
+ <!-- ## Master (unreleased) -->
2
+
3
+ ## 0.5.0
4
+
5
+ - Add a `current_thread` option of `Expeditor::Command#start` method to execute a task on current thread [#13](https://github.com/cookpad/expeditor/pull/13)
6
+ - Drop support for MRI 2.0.x [#15](https://github.com/cookpad/expeditor/pull/15)
7
+ - Deprecate Expeditor::Command#with_fallback. Use `set_fallback` instead [#14](https://github.com/cookpad/expeditor/pull/14)
8
+ - Do not allow set_fallback call after command is started. [#18](https://github.com/cookpad/expeditor/pull/18)
9
+
1
10
  ## 0.4.0
2
11
  - Add Expeditor::Service#current\_status [#9](https://github.com/cookpad/expeditor/issues/9)
3
12
  - Add Expeditor::Service#reset\_status! [#10](https://github.com/cookpad/expeditor/issues/10)
data/README.md CHANGED
@@ -8,6 +8,8 @@ It is inspired by [Netflix/Hystrix](https://github.com/Netflix/Hystrix).
8
8
 
9
9
  ## Installation
10
10
 
11
+ Expeditor currently supports Ruby 2.1 and higher.
12
+
11
13
  Add this line to your application's Gemfile:
12
14
 
13
15
  ```ruby
@@ -68,7 +70,7 @@ command = Expeditor::Command.new do
68
70
  end
69
71
 
70
72
  # use fallback value if command is failed
71
- command_with_fallback = command.with_fallback do |e|
73
+ command_with_fallback = command.set_fallback do |e|
72
74
  log(e)
73
75
  default_value
74
76
  end
@@ -145,6 +147,26 @@ command = Expeditor::Command.new(service: service) do
145
147
  end
146
148
  ```
147
149
 
150
+ ### synchronous execution
151
+
152
+ Use `current_thread` option of `#start`, command executes synchronous on current thread.
153
+
154
+ ```ruby
155
+ command1 = Expeditor::Command.new do
156
+ ...
157
+ end
158
+
159
+ command2 = Expeditor::Command.new do
160
+ ...
161
+ end
162
+
163
+ command1.start(current_thread: true) # blocking
164
+ command2.start(current_thread: true) # blocking
165
+
166
+ command1.get
167
+ command2.get
168
+ ```
169
+
148
170
  ## Development
149
171
 
150
172
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -24,7 +24,7 @@ command2 = Expeditor::Command.new(service: service, timeout: 0.5) do
24
24
  'command2'
25
25
  end
26
26
  # command2_d is command2 with fallback
27
- command2_d = command2.with_fallback do |e|
27
+ command2_d = command2.set_fallback do |e|
28
28
  'command2 fallback'
29
29
  end
30
30
 
@@ -44,7 +44,7 @@ command4 = Expeditor::Command.new(
44
44
  sleep 0.3
45
45
  v2 + ', ' + v3
46
46
  end
47
- command4_d = command4.with_fallback do
47
+ command4_d = command4.set_fallback do
48
48
  'command4 fallback'
49
49
  end
50
50
 
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
+ spec.required_ruby_version = '>= 2.1.0'
23
+
22
24
  spec.add_runtime_dependency "concurrent-ruby", "~> 1.0.0"
23
25
  spec.add_runtime_dependency "concurrent-ruby-ext", "~> 1.0.0"
24
26
  spec.add_runtime_dependency "retryable", "> 1.0"
@@ -14,41 +14,49 @@ module Expeditor
14
14
  @service = opts.fetch(:service, Expeditor::Services.default)
15
15
  @timeout = opts[:timeout]
16
16
  @dependencies = opts.fetch(:dependencies, [])
17
- @normal_future = initial_normal(&block)
18
- @fallback_var = nil
17
+
18
+ @normal_future = nil
19
19
  @retryable_options = Concurrent::IVar.new
20
+ @normal_block = block
21
+ @fallback_block = nil
22
+ @ivar = Concurrent::IVar.new
20
23
  end
21
24
 
22
- def start
23
- if not started?
24
- @dependencies.each(&:start)
25
+ # @param current_thread [Boolean] Execute the task on current thread(blocking)
26
+ def start(current_thread: false)
27
+ unless started?
28
+ if current_thread
29
+ prepare(Concurrent::ImmediateExecutor.new)
30
+ else
31
+ prepare
32
+ end
25
33
  @normal_future.safe_execute
26
34
  end
27
35
  self
28
36
  end
29
37
 
30
38
  # Equivalent to retryable gem options
31
- def start_with_retry(retryable_options = {})
32
- if not started?
39
+ def start_with_retry(current_thread: false, **retryable_options)
40
+ unless started?
33
41
  @retryable_options.set(retryable_options)
34
- start
42
+ start(current_thread: current_thread)
35
43
  end
36
44
  self
37
45
  end
38
46
 
39
47
  def started?
40
- @normal_future.executed?
48
+ @normal_future && @normal_future.executed?
41
49
  end
42
50
 
43
51
  def get
44
- raise NotStartedError if not started?
52
+ raise NotStartedError unless started?
45
53
  @normal_future.get_or_else do
46
- if @fallback_var && @service.fallback_enabled?
47
- @fallback_var.wait
48
- if @fallback_var.rejected?
49
- raise @fallback_var.reason
54
+ if @fallback_block && @service.fallback_enabled?
55
+ @ivar.wait
56
+ if @ivar.rejected?
57
+ raise @ivar.reason
50
58
  else
51
- @fallback_var.value
59
+ @ivar.value
52
60
  end
53
61
  else
54
62
  raise @normal_future.reason
@@ -56,16 +64,22 @@ module Expeditor
56
64
  end
57
65
  end
58
66
 
67
+ def set_fallback(&block)
68
+ if started?
69
+ raise AlreadyStartedError, "Do not allow set_fallback call after command is started"
70
+ end
71
+ reset_fallback(&block)
72
+ self
73
+ end
74
+
59
75
  def with_fallback(&block)
60
- command = self.clone
61
- command.reset_fallback(&block)
62
- command
76
+ warn 'Expeditor::Command#with_fallback is deprecated. Please use set_fallback instead'
77
+ set_fallback(&block)
63
78
  end
64
79
 
65
80
  def wait
66
- raise NotStartedError if not started?
67
- @normal_future.wait
68
- @fallback_var.wait if @fallback_var && @service.fallback_enabled?
81
+ raise NotStartedError unless started?
82
+ @ivar.wait
69
83
  end
70
84
 
71
85
  # command.on_complete do |success, value, reason|
@@ -109,25 +123,12 @@ module Expeditor
109
123
  Command.new(opts, &block).start
110
124
  end
111
125
 
112
- protected
126
+ private
113
127
 
114
128
  def reset_fallback(&block)
115
- @fallback_var = Concurrent::IVar.new
116
- @normal_future.add_observer do |_, value, reason|
117
- if reason != nil
118
- future = RichFuture.new(executor: Concurrent.global_io_executor) do
119
- success, val, reason = Concurrent::SafeTaskExecutor.new(block, rescue_exception: true).execute(reason)
120
- @fallback_var.send(:complete, success, val, reason)
121
- end
122
- future.safe_execute
123
- else
124
- @fallback_var.send(:complete, true, value, nil)
125
- end
126
- end
129
+ @fallback_block = block
127
130
  end
128
131
 
129
- private
130
-
131
132
  def breakable_block(args, &block)
132
133
  if @service.open?
133
134
  raise CircuitBreakError
@@ -181,8 +182,8 @@ module Expeditor
181
182
  # end
182
183
  # end
183
184
  # end
184
- def initial_normal(&block)
185
- future = RichFuture.new(executor: @service.executor) do
185
+ def initial_normal(executor, &block)
186
+ future = RichFuture.new(executor: executor) do
186
187
  args = wait_dependencies
187
188
  timeout_block(args, &block)
188
189
  end
@@ -224,18 +225,37 @@ module Expeditor
224
225
  end
225
226
 
226
227
  def on(&callback)
227
- if @fallback_var
228
- @fallback_var.add_observer(&callback)
229
- else
230
- @normal_future.add_observer(&callback)
228
+ @ivar.add_observer(&callback)
229
+ end
230
+
231
+ # set future
232
+ # set fallback future as an observer
233
+ # start dependencies
234
+ def prepare(executor = @service.executor)
235
+ @normal_future = initial_normal(executor, &@normal_block)
236
+ @normal_future.add_observer do |_, value, reason|
237
+ if reason # failure
238
+ if @fallback_block
239
+ future = RichFuture.new(executor: executor) do
240
+ success, value, reason = Concurrent::SafeTaskExecutor.new(@fallback_block, rescue_exception: true).execute(reason)
241
+ @ivar.send(:complete, success, value, reason)
242
+ end
243
+ future.safe_execute
244
+ else
245
+ @ivar.fail(reason)
246
+ end
247
+ else # success
248
+ @ivar.set(value)
249
+ end
231
250
  end
251
+
252
+ @dependencies.each(&:start)
232
253
  end
233
254
 
234
255
  class ConstCommand < Command
235
256
  def initialize(value)
236
- @service = Expeditor::Services.default
237
- @dependencies = []
238
- @normal_future = RichFuture.new {}.set(value)
257
+ super(){ value }
258
+ self.start
239
259
  end
240
260
  end
241
261
  end
@@ -4,10 +4,15 @@ module Expeditor
4
4
  NotStartedError = Class.new(StandardError)
5
5
  RejectedExecutionError = Concurrent::RejectedExecutionError
6
6
  CircuitBreakError = Class.new(StandardError)
7
+ AlreadyStartedError = Class.new(StandardError)
7
8
  class DependencyError < StandardError
8
9
  attr :error
9
10
  def initialize(e)
10
11
  @error = e
11
12
  end
13
+
14
+ def message
15
+ @error.message
16
+ end
12
17
  end
13
18
  end
@@ -1,3 +1,3 @@
1
1
  module Expeditor
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expeditor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - shohei-yasutake
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-25 00:00:00.000000000 Z
11
+ date: 2016-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -135,7 +135,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: 2.1.0
139
139
  required_rubygems_version: !ruby/object:Gem::Requirement
140
140
  requirements:
141
141
  - - ">="