finite_machine 0.11.2 → 0.11.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/.travis.yml +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -0
- data/README.md +3 -1
- data/Rakefile +1 -1
- data/benchmarks/memory_usage.rb +21 -0
- data/finite_machine.gemspec +2 -2
- data/lib/finite_machine.rb +2 -2
- data/lib/finite_machine/async_proxy.rb +26 -1
- data/lib/finite_machine/{event_queue.rb → message_queue.rb} +38 -5
- data/lib/finite_machine/observer.rb +39 -20
- data/lib/finite_machine/state_machine.rb +3 -9
- data/lib/finite_machine/version.rb +1 -1
- data/spec/performance/benchmark_spec.rb +62 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/async_callbacks_spec.rb +33 -0
- data/spec/unit/async_events_spec.rb +1 -32
- data/spec/unit/event_queue_spec.rb +7 -4
- data/tasks/spec.rake +5 -0
- metadata +16 -7
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64b466f571e5b537fe1836ce548cc742ffee4dfc
|
4
|
+
data.tar.gz: fbbc424571e422139ca7896cfd2465023ddab2ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa9c41cfd27257a3ae5f896bf00fd582ad5586e2e064632c93490173800c85fd6b9bb033a2d0ac5c10850b1ad86b12f79419e425f74497656a40bf85425332f4
|
7
|
+
data.tar.gz: 635d68e625689ac0b0c7adbdf04d50e6abf7c8f000d67e4e263d498693f7fb44d8b55f72dc79e6cb026189fc9a3b6a97f584add2b7e6154bf96afb24c92bae62
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.11.3] - 2016-03-04
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add performance tests & memory usage benchmarks
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
* Change EventQueue to MessageQueue for handling generic asynchronous messages
|
10
|
+
* Split async behaviour to use CallbackQueue for observed callbacks and EventQueue for async event triggers.
|
11
|
+
* Change AsyncProxy and Observer to lazy load message queue
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
* Fix memory leak - issue #42 with help from @craiglittle
|
15
|
+
|
3
16
|
## [v0.11.2] - 2015-12-30
|
4
17
|
|
5
18
|
### Added
|
@@ -237,6 +250,7 @@
|
|
237
250
|
### Fixed
|
238
251
|
* Fix bug - callback event object returns correct from state
|
239
252
|
|
253
|
+
[v0.11.3]: https://github.com/peter-murach/finite_machine/compare/v0.11.2...v0.11.3
|
240
254
|
[v0.11.2]: https://github.com/peter-murach/finite_machine/compare/v0.11.1...v0.11.2
|
241
255
|
[v0.11.1]: https://github.com/peter-murach/finite_machine/compare/v0.11.0...v0.11.1
|
242
256
|
[v0.11.0]: https://github.com/peter-murach/finite_machine/compare/v0.10.2...v0.11.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -559,6 +559,7 @@ fm = FiniteMachine.define do
|
|
559
559
|
:low => :medium,
|
560
560
|
:medium => :high
|
561
561
|
}
|
562
|
+
end
|
562
563
|
```
|
563
564
|
|
564
565
|
The same can be more naturally rewritten also as:
|
@@ -572,6 +573,7 @@ fm = FiniteMachine.define do
|
|
572
573
|
event :bump, :low => :medium
|
573
574
|
event :bump, :medium => :high
|
574
575
|
}
|
576
|
+
end
|
575
577
|
```
|
576
578
|
|
577
579
|
### 2.7 Silent transitions
|
@@ -1441,4 +1443,4 @@ Creating a standalone **FiniteMachine** brings a number of benefits, one of them
|
|
1441
1443
|
|
1442
1444
|
## Copyright
|
1443
1445
|
|
1444
|
-
Copyright (c) 2014-
|
1446
|
+
Copyright (c) 2014-2016 Piotr Murach. See LICENSE for further details.
|
data/Rakefile
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'finite_machine'
|
4
|
+
|
5
|
+
3.times do
|
6
|
+
puts
|
7
|
+
|
8
|
+
GC.start
|
9
|
+
|
10
|
+
before = GC.stat
|
11
|
+
p ObjectSpace.count_objects
|
12
|
+
|
13
|
+
1_000.times do
|
14
|
+
FiniteMachine.define
|
15
|
+
end
|
16
|
+
|
17
|
+
p ObjectSpace.count_objects
|
18
|
+
after = GC.stat
|
19
|
+
|
20
|
+
p "GC count: #{after[:count] - before[:count]}"
|
21
|
+
end
|
data/finite_machine.gemspec
CHANGED
@@ -18,6 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
21
|
+
spec.add_development_dependency 'bundler', '>= 1.5.0', '< 2.0'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
23
|
end
|
data/lib/finite_machine.rb
CHANGED
@@ -15,7 +15,7 @@ require "finite_machine/async_proxy"
|
|
15
15
|
require "finite_machine/async_call"
|
16
16
|
require "finite_machine/hook_event"
|
17
17
|
require "finite_machine/env"
|
18
|
-
require "finite_machine/
|
18
|
+
require "finite_machine/message_queue"
|
19
19
|
require "finite_machine/events_chain"
|
20
20
|
require "finite_machine/logger"
|
21
21
|
require "finite_machine/transition"
|
@@ -66,7 +66,7 @@ module FiniteMachine
|
|
66
66
|
MissingInitialStateError = Class.new(::StandardError)
|
67
67
|
|
68
68
|
# Raised when event queue is already dead
|
69
|
-
|
69
|
+
MessageQueueDeadError = Class.new(::StandardError)
|
70
70
|
|
71
71
|
# Raised when argument is already defined
|
72
72
|
AlreadyDefinedError = Class.new(::ArgumentError)
|
@@ -2,11 +2,20 @@
|
|
2
2
|
|
3
3
|
module FiniteMachine
|
4
4
|
# An asynchronous messages proxy
|
5
|
+
#
|
6
|
+
# @api private
|
5
7
|
class AsyncProxy
|
6
8
|
include Threadable
|
7
9
|
|
8
10
|
attr_threadsafe :context
|
9
11
|
|
12
|
+
# The queue for asynchronoous events
|
13
|
+
#
|
14
|
+
# @return [EventQueue]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
attr_threadsafe :event_queue
|
18
|
+
|
10
19
|
# Initialize an AsynxProxy
|
11
20
|
#
|
12
21
|
# @param [Object] context
|
@@ -14,7 +23,10 @@ module FiniteMachine
|
|
14
23
|
#
|
15
24
|
# @api private
|
16
25
|
def initialize(context)
|
17
|
-
self.context
|
26
|
+
self.context = context
|
27
|
+
self.event_queue = MessageQueue.new
|
28
|
+
|
29
|
+
ObjectSpace.define_finalizer(self, self.class.cleanup(event_queue))
|
18
30
|
end
|
19
31
|
|
20
32
|
# Delegate asynchronous event to event queue
|
@@ -24,7 +36,20 @@ module FiniteMachine
|
|
24
36
|
callable = Callable.new(method_name)
|
25
37
|
async_call = AsyncCall.new(context, callable, *args, &block)
|
26
38
|
|
39
|
+
event_queue.start unless event_queue.running?
|
27
40
|
context.event_queue << async_call
|
28
41
|
end
|
42
|
+
|
43
|
+
# Clean up event queue
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
def self.cleanup(queue)
|
47
|
+
proc do
|
48
|
+
begin
|
49
|
+
queue && queue.shutdown
|
50
|
+
rescue MessageQueueDeadError
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
29
54
|
end # AsyncProxy
|
30
55
|
end # FiniteMachine
|
@@ -1,26 +1,44 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module FiniteMachine
|
4
|
-
#
|
5
|
-
|
4
|
+
# Allows for storage of asynchronous messages such as events
|
5
|
+
# and callbacks.
|
6
|
+
#
|
7
|
+
# Used internally by {Observer} and {StateMachine}
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
class MessageQueue
|
6
11
|
include Threadable
|
7
12
|
|
8
13
|
# Initialize an event queue
|
9
14
|
#
|
10
15
|
# @example
|
11
|
-
#
|
16
|
+
# MessageQueue.new
|
12
17
|
#
|
13
18
|
# @api public
|
14
19
|
def initialize
|
15
20
|
@queue = Queue.new
|
16
21
|
@dead = false
|
17
22
|
@listeners = []
|
23
|
+
@thread = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# Start a new thread with a queue of callback events to run
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def start
|
30
|
+
return if running?
|
18
31
|
|
19
32
|
@thread = Thread.new do
|
33
|
+
Thread.current.abort_on_exception = true
|
20
34
|
process_events
|
21
35
|
end
|
22
36
|
end
|
23
37
|
|
38
|
+
def running?
|
39
|
+
!@thread.nil? && alive?
|
40
|
+
end
|
41
|
+
|
24
42
|
# Retrieve the next event
|
25
43
|
#
|
26
44
|
# @return [AsyncCall]
|
@@ -41,7 +59,13 @@ module FiniteMachine
|
|
41
59
|
#
|
42
60
|
# @api public
|
43
61
|
def <<(event)
|
44
|
-
sync_exclusive
|
62
|
+
sync_exclusive do
|
63
|
+
if @dead
|
64
|
+
discard_message(event)
|
65
|
+
else
|
66
|
+
@queue << event
|
67
|
+
end
|
68
|
+
end
|
45
69
|
self
|
46
70
|
end
|
47
71
|
|
@@ -89,6 +113,7 @@ module FiniteMachine
|
|
89
113
|
#
|
90
114
|
# @api public
|
91
115
|
def join(timeout = nil)
|
116
|
+
return unless @thread
|
92
117
|
timeout.nil? ? @thread.join : @thread.join(timeout)
|
93
118
|
end
|
94
119
|
|
@@ -110,7 +135,7 @@ module FiniteMachine
|
|
110
135
|
@dead = true
|
111
136
|
end
|
112
137
|
while !queue.empty?
|
113
|
-
|
138
|
+
discard_message(queue.pop)
|
114
139
|
end
|
115
140
|
true
|
116
141
|
end
|
@@ -127,6 +152,10 @@ module FiniteMachine
|
|
127
152
|
sync_shared { @queue.size }
|
128
153
|
end
|
129
154
|
|
155
|
+
def inspect
|
156
|
+
"#<#{self.class}:#{object_id.to_s(16)} @size=#{size}, @dead=#{@dead}>"
|
157
|
+
end
|
158
|
+
|
130
159
|
private
|
131
160
|
|
132
161
|
# Notify consumers about process event
|
@@ -154,5 +183,9 @@ module FiniteMachine
|
|
154
183
|
rescue Exception => ex
|
155
184
|
Logger.error "Error while running event: #{Logger.format_error(ex)}"
|
156
185
|
end
|
186
|
+
|
187
|
+
def discard_message(message)
|
188
|
+
Logger.debug "Discarded message: #{message}" if $DEBUG
|
189
|
+
end
|
157
190
|
end # EventQueue
|
158
191
|
end # FiniteMachine
|
@@ -16,11 +16,17 @@ module FiniteMachine
|
|
16
16
|
|
17
17
|
# Initialize an Observer
|
18
18
|
#
|
19
|
+
# @param [StateMachine] machine
|
20
|
+
# reference to the current machine
|
21
|
+
#
|
19
22
|
# @api public
|
20
23
|
def initialize(machine)
|
21
|
-
@machine
|
24
|
+
@machine = machine
|
25
|
+
@hooks = FiniteMachine::Hooks.new
|
26
|
+
@callback_queue = MessageQueue.new
|
27
|
+
|
22
28
|
@machine.subscribe(self)
|
23
|
-
|
29
|
+
ObjectSpace.define_finalizer(self, self.class.cleanup(@callback_queue))
|
24
30
|
end
|
25
31
|
|
26
32
|
# Evaluate in current context
|
@@ -130,24 +136,6 @@ module FiniteMachine
|
|
130
136
|
|
131
137
|
private
|
132
138
|
|
133
|
-
# Defer callback execution
|
134
|
-
#
|
135
|
-
# @api private
|
136
|
-
def defer(callable, trans_event, *data)
|
137
|
-
async_call = AsyncCall.new(machine, callable, trans_event, *data)
|
138
|
-
machine.event_queue << async_call
|
139
|
-
end
|
140
|
-
|
141
|
-
# Create callable instance
|
142
|
-
#
|
143
|
-
# @api private
|
144
|
-
def create_callable(hook)
|
145
|
-
callback = proc do |trans_event, *data|
|
146
|
-
machine.instance_exec(trans_event, *data, &hook)
|
147
|
-
end
|
148
|
-
Callable.new(callback)
|
149
|
-
end
|
150
|
-
|
151
139
|
# Handle callback and decide if run synchronously or asynchronously
|
152
140
|
#
|
153
141
|
# @param [Proc] :hook
|
@@ -177,6 +165,25 @@ module FiniteMachine
|
|
177
165
|
end
|
178
166
|
end
|
179
167
|
|
168
|
+
# Defer callback execution
|
169
|
+
#
|
170
|
+
# @api private
|
171
|
+
def defer(callable, trans_event, *data)
|
172
|
+
async_call = AsyncCall.new(machine, callable, trans_event, *data)
|
173
|
+
@callback_queue.start unless @callback_queue.running?
|
174
|
+
@callback_queue << async_call
|
175
|
+
end
|
176
|
+
|
177
|
+
# Create callable instance
|
178
|
+
#
|
179
|
+
# @api private
|
180
|
+
def create_callable(hook)
|
181
|
+
callback = proc do |trans_event, *data|
|
182
|
+
machine.instance_exec(trans_event, *data, &hook)
|
183
|
+
end
|
184
|
+
Callable.new(callback)
|
185
|
+
end
|
186
|
+
|
180
187
|
# Callback names including all states and events
|
181
188
|
#
|
182
189
|
# @return [Array[Symbol]]
|
@@ -218,5 +225,17 @@ module FiniteMachine
|
|
218
225
|
*_, callback_name = *method_name.to_s.match(/^(\w*?on_\w+?)_(\w+)$/)
|
219
226
|
callback_name && callback_names.include?(:"#{callback_name}")
|
220
227
|
end
|
228
|
+
|
229
|
+
# Clean up callback queue
|
230
|
+
#
|
231
|
+
# @api private
|
232
|
+
def self.cleanup(queue)
|
233
|
+
proc do
|
234
|
+
begin
|
235
|
+
queue && queue.shutdown
|
236
|
+
rescue MessageQueueDeadError
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
221
240
|
end # Observer
|
222
241
|
end # FiniteMachine
|
@@ -57,13 +57,6 @@ module FiniteMachine
|
|
57
57
|
# @api private
|
58
58
|
attr_threadsafe :subscribers
|
59
59
|
|
60
|
-
# The queue for asynchronoous events
|
61
|
-
#
|
62
|
-
# @return [EventQueue]
|
63
|
-
#
|
64
|
-
# @api private
|
65
|
-
attr_threadsafe :event_queue
|
66
|
-
|
67
60
|
# Allow or not logging of transitions
|
68
61
|
attr_threadsafe :log_transitions
|
69
62
|
|
@@ -72,13 +65,14 @@ module FiniteMachine
|
|
72
65
|
|
73
66
|
def_delegator :events_dsl, :event
|
74
67
|
|
68
|
+
def_delegator :@async_proxy, :event_queue
|
69
|
+
|
75
70
|
# Initialize state machine
|
76
71
|
#
|
77
72
|
# @api private
|
78
73
|
def initialize(*args, &block)
|
79
74
|
attributes = args.last.is_a?(Hash) ? args.pop : {}
|
80
75
|
|
81
|
-
@event_queue = EventQueue.new
|
82
76
|
@initial_state = DEFAULT_STATE
|
83
77
|
@async_proxy = AsyncProxy.new(self)
|
84
78
|
@subscribers = Subscribers.new
|
@@ -120,7 +114,7 @@ module FiniteMachine
|
|
120
114
|
# @api public
|
121
115
|
def async(method_name = nil, *args, &block)
|
122
116
|
if method_name
|
123
|
-
@async_proxy.method_missing
|
117
|
+
@async_proxy.method_missing(method_name, *args, &block)
|
124
118
|
else
|
125
119
|
@async_proxy
|
126
120
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec.describe FiniteMachine do
|
4
|
+
include RSpec::Benchmark::Matchers
|
5
|
+
|
6
|
+
class Measurement
|
7
|
+
attr_reader :steps, :loops
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@steps = 0
|
11
|
+
@loops = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def inc_step
|
15
|
+
@steps += 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def inc_loop
|
19
|
+
@loops += 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "correctly loops through events" do
|
24
|
+
measurement = Measurement.new
|
25
|
+
|
26
|
+
fsm = FiniteMachine.define do
|
27
|
+
initial :green
|
28
|
+
|
29
|
+
target(measurement)
|
30
|
+
|
31
|
+
events {
|
32
|
+
event :next, :green => :yellow,
|
33
|
+
:yellow => :red,
|
34
|
+
:red => :green
|
35
|
+
}
|
36
|
+
|
37
|
+
callbacks {
|
38
|
+
on_enter do |event| target.inc_step; true end
|
39
|
+
on_enter :red do |event| target.inc_loop; true end
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
100.times { fsm.next }
|
44
|
+
|
45
|
+
expect(measurement.steps).to eq(100)
|
46
|
+
expect(measurement.loops).to eq(100 / 3)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "performs at least 300 ips" do
|
50
|
+
fsm = FiniteMachine.define do
|
51
|
+
initial :green
|
52
|
+
|
53
|
+
events {
|
54
|
+
event :next, :green => :yellow,
|
55
|
+
:yellow => :red,
|
56
|
+
:red => :green
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
expect { fsm.next }.to perform_at_least(400).ips
|
61
|
+
end
|
62
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec.describe FiniteMachine, 'async callbacks' do
|
4
|
+
|
5
|
+
it "permits async callback" do
|
6
|
+
called = []
|
7
|
+
fsm = FiniteMachine.define do
|
8
|
+
initial :green, silent: false
|
9
|
+
|
10
|
+
events {
|
11
|
+
event :slow, :green => :yellow
|
12
|
+
event :go, :yellow => :green
|
13
|
+
}
|
14
|
+
|
15
|
+
callbacks {
|
16
|
+
on_enter :green, :async do |event| called << 'on_enter_green' end
|
17
|
+
on_before :slow, :async do |event| called << 'on_before_slow' end
|
18
|
+
on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
|
19
|
+
on_after :go, :async do |event| called << 'on_after_go' end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
fsm.slow
|
23
|
+
fsm.go
|
24
|
+
sleep 0.1
|
25
|
+
expect(called).to match_array([
|
26
|
+
'on_enter_green',
|
27
|
+
'on_before_slow',
|
28
|
+
'on_exit_yellow',
|
29
|
+
'on_enter_green',
|
30
|
+
'on_after_go'
|
31
|
+
])
|
32
|
+
end
|
33
|
+
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
RSpec.describe FiniteMachine, 'async_events' do
|
3
|
+
RSpec.describe FiniteMachine, 'async events' do
|
6
4
|
|
7
5
|
it 'runs events asynchronously' do
|
8
6
|
called = []
|
@@ -106,33 +104,4 @@ RSpec.describe FiniteMachine, 'async_events' do
|
|
106
104
|
expect(fsmFoo.current).to eql(:yellow)
|
107
105
|
expect(fsmBar.current).to eql(:yellow)
|
108
106
|
end
|
109
|
-
|
110
|
-
it "permits async callback" do
|
111
|
-
called = []
|
112
|
-
fsm = FiniteMachine.define do
|
113
|
-
initial :green, silent: false
|
114
|
-
|
115
|
-
events {
|
116
|
-
event :slow, :green => :yellow
|
117
|
-
event :go, :yellow => :green
|
118
|
-
}
|
119
|
-
|
120
|
-
callbacks {
|
121
|
-
on_enter :green, :async do |event| called << 'on_enter_green' end
|
122
|
-
on_before :slow, :async do |event| called << 'on_before_slow' end
|
123
|
-
on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
|
124
|
-
on_after :go, :async do |event| called << 'on_after_go' end
|
125
|
-
}
|
126
|
-
end
|
127
|
-
fsm.slow
|
128
|
-
fsm.go
|
129
|
-
sleep 0.1
|
130
|
-
expect(called).to match_array([
|
131
|
-
'on_enter_green',
|
132
|
-
'on_before_slow',
|
133
|
-
'on_exit_yellow',
|
134
|
-
'on_enter_green',
|
135
|
-
'on_after_go'
|
136
|
-
])
|
137
|
-
end
|
138
107
|
end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
RSpec.describe FiniteMachine::EventQueue do
|
3
|
+
RSpec.describe FiniteMachine::MessageQueue do
|
6
4
|
|
7
5
|
subject(:event_queue) { described_class.new }
|
8
6
|
|
9
7
|
it "dispatches all events" do
|
8
|
+
event_queue.start
|
10
9
|
called = []
|
11
10
|
event1 = double(:event1, dispatch: called << 'event1_dispatched')
|
12
11
|
event2 = double(:event2, dispatch: called << 'event2_dispatched')
|
@@ -18,7 +17,9 @@ RSpec.describe FiniteMachine::EventQueue do
|
|
18
17
|
end
|
19
18
|
|
20
19
|
it "logs error" do
|
21
|
-
|
20
|
+
event_queue.start
|
21
|
+
event = spy(:event)
|
22
|
+
allow(event).to receive(:dispatch) { raise }
|
22
23
|
expect(FiniteMachine::Logger).to receive(:error)
|
23
24
|
event_queue << event
|
24
25
|
event_queue.join(0.01)
|
@@ -26,6 +27,7 @@ RSpec.describe FiniteMachine::EventQueue do
|
|
26
27
|
end
|
27
28
|
|
28
29
|
it "notifies listeners" do
|
30
|
+
event_queue.start
|
29
31
|
called = []
|
30
32
|
event1 = double(:event1, dispatch: true)
|
31
33
|
event2 = double(:event2, dispatch: true)
|
@@ -38,6 +40,7 @@ RSpec.describe FiniteMachine::EventQueue do
|
|
38
40
|
end
|
39
41
|
|
40
42
|
it "allows to shutdown event queue" do
|
43
|
+
event_queue.start
|
41
44
|
event1 = double(:event1, dispatch: true)
|
42
45
|
event2 = double(:event2, dispatch: true)
|
43
46
|
event3 = double(:event3, dispatch: true)
|
data/tasks/spec.rake
CHANGED
@@ -18,6 +18,11 @@ begin
|
|
18
18
|
RSpec::Core::RakeTask.new(:integration) do |task|
|
19
19
|
task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
|
20
20
|
end
|
21
|
+
|
22
|
+
desc 'Run performance specs'
|
23
|
+
RSpec::Core::RakeTask.new(:perf) do |task|
|
24
|
+
task.pattern = 'spec/performance{,/*/**}/*_spec.rb'
|
25
|
+
end
|
21
26
|
end
|
22
27
|
|
23
28
|
rescue LoadError
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: finite_machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.5.0
|
20
|
+
- - <
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
20
23
|
type: :development
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - '>='
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
29
|
+
version: 1.5.0
|
30
|
+
- - <
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: rake
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -49,8 +55,6 @@ extra_rdoc_files: []
|
|
49
55
|
files:
|
50
56
|
- .gitignore
|
51
57
|
- .rspec
|
52
|
-
- .ruby-gemset
|
53
|
-
- .ruby-version
|
54
58
|
- .travis.yml
|
55
59
|
- CHANGELOG.md
|
56
60
|
- Gemfile
|
@@ -58,6 +62,7 @@ files:
|
|
58
62
|
- README.md
|
59
63
|
- Rakefile
|
60
64
|
- assets/finite_machine_logo.png
|
65
|
+
- benchmarks/memory_usage.rb
|
61
66
|
- examples/atm.rb
|
62
67
|
- examples/bug_system.rb
|
63
68
|
- finite_machine.gemspec
|
@@ -71,12 +76,12 @@ files:
|
|
71
76
|
- lib/finite_machine/dsl.rb
|
72
77
|
- lib/finite_machine/env.rb
|
73
78
|
- lib/finite_machine/event_definition.rb
|
74
|
-
- lib/finite_machine/event_queue.rb
|
75
79
|
- lib/finite_machine/events_chain.rb
|
76
80
|
- lib/finite_machine/hook_event.rb
|
77
81
|
- lib/finite_machine/hooks.rb
|
78
82
|
- lib/finite_machine/listener.rb
|
79
83
|
- lib/finite_machine/logger.rb
|
84
|
+
- lib/finite_machine/message_queue.rb
|
80
85
|
- lib/finite_machine/observer.rb
|
81
86
|
- lib/finite_machine/safety.rb
|
82
87
|
- lib/finite_machine/state_definition.rb
|
@@ -91,8 +96,10 @@ files:
|
|
91
96
|
- lib/finite_machine/undefined_transition.rb
|
92
97
|
- lib/finite_machine/version.rb
|
93
98
|
- spec/integration/system_spec.rb
|
99
|
+
- spec/performance/benchmark_spec.rb
|
94
100
|
- spec/spec_helper.rb
|
95
101
|
- spec/unit/alias_target_spec.rb
|
102
|
+
- spec/unit/async_callbacks_spec.rb
|
96
103
|
- spec/unit/async_events_spec.rb
|
97
104
|
- spec/unit/callable/call_spec.rb
|
98
105
|
- spec/unit/callbacks_spec.rb
|
@@ -171,8 +178,10 @@ specification_version: 4
|
|
171
178
|
summary: A minimal finite state machine with a straightforward syntax.
|
172
179
|
test_files:
|
173
180
|
- spec/integration/system_spec.rb
|
181
|
+
- spec/performance/benchmark_spec.rb
|
174
182
|
- spec/spec_helper.rb
|
175
183
|
- spec/unit/alias_target_spec.rb
|
184
|
+
- spec/unit/async_callbacks_spec.rb
|
176
185
|
- spec/unit/async_events_spec.rb
|
177
186
|
- spec/unit/callable/call_spec.rb
|
178
187
|
- spec/unit/callbacks_spec.rb
|
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
finite_machine
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.0.0
|