ruote-synchronize 0.1.0
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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +12 -0
- data/.yardopts +4 -0
- data/Gemfile +14 -0
- data/LICENSE +22 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/lib/ruote/synchronize.rb +54 -0
- data/lib/ruote/synchronize/broker.rb +77 -0
- data/lib/ruote/synchronize/participant.rb +51 -0
- data/lib/ruote/synchronize/version.rb +7 -0
- data/ruote-synchronize.gemspec +32 -0
- data/spec/lib/ruote/synchronize/broker_spec.rb +123 -0
- data/spec/lib/ruote/synchronize/participant_spec.rb +86 -0
- data/spec/spec_helper.rb +12 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MmE5MjczM2EwMjk3YjIwNzBmODg0NDIxYzc1ZDA5NjEzZDgxNGE2Yg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NmI5YWExMjcxZTIwNDUyM2UzNDA2ZWZkMWM5OTkxZGY2N2MyODk3MA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZGJiNmYyN2ZjNGE5NTI0MmIwN2Y0Njg2MGEyNzU2NThlOTlkMmJhYzVmYTAy
|
10
|
+
YmU5MTQ1NzM1ZDRhMGNhZDJkNTJhNWIwMTZiNDY0NTQ5NzU4ZmI3ZjhiY2Ex
|
11
|
+
NzA1YjMwZDI5NmNjNzZjMzczZDk1NjA0ZmQ3NDE0YzhiMTc5ZTY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZWU5MzBkZjZiNTFkY2YxMDk0OTljMWRmMjUzZGJmNzAyNTVjZmY5YmQ4YzA1
|
14
|
+
N2Q5ODgxMTAyZmJhZGVkYmFjNGRjY2YxYjE0ZDQ3NDEzZjUxMTQ1M2Y4MjUx
|
15
|
+
NjJjMmFiNjY3ODM1NDg5ODFhM2ExMjUxZTkwYmIwNzM5OTIyY2Q=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in ruote-broker.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
platforms :ruby_18, :jruby do
|
7
|
+
gem 'json' unless RUBY_VERSION > '1.9' # is there a jruby but 1.8 only selector?
|
8
|
+
end
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem 'rake'
|
12
|
+
gem 'rspec'
|
13
|
+
gem 'coveralls', :require => false
|
14
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Adrien Kohlbecker
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
[](https://travis-ci.org/adrienkohlbecker/ruote-synchronize) [](https://coveralls.io/r/adrienkohlbecker/ruote-synchronize) [](https://codeclimate.com/github/adrienkohlbecker/ruote-synchronize) [](https://gemnasium.com/adrienkohlbecker/ruote-synchronize)
|
2
|
+
|
3
|
+
# Ruote::Synchronize
|
4
|
+
|
5
|
+
- **Homepage**: [github.com/adrienkohlbecker/ruote-synchronize](https://github.com/adrienkohlbecker/ruote-synchronize)
|
6
|
+
- **Rdoc**: [rdoc.info/gems/ruote-synchronize](http://rdoc.info/gems/ruote-synchronize)
|
7
|
+
- **Author**: Adrien Kohlbecker
|
8
|
+
- **License**: MIT License
|
9
|
+
- **Latest Version**: 0.1.0
|
10
|
+
- **Release Date**: April 29, 2013
|
11
|
+
|
12
|
+
## Synopsis
|
13
|
+
|
14
|
+
A process synchronisation module for Ruote.
|
15
|
+
|
16
|
+
Will define a `synchronize :key => "my_unique_key"` participant.
|
17
|
+
You can use it in two processes by defining the same synchronisation key.
|
18
|
+
The first process to reach the synchronization will wait for the other one.
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
|
24
|
+
# Charly and Doug will only run when both Alice and Bob have run,
|
25
|
+
# no matter which one of Alice or Bob finishes first
|
26
|
+
|
27
|
+
Ruote::Synchronize.setup(engine)
|
28
|
+
|
29
|
+
pdef1 = Ruote.process_definition do
|
30
|
+
alice
|
31
|
+
synchronize :key => 'my_very_unique_key'
|
32
|
+
charly
|
33
|
+
end
|
34
|
+
|
35
|
+
pdef2 = Ruote.process_definition do
|
36
|
+
bob
|
37
|
+
synchronize :key => 'my_very_unique_key'
|
38
|
+
doug
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
It works by storing the first workitem along with the key.
|
43
|
+
When the second process reaches synchronize, it will find the previous workitem,
|
44
|
+
receive it (allowing the first process to proceed), and reply immediately.
|
45
|
+
|
46
|
+
You must use a key that you know will NEVER be used outside of the two process you want to synchronize.
|
47
|
+
|
48
|
+
**Pay attention to multiple launches** (if your process is launched by an HTTP request for example).
|
49
|
+
If three processes with the same key are launched, the two first will be synchronized and the last one will be left hanging.
|
50
|
+
|
51
|
+
## Requirements
|
52
|
+
|
53
|
+
A functionall installation of [Ruote](http://ruote.rubyforge.org) is needed.
|
54
|
+
|
55
|
+
ruote-synchronize has been tested on Ruby 1.8+.
|
56
|
+
|
57
|
+
## Installation
|
58
|
+
|
59
|
+
Add this line to your application's Gemfile:
|
60
|
+
|
61
|
+
gem 'ruote-synchronize'
|
62
|
+
|
63
|
+
And then execute:
|
64
|
+
|
65
|
+
$ bundle
|
66
|
+
|
67
|
+
Or install it yourself as:
|
68
|
+
|
69
|
+
$ gem install ruote-synchronize
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
1. Fork it
|
74
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
75
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
76
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
77
|
+
5. Run the tests (`bundle exec rspec`)
|
78
|
+
6. Create new Pull Request
|
79
|
+
|
80
|
+
## Changelog
|
81
|
+
|
82
|
+
- **April 29, 2013**: 0.1.0 release
|
83
|
+
- Initial release
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'ruote'
|
4
|
+
require 'ruote/synchronize/broker'
|
5
|
+
require 'ruote/synchronize/participant'
|
6
|
+
require 'ruote/synchronize/version'
|
7
|
+
|
8
|
+
module Ruote
|
9
|
+
|
10
|
+
# A process synchronisation module for Ruote.
|
11
|
+
#
|
12
|
+
# Will define a `synchronize :key => "my_unique_key"` participant.
|
13
|
+
# You can use it in two processes by defining the same synchronisation key.
|
14
|
+
# The first process to reach the synchronization will wait for the other one.
|
15
|
+
#
|
16
|
+
# It works by storing the first workitem along with the key.
|
17
|
+
# When the second process reaches synchronize, it will find the previous workitem,
|
18
|
+
# receive it (allowing the first process to proceed), and reply immediately.
|
19
|
+
#
|
20
|
+
# You must use a key that you know will NEVER be used outside of the two process you want to synchronize.
|
21
|
+
#
|
22
|
+
# Pay attention to multiple launches (if your process is launched by an HTTP request for example).
|
23
|
+
# If three processes with the same key are launched, the two first will be synchronized and the last one will be left hanging.
|
24
|
+
#
|
25
|
+
# @example Charly and Doug will only run when both Alice and Bob have run, no matter which one of Alice or Bob finishes first
|
26
|
+
#
|
27
|
+
# Ruote::Synchronize.setup(engine)
|
28
|
+
#
|
29
|
+
# pdef1 = Ruote.process_definition do
|
30
|
+
# alice
|
31
|
+
# synchronize :key => 'my_very_unique_key'
|
32
|
+
# charly
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# pdef2 = Ruote.process_definition do
|
36
|
+
# bob
|
37
|
+
# synchronize :key => 'my_very_unique_key'
|
38
|
+
# doug
|
39
|
+
# end
|
40
|
+
module Synchronize
|
41
|
+
|
42
|
+
# Will register the `synchronize` storage type and participant.
|
43
|
+
# You need to execute this method before launching any processes.
|
44
|
+
# @param [Ruote::Dashboard, Ruote::Engine] dashboard your Ruote dashboard.
|
45
|
+
# @return [void]
|
46
|
+
def self.setup(dashboard)
|
47
|
+
|
48
|
+
dashboard.context.storage.add_type 'synchronize'
|
49
|
+
dashboard.register_participant 'synchronize', Ruote::Synchronize::Participant
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Ruote
|
4
|
+
module Synchronize
|
5
|
+
|
6
|
+
# A Ruote Receiver that act as a broker between two processes.
|
7
|
+
# It will store workitems under the `synchronize` storage type.
|
8
|
+
class Broker
|
9
|
+
|
10
|
+
include Ruote::ReceiverMixin
|
11
|
+
|
12
|
+
# @param [Ruote::Context] context (needed by Ruote)
|
13
|
+
def initialize(context)
|
14
|
+
@context = context
|
15
|
+
end
|
16
|
+
|
17
|
+
# Check if there was a previous workitem stored with the same key.
|
18
|
+
# If so, receives and deletes the stored workitem.
|
19
|
+
# Else, stores the workitem with the key.
|
20
|
+
# @param [#to_s] key The unique key to do the lookup with
|
21
|
+
# @param [Ruote::Workitem] workitem The workitem to store
|
22
|
+
# @return [true, false] True if there was a previous workitem
|
23
|
+
# with the same key, false otherwise
|
24
|
+
def publish(key, workitem)
|
25
|
+
|
26
|
+
if doc = stored_doc_from_key(key)
|
27
|
+
# another process already registered the same key
|
28
|
+
# allow both processes to continue
|
29
|
+
continue_with doc
|
30
|
+
true
|
31
|
+
else
|
32
|
+
# this process is the first to register
|
33
|
+
# store the workitem for now
|
34
|
+
wait_for key, workitem
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# Deletes a previously stored key from storage
|
41
|
+
# @param [#to_s] key The key to delere
|
42
|
+
# @return [void]
|
43
|
+
def unpublish(key)
|
44
|
+
doc = stored_doc_from_key(key)
|
45
|
+
@context.storage.delete(doc) if doc
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def stored_doc_from_key(key)
|
51
|
+
@context.storage.get('synchronize', key)
|
52
|
+
end
|
53
|
+
|
54
|
+
def continue_with(doc)
|
55
|
+
|
56
|
+
stored_workitem = Ruote::Workitem.new(doc['workitem'])
|
57
|
+
receive(stored_workitem)
|
58
|
+
@context.storage.delete(doc)
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def wait_for(key, workitem)
|
63
|
+
|
64
|
+
doc = {
|
65
|
+
'type' => 'synchronize',
|
66
|
+
'_id' => key,
|
67
|
+
'workitem' => workitem.to_h
|
68
|
+
}
|
69
|
+
@context.storage.put(doc)
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Ruote
|
4
|
+
module Synchronize
|
5
|
+
|
6
|
+
# Raised when the synchronize participant is used without a key
|
7
|
+
# @example Will raise UndefinedKey during process execution
|
8
|
+
# pdef = Ruote.process_definition do
|
9
|
+
# synchronize
|
10
|
+
# synchronize :key => nil
|
11
|
+
# synchronize :key => ''
|
12
|
+
# end
|
13
|
+
class UndefinedKey < RuntimeError
|
14
|
+
end
|
15
|
+
|
16
|
+
# A special kind of participant registered as "synchronize"
|
17
|
+
class Participant
|
18
|
+
|
19
|
+
include Ruote::LocalParticipant
|
20
|
+
|
21
|
+
# Replies if another synchronize call was made previously with the same key.
|
22
|
+
# Otherwise stores the workitem and does not reply.
|
23
|
+
# @raise [UndefinedKey] if synchronize was called with a nil or empty key.
|
24
|
+
# @return [void]
|
25
|
+
def on_workitem
|
26
|
+
|
27
|
+
key = workitem.lookup('params.key')
|
28
|
+
raise UndefinedKey if key.to_s.empty?
|
29
|
+
|
30
|
+
reply if broker.publish(key, workitem)
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# Deletes the synchronization key from storage if it still exists.
|
35
|
+
# @return [void]
|
36
|
+
def on_cancel
|
37
|
+
|
38
|
+
key = applied_workitem.lookup('params.key')
|
39
|
+
broker.unpublish(key)
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def broker
|
46
|
+
@broker ||= Ruote::Synchronize::Broker.new(self.context)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruote/synchronize/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ruote-synchronize"
|
8
|
+
spec.version = Ruote::Synchronize::VERSION
|
9
|
+
spec.authors = ["Adrien Kohlbecker"]
|
10
|
+
spec.email = ["adrien.kohlbecker@gmail.com"]
|
11
|
+
spec.description = %q{A process synchronisation module for Ruote.}
|
12
|
+
spec.summary = %q{A process synchronisation module for Ruote.
|
13
|
+
Will define a synchronize :key => "my_unique_key" participant.
|
14
|
+
You can use it in two processes by defining the same synchronisation key.
|
15
|
+
The first process to reach the synchronization will wait for the other one.}.gsub(/^\s+/, '')
|
16
|
+
|
17
|
+
spec.homepage = "https://github.com/adrienkohlbecker/ruote-synchronize"
|
18
|
+
spec.license = "MIT"
|
19
|
+
|
20
|
+
spec.files = `git ls-files`.split($/)
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_dependency "ruote"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
28
|
+
spec.add_development_dependency 'rubocop'
|
29
|
+
spec.add_development_dependency 'mutant'
|
30
|
+
spec.add_development_dependency 'yard'
|
31
|
+
spec.add_development_dependency 'redcarpet'
|
32
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ruote::Synchronize::Broker do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
|
9
|
+
@board = Ruote::Dashboard.new(Ruote::Worker.new(Ruote::HashStorage.new))
|
10
|
+
|
11
|
+
@board.register(/^block_/) do |workitem|
|
12
|
+
workitem.fields[workitem.participant_name] = 'was here'
|
13
|
+
end
|
14
|
+
|
15
|
+
Ruote::Synchronize.setup(@board)
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
after :each do
|
20
|
+
|
21
|
+
@board.shutdown
|
22
|
+
@board.storage.purge!
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
context '#initialize' do
|
27
|
+
|
28
|
+
it 'accepts a context' do
|
29
|
+
|
30
|
+
expect{Ruote::Synchronize::Broker.new}.to raise_error
|
31
|
+
expect{Ruote::Synchronize::Broker.new(@board.context)}.not_to raise_error
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'registers the synchronize participant' do
|
36
|
+
|
37
|
+
sync = Ruote::Synchronize::Broker.new(@board.context)
|
38
|
+
expect(@board.participant('synchronize')).not_to be_nil
|
39
|
+
expect(@board.participant('synchronize').class).to eq(Ruote::Synchronize::Participant)
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context '#publish' do
|
46
|
+
|
47
|
+
let(:sync) { Ruote::Synchronize::Broker.new(@board.context) }
|
48
|
+
let(:key) { 'my_key' }
|
49
|
+
let(:workitem) { Ruote::Workitem.new({'abc'=> true}) }
|
50
|
+
|
51
|
+
context 'with a fresh storage' do
|
52
|
+
|
53
|
+
it 'stores the workitem with the message' do
|
54
|
+
sync.publish(key, workitem)
|
55
|
+
expect(@board.context.storage.get('synchronize', key)['workitem']).to eq(workitem.to_h)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns false' do
|
59
|
+
expect(sync.publish(key, workitem).is_a? FalseClass).to be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with a previously published message' do
|
65
|
+
|
66
|
+
before :each do
|
67
|
+
sync.publish(key, workitem)
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:another_workitem) { Ruote::Workitem.new({:def => true}) }
|
71
|
+
|
72
|
+
it 'deletes the previous message' do
|
73
|
+
sync.publish(key, another_workitem)
|
74
|
+
expect(@board.context.storage.get('synchronize', key)).to be_nil
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'returns true' do
|
79
|
+
expect(sync.publish(key, another_workitem).is_a? TrueClass).to be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'receives the previous workitem' do
|
83
|
+
sync.should_receive(:receive).with(workitem)
|
84
|
+
sync.publish(key, another_workitem)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context '#unpublish' do
|
93
|
+
|
94
|
+
let(:sync) { Ruote::Synchronize::Broker.new(@board.context) }
|
95
|
+
let(:key) { 'my_key' }
|
96
|
+
let(:workitem) { Ruote::Workitem.new({'abc'=> true}) }
|
97
|
+
|
98
|
+
context 'with a fresh storage' do
|
99
|
+
|
100
|
+
it 'returns nil' do
|
101
|
+
expect(sync.unpublish(key)).to be_nil
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'with a previously published message' do
|
107
|
+
|
108
|
+
before :each do
|
109
|
+
sync.publish(key, workitem)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'deletes the previous message' do
|
113
|
+
sync.unpublish(key)
|
114
|
+
expect(@board.context.storage.get('synchronize', key)).to be_nil
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'ruote/storage/fs_storage'
|
5
|
+
|
6
|
+
describe Ruote::Synchronize::Broker do
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@board = Ruote::Dashboard.new(Ruote::Worker.new(Ruote::FsStorage.new('ruote_work')))
|
10
|
+
@participant = Ruote::Synchronize::Participant.new
|
11
|
+
@participant.context = @board.context
|
12
|
+
end
|
13
|
+
|
14
|
+
after :each do
|
15
|
+
@board.shutdown
|
16
|
+
@board.storage.purge!
|
17
|
+
end
|
18
|
+
|
19
|
+
context '#on_workitem' do
|
20
|
+
|
21
|
+
let(:workitem) { Ruote::Workitem.new({'abc' => true, 'fields' => {'params' => {'key' => 'my_key'}}}) }
|
22
|
+
let(:key) { 'my_key' }
|
23
|
+
|
24
|
+
it 'raises if the key is not defined' do
|
25
|
+
workitem.fields['params']['key'] = nil
|
26
|
+
expect{@participant._on_workitem(workitem)}.to raise_error(Ruote::Synchronize::UndefinedKey)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'raises if the key is an empty string' do
|
30
|
+
workitem.fields['params']['key'] = ''
|
31
|
+
expect{@participant._on_workitem(workitem)}.to raise_error(Ruote::Synchronize::UndefinedKey)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with a fresh storage' do
|
35
|
+
|
36
|
+
it 'stores the message' do
|
37
|
+
@participant._on_workitem(workitem)
|
38
|
+
expect(@board.context.storage.get('synchronize', key)).not_to be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'does not reply' do
|
42
|
+
@participant.should_not_receive(:reply)
|
43
|
+
@participant._on_workitem(workitem)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with a previous message' do
|
49
|
+
|
50
|
+
before :each do
|
51
|
+
@another_participant = Ruote::Synchronize::Participant.new
|
52
|
+
@another_participant.context = @board.context
|
53
|
+
@another_participant._on_workitem(workitem)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'replies to the other participant' do
|
57
|
+
Ruote::Synchronize::Broker.any_instance.should_receive(:receive).with(@another_participant.workitem)
|
58
|
+
@participant._on_workitem(workitem)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'replies immediately' do
|
62
|
+
@participant.should_receive(:reply)
|
63
|
+
@participant._on_workitem(workitem)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
context '#on_cancel' do
|
71
|
+
|
72
|
+
let(:workitem) { Ruote::Workitem.new({'abc' => true, 'fields' => {'params' => {'key' => 'my_key'}}}) }
|
73
|
+
let(:key) { 'my_key' }
|
74
|
+
|
75
|
+
it 'deletes the message' do
|
76
|
+
|
77
|
+
@participant._on_workitem(workitem)
|
78
|
+
@participant.stub(:applied_workitem).and_return workitem
|
79
|
+
@participant.on_cancel
|
80
|
+
expect(@board.context.storage.get('synchronize', key)).to be_nil
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruote-synchronize
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adrien Kohlbecker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruote
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mutant
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: redcarpet
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: A process synchronisation module for Ruote.
|
98
|
+
email:
|
99
|
+
- adrien.kohlbecker@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- .rspec
|
106
|
+
- .travis.yml
|
107
|
+
- .yardopts
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- lib/ruote/synchronize.rb
|
113
|
+
- lib/ruote/synchronize/broker.rb
|
114
|
+
- lib/ruote/synchronize/participant.rb
|
115
|
+
- lib/ruote/synchronize/version.rb
|
116
|
+
- ruote-synchronize.gemspec
|
117
|
+
- spec/lib/ruote/synchronize/broker_spec.rb
|
118
|
+
- spec/lib/ruote/synchronize/participant_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
homepage: https://github.com/adrienkohlbecker/ruote-synchronize
|
121
|
+
licenses:
|
122
|
+
- MIT
|
123
|
+
metadata: {}
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 2.0.3
|
141
|
+
signing_key:
|
142
|
+
specification_version: 4
|
143
|
+
summary: A process synchronisation module for Ruote. Will define a synchronize :key
|
144
|
+
=> "my_unique_key" participant. You can use it in two processes by defining the
|
145
|
+
same synchronisation key. The first process to reach the synchronization will wait
|
146
|
+
for the other one.
|
147
|
+
test_files:
|
148
|
+
- spec/lib/ruote/synchronize/broker_spec.rb
|
149
|
+
- spec/lib/ruote/synchronize/participant_spec.rb
|
150
|
+
- spec/spec_helper.rb
|
151
|
+
has_rdoc:
|