ruote-nats 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.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea/
19
+ .DS_Store
@@ -0,0 +1,8 @@
1
+ yardoc
2
+ --title ruote-nats
3
+ --no-private
4
+ --protected lib/**/*.rb
5
+ --markup-provider=redcarpet
6
+ --markup=markdown
7
+ --asset image
8
+ - README.md
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (C) 2012 Naoto Takai. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.RE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,62 @@
1
+ # ruote-nats
2
+
3
+ ruote-nats is an implementation of the ruote participant and receivers to process workitem on remote host using NATS.
4
+
5
+ ![System Diagram](https://github.com/takai/ruote-nats/raw/master/image/system-diagram.png)
6
+
7
+ ## Usage
8
+
9
+ Participant registration:
10
+
11
+ ```ruby
12
+ engine.register_participant :remote_shell, RuoteNATS::Participant
13
+ ```
14
+
15
+ Process definition:
16
+
17
+ ```ruby
18
+ remote_shell :command => '/bin/date', :env => { 'LANG' => 'C' }
19
+ ```
20
+
21
+ ### Options
22
+
23
+ * ```queue```: subject to publish command name, the default value is "remote.command".
24
+ * ```executor```: executor to dispatch on remote host, the default value is "RuoteNATS::ShellExecutor".
25
+
26
+ ### Options for ShellExecutor
27
+
28
+ * ```command```: (required) shell script.
29
+ * ```env```: environments variables for command.
30
+
31
+ ## Single File Example
32
+
33
+ ```ruby
34
+ require 'bundler/setup'
35
+
36
+ require 'ruote'
37
+ require 'ruote-nats'
38
+
39
+ RuoteNATS.logger.level = Logger::DEBUG
40
+
41
+ NATS.start do
42
+ begin
43
+ pdef = Ruote.define do
44
+ remote_shell :command => '/bin/date', :env => { 'LANG' => 'C' }
45
+ end
46
+
47
+ engine = Ruote::Engine.new(Ruote::Worker.new(Ruote::HashStorage.new))
48
+ engine.register_participant :remote_shell, RuoteNATS::Participant
49
+
50
+ RuoteNATS::CommandReceiver.new.start
51
+ RuoteNATS::ReplyReceiver.new(engine).start
52
+
53
+ engine.launch(pdef)
54
+
55
+ EM.add_timer(1) do
56
+ NATS.stop
57
+ end
58
+ rescue
59
+ Logger.new(STDOUT).error($!.message)
60
+ end
61
+ end
62
+ ```
@@ -0,0 +1,8 @@
1
+ # -*- mode: ruby; coding: utf-8 -*-
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ # -*- mode: ruby; coding: utf-8 -*-
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'ruote'
6
+ require 'ruote-nats'
7
+
8
+ RuoteNATS.logger.level = Logger::DEBUG
9
+
10
+ NATS.start do
11
+ begin
12
+ pdef = Ruote.define do
13
+ remote_shell :command => '/bin/date', :env => { 'LANG' => 'C' }
14
+ end
15
+
16
+ engine = Ruote::Engine.new(Ruote::Worker.new(Ruote::HashStorage.new))
17
+ engine.register_participant :remote_shell, RuoteNATS::Participant
18
+
19
+ RuoteNATS::CommandReceiver.new.start
20
+ RuoteNATS::ReplyReceiver.new(engine).start
21
+
22
+ engine.launch(pdef)
23
+
24
+ EM.add_timer(1) do
25
+ NATS.stop
26
+ end
27
+ rescue
28
+ Logger.new(STDOUT).error($!.message)
29
+ end
30
+ end
Binary file
@@ -0,0 +1,29 @@
1
+ require 'logger'
2
+ require 'msgpack'
3
+ require 'nats/client'
4
+ require 'ruote'
5
+ require 'open3'
6
+
7
+ require 'ruote-nats/command_receiver'
8
+ require 'ruote-nats/participant'
9
+ require 'ruote-nats/reply_receiver'
10
+ require 'ruote-nats/shell_executor'
11
+ require 'ruote-nats/version'
12
+
13
+ module RuoteNATS
14
+ class << self
15
+ # Get the logger.
16
+ #
17
+ # @return [Logger] logger
18
+ def logger
19
+ @logger ||= Logger.new(STDOUT).tap { |log| log.level = Logger::INFO }
20
+ end
21
+
22
+ # Sets the logger.
23
+ #
24
+ # @param [Logger] logger
25
+ def logger=(logger)
26
+ @logger = logger
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ module RuoteNATS
2
+ class CommandReceiver
3
+
4
+ # Starts to subscribe command queue.
5
+ #
6
+ # @param [String] queue_name
7
+ def start(queue_name = 'remote.command')
8
+ NATS.subscribe(queue_name, queue: queue_name, max: 1) do |message, reply|
9
+ NATS.publish(reply, 'ACCEPT') do
10
+ unpacked = MessagePack.unpack(message)
11
+ workitem = Ruote::Workitem.new(unpacked)
12
+
13
+ RuoteNATS.logger.info do
14
+ "(#{workitem.sid}) receive command: #{lookup_executor(workitem)} (#{workitem.lookup('params')})"
15
+ end
16
+
17
+ dispatch(workitem)
18
+ publish_reply(workitem)
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+ def dispatch(workitem)
25
+ executor = lookup_executor(workitem)
26
+ results = constantize(executor).new.execute(workitem)
27
+ rescue
28
+ workitem.result = 'error'
29
+ results = { message: $!.message, backtrace: $!.backtrace }
30
+ ensure
31
+ store_results(workitem, results)
32
+ end
33
+
34
+ def lookup_executor(workitem)
35
+ workitem.lookup('params.executor') || 'RuoteNATS::ShellExecutor'
36
+ end
37
+
38
+ def constantize(executor_name)
39
+ names = executor_name.split('::')
40
+ names.shift if names.empty? || names.first.empty?
41
+
42
+ constant = Object
43
+ names.each do |name|
44
+ constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
45
+ end
46
+ constant
47
+ end
48
+
49
+ def store_results(workitem, results)
50
+ params = workitem.lookup('params')
51
+
52
+ workitem.set_field('results', Hash.new) unless workitem.lookup('results')
53
+ workitem.set_field("results.#{workitem.sid}", params.merge(results))
54
+ end
55
+
56
+ def publish_reply(workitem)
57
+ queue_name = workitem.lookup('reply_to') || 'remote.command.reply'
58
+
59
+ packed = MessagePack.pack(workitem.to_h)
60
+ NATS.publish(queue_name, packed) do
61
+ RuoteNATS.logger.info do
62
+ results = workitem.lookup("results.#{workitem.sid}")
63
+ "(#{workitem.sid}) reply: #{lookup_executor(workitem)} (#{results})"
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,50 @@
1
+ module RuoteNATS
2
+
3
+ class TimeoutError < StandardError
4
+ end
5
+
6
+ # # RuoteNATS::Participant
7
+ #
8
+ class Participant
9
+ include Ruote::LocalParticipant
10
+
11
+ DEFALUT_TIMEOUT = 1
12
+
13
+ # @param [Ruote::Workitem] workitem
14
+ def consume(workitem)
15
+ queue_name = workitem.lookup('params.queue') || 'remote.command'
16
+ message = MessagePack.pack(workitem.to_h)
17
+
18
+ sid = NATS.request(queue_name, message) do |reply|
19
+ RuoteNATS.logger.info do
20
+ executor = workitem.lookup('params.executor') || 'RuoteNATS::ShellExecutor'
21
+ "(#{workitem.sid}) request: #{executor} (#{workitem.lookup('params')})"
22
+ end
23
+ end
24
+
25
+ timeout = (workitem.lookup('params.timeout') || DEFALUT_TIMEOUT).to_i
26
+ NATS.timeout(sid, timeout) do
27
+ handle_error(workitem)
28
+ end
29
+ rescue
30
+ RuoteNATS.logger.error($!.message)
31
+ raise $!
32
+ end
33
+
34
+ def cancel
35
+ end
36
+
37
+ private
38
+ def handle_error(workitem)
39
+ executor = workitem.lookup('params.executor') || 'RuoteNATS::ShellExecutor'
40
+ RuoteNATS.logger.error do
41
+ "(#{workitem.sid}) timeout: #{executor} (#{workitem.lookup('params')})"
42
+ end
43
+
44
+ error = TimeoutError.new("Request timeout: workitem could not be processed.")
45
+
46
+ error_handler = context.error_handler
47
+ error_handler.action_handle('error', workitem.to_h['fei'], error)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ module RuoteNATS
2
+ class ReplyReceiver
3
+
4
+ # @param [Ruote::Engine] engine
5
+ def initialize(engine)
6
+ @engine = engine
7
+ end
8
+
9
+ # Start to subscribe reply queue.
10
+ #
11
+ # @param [String] queue name
12
+ def start(queue_name = 'remote.command.reply')
13
+ NATS.subscribe(queue_name) do |message, reply|
14
+ unpacked = MessagePack.unpack(message)
15
+ workitem = Ruote::Workitem.new(unpacked)
16
+
17
+ RuoteNATS.logger.info do
18
+ executor = workitem.lookup('params.executor') || 'RuoteNATS::ShellExecutor'
19
+ result = workitem.lookup("results.#{workitem.sid}")
20
+
21
+ "(#{workitem.sid}) receive reply: #{executor} #{workitem.result} (#{result})"
22
+ end
23
+
24
+ if workitem.result == 'success'
25
+ @engine.reply_to_engine(workitem)
26
+ else
27
+ handle_error(workitem)
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+ def handle_error(workitem)
34
+ message = workitem.lookup("results.#{workitem.sid}.message")
35
+ backtrace = workitem.lookup("results.#{workitem.sid}.backtrace")
36
+
37
+ error = RuntimeError.new(message)
38
+ error.set_backtrace(backtrace)
39
+
40
+ error_handler = @engine.context.error_handler
41
+ error_handler.action_handle('error', workitem.to_h['fei'], error)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ module RuoteNATS
2
+ class ShellExecutor
3
+
4
+ # Execute shell command
5
+ #
6
+ # @param [Ruote::Workitem] workitem
7
+ # @return [Hash] the result of command execution
8
+ def execute(workitem)
9
+ if workitem.lookup('params.command')
10
+ out, status = invoke(workitem)
11
+
12
+ if status.success?
13
+ { out: out, status: status.exitstatus, finished_at: Ruote.now_to_utc_s }
14
+ else
15
+ raise "out: #{out}, status: #{status.exitstatus}, finished_at: #{Ruote.now_to_utc_s}"
16
+ end
17
+ else
18
+ workitem.result = 'failure'
19
+
20
+ message = 'command is not specified, check your process definition'
21
+ RuoteNATS.logger.error do
22
+ "(#{workitem.sid}) shell: #{message}"
23
+ end
24
+ raise message
25
+ end
26
+ end
27
+
28
+ private
29
+ def invoke(workitem)
30
+ params = workitem.lookup('params')
31
+ env = params['env'] || { }
32
+ command = params['command']
33
+
34
+ RuoteNATS.logger.info do
35
+ message = "(#{workitem.sid}) shell: `#{command}`"
36
+ message << " with env #{env.inspect}" if env
37
+ message
38
+ end
39
+
40
+ out, status = Open3.capture2e(env, command)
41
+
42
+ RuoteNATS.logger.info do
43
+ "(#{workitem.sid}) shell: `#{command}` returns #{status.exitstatus}"
44
+ end
45
+ if RuoteNATS.logger.debug?
46
+ out.each_line do |line|
47
+ RuoteNATS.logger.debug "(#{workitem.sid}) shell: #{line.chomp}"
48
+ end
49
+ end
50
+
51
+ return out, status
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module RuoteNATS
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,32 @@
1
+ # -*- mode: ruby; coding: utf-8 -*-
2
+
3
+ require File.expand_path('../lib/ruote-nats/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.authors = ['Naoto Takai']
7
+ gem.email = ['takai@recompile.net']
8
+ gem.description = 'NATS participant and receivers for ruote'
9
+ gem.summary = 'ruote-nats is an implementation of the ruote participant and receivers ' \
10
+ 'to process workitem on remote host using NATS'
11
+ gem.homepage = 'https://github.com/takai/ruote-nats'
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.name = 'ruote-nats'
17
+ gem.require_paths = ['lib']
18
+ gem.version = RuoteNATS::VERSION
19
+
20
+ gem.add_dependency('ruote', '= 2.2.0')
21
+ gem.add_dependency('nats', '>= 0.4.22')
22
+ gem.add_dependency('msgpack', '>= 0.4.6')
23
+
24
+ gem.add_development_dependency('rspec')
25
+ gem.add_development_dependency('rake')
26
+ gem.add_development_dependency('simplecov')
27
+ gem.add_development_dependency('pry')
28
+ gem.add_development_dependency('pry-nav')
29
+ gem.add_development_dependency('yard')
30
+ gem.add_development_dependency('redcarpet')
31
+ gem.add_development_dependency('github-markup')
32
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module RuoteNATS
4
+
5
+ class NoopExecutor
6
+ def execute(workitem)
7
+ { noop: true }
8
+ end
9
+ end
10
+
11
+ describe CommandReceiver do
12
+ let(:dispatcher) { CommandReceiver.new }
13
+ let(:workitem) do
14
+ Ruote::Workitem.new("fields" =>
15
+ { "params" =>
16
+ { "command" => "/bin/date",
17
+ "env" => {
18
+ "LANG" => "C" },
19
+ "ref" => "noop",
20
+ "executor" => "RuoteNATS::NoopExecutor" },
21
+ "dispatched_at" => "2000-01-01 11:11:11.111111 UTC" },
22
+ "fei" =>
23
+ { "engine_id" => "engine",
24
+ "wfid" => "20000101-abcdefg",
25
+ "subid" => "abcdefghijklmnopqrstu",
26
+ "expid" => "0_0" },
27
+ "participant_name" => "noop")
28
+ end
29
+
30
+ around :each do |example|
31
+ NATS.start(autostart: true) { example.run }
32
+ end
33
+
34
+ describe '#start' do
35
+ context do
36
+ it 'starts to subscribe queue' do
37
+ sid = NATS.subscribe('remote.command.reply') do |message|
38
+ unpacked = MessagePack.unpack(message)
39
+ workitem = Ruote::Workitem.new(unpacked)
40
+ workitem.lookup("results.#{workitem.sid}").should include("noop" => true)
41
+
42
+ NATS.stop
43
+ end
44
+ NATS.timeout(sid, 1, expected: 1) do
45
+ NATS.stop
46
+ fail "reply message is not sent"
47
+ end
48
+
49
+ subject.start
50
+ message = MessagePack.pack(workitem.to_h)
51
+ NATS.request('remote.command', message) do |reply|
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module RuoteNATS
4
+ describe Participant do
5
+ around :each do |example|
6
+ NATS.start(autostart: true) { example.run }
7
+ end
8
+
9
+ let(:workitem) do
10
+ Ruote::Workitem.new("fields" =>
11
+ { "params" =>
12
+ { "command" => "/bin/date",
13
+ "env" => {
14
+ "LANG" => "C" },
15
+ "ref" => "shell" },
16
+ "dispatched_at" => "2000-01-01 11:11:11.111111 UTC" },
17
+ "fei" =>
18
+ { "engine_id" => "engine",
19
+ "wfid" => "20000101-abcdefg",
20
+ "subid" => "abcdefghijklmnopqrstu",
21
+ "expid" => "0_0" },
22
+ "participant_name" => "shell")
23
+ end
24
+
25
+ describe '#consume' do
26
+ context 'send successfully' do
27
+ it 'sends command message' do
28
+ sid = NATS.subscribe('remote.command', queue: 'remote.command', max: 1) do |message, reply|
29
+ unpacked = MessagePack.unpack(message)
30
+ unpacked.should eq workitem.to_h
31
+
32
+ NATS.publish(reply, 'ACCEPT') do
33
+ NATS.stop
34
+ end
35
+ end
36
+ NATS.timeout(sid, 1, expected: 1) do
37
+ NATS.stop
38
+ fail "command message is not sent"
39
+ end
40
+
41
+ subject.consume(workitem)
42
+ end
43
+ end
44
+ end
45
+ context 'send successfully' do
46
+ before { subject.context = MockContext.new }
47
+
48
+ it 'sends command message' do
49
+ EM.add_timer(2) do
50
+ NATS.stop
51
+ fail "#handle_error must be called"
52
+ end
53
+ subject.consume(workitem)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ module RuoteNATS
4
+
5
+ describe ReplyReceiver do
6
+ around :each do |example|
7
+ NATS.start(autostart: true) { example.run }
8
+ end
9
+
10
+ let(:engine) { MockEngine.new }
11
+ let(:receiver) { ReplyReceiver.new(engine) }
12
+ let(:message) { MessagePack.pack(workitem.to_h) }
13
+
14
+ describe '#start' do
15
+ context 'success' do
16
+ let(:workitem) do
17
+ Ruote::Workitem.new("fields" =>
18
+ { "params" =>
19
+ { "executor" => "ReplyReceiverSpec" },
20
+ "dispatched_at" => "2000-01-01 11:11:11.111111 UTC",
21
+ "__result__" => "success" },
22
+ "fei" =>
23
+ { "engine_id" => "engine",
24
+ "wfid" => "20000101-abcdefg",
25
+ "subid" => "abcdefghijklmnopqrstu",
26
+ "expid" => "0_0" },
27
+ "participant_name" => "shell")
28
+ end
29
+
30
+ it 'replies to engine' do
31
+ receiver.start
32
+ NATS.publish('remote.command.reply', message)
33
+
34
+ EM.add_timer(1) do
35
+ fail "#reply_to_engine must be called"
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'failure' do
41
+ let(:workitem) do
42
+ Ruote::Workitem.new("fields" =>
43
+ { "params" =>
44
+ { "executor" => "ReplyReceiverSpec" },
45
+ "dispatched_at" => "2000-01-01 11:11:11.111111 UTC",
46
+ "__result__" => "failure" },
47
+ "fei" =>
48
+ { "engine_id" => "engine",
49
+ "wfid" => "20000101-abcdefg",
50
+ "subid" => "abcdefghijklmnopqrstu",
51
+ "expid" => "0_0" },
52
+ "participant_name" => "shell")
53
+ end
54
+ it 'replies to engine' do
55
+ handler = double.as_null_object
56
+ engine.stub_chain(:context, :error_handler => handler)
57
+
58
+ receiver.start
59
+ NATS.publish('remote.command.reply', message)
60
+
61
+ EM.add_timer(1) do
62
+ fail "#handle_error must be called"
63
+ NATS.stop
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ module RuoteNATS
4
+ describe ShellExecutor do
5
+ describe '#execute' do
6
+ subject { ShellExecutor.new.execute(workitem) }
7
+
8
+ context 'with command and env fields' do
9
+ let(:workitem) do
10
+ Ruote::Workitem.new("fields" =>
11
+ { "params" =>
12
+ { "command" => "ruby -e 'print ENV[\"LANG\"]'",
13
+ "env" => {
14
+ "LANG" => "ja_JP.UTF-8" },
15
+ "ref" => "shell" },
16
+ "dispatched_at" => "2000-01-01 11:11:11.111111 UTC" },
17
+ "fei" =>
18
+ { "engine_id" => "engine",
19
+ "wfid" => "20000101-abcdefg",
20
+ "subid" => "abcdefghijklmnopqrstu",
21
+ "expid" => "0_0" },
22
+ "participant_name" => "shell")
23
+ end
24
+ it { should include(out: "ja_JP.UTF-8") }
25
+ end
26
+
27
+ context 'without command fields' do
28
+ let(:workitem) do
29
+ Ruote::Workitem.new("fields" =>
30
+ { "params" =>
31
+ { "ref" => "shell" },
32
+ "dispatched_at" => "2000-01-01 11:11:11.111111 UTC" },
33
+ "fei" =>
34
+ { "engine_id" => "engine",
35
+ "wfid" => "20000101-abcdefg",
36
+ "subid" => "abcdefghijklmnopqrstu",
37
+ "expid" => "0_0" },
38
+ "participant_name" => "send_command")
39
+ end
40
+ it { expect{ subject }.to raise_error(RuntimeError, 'command is not specified, check your process definition') }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,46 @@
1
+ # -*- mode:ruby; coding: utf-8 -*-
2
+
3
+ require 'eventmachine'
4
+ require 'simplecov'
5
+ SimpleCov.start { add_filter 'spec' }
6
+
7
+ require 'ruote-nats'
8
+
9
+ RSpec.configure do |config|
10
+ config.before(:all) do
11
+ RuoteNATS.logger.level = Logger::DEBUG
12
+ end
13
+
14
+ config.after(:all) do
15
+ begin
16
+ pid = IO.read('/tmp/nats-server.pid')
17
+ `kill -TERM #{pid}`
18
+ rescue Errno::ENOENT
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ module RuoteNATS
25
+ class MockErrorHandler
26
+ def action_handle(action, fei, exception)
27
+ NATS.stop
28
+ end
29
+ end
30
+
31
+ class MockContext
32
+ def error_handler
33
+ MockErrorHandler.new
34
+ end
35
+ end
36
+
37
+ class MockEngine
38
+ def reply_to_engine(workitem)
39
+ NATS.stop
40
+ end
41
+
42
+ def context
43
+ MockContext.new
44
+ end
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,248 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruote-nats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Naoto Takai
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ruote
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: nats
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.4.22
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.22
46
+ - !ruby/object:Gem::Dependency
47
+ name: msgpack
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.6
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.4.6
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: pry
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: pry-nav
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: yard
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: redcarpet
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: github-markup
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ description: NATS participant and receivers for ruote
191
+ email:
192
+ - takai@recompile.net
193
+ executables: []
194
+ extensions: []
195
+ extra_rdoc_files: []
196
+ files:
197
+ - .gitignore
198
+ - .yardopts
199
+ - Gemfile
200
+ - LICENSE
201
+ - README.md
202
+ - Rakefile
203
+ - example/single_file.rb
204
+ - image/system-diagram.png
205
+ - lib/ruote-nats.rb
206
+ - lib/ruote-nats/command_receiver.rb
207
+ - lib/ruote-nats/participant.rb
208
+ - lib/ruote-nats/reply_receiver.rb
209
+ - lib/ruote-nats/shell_executor.rb
210
+ - lib/ruote-nats/version.rb
211
+ - ruote-nats.gemspec
212
+ - spec/command_receiver_spec.rb
213
+ - spec/participant_spec.rb
214
+ - spec/reply_receiver_spec.rb
215
+ - spec/shell_executor_spec.rb
216
+ - spec/spec_helper.rb
217
+ homepage: https://github.com/takai/ruote-nats
218
+ licenses: []
219
+ post_install_message:
220
+ rdoc_options: []
221
+ require_paths:
222
+ - lib
223
+ required_ruby_version: !ruby/object:Gem::Requirement
224
+ none: false
225
+ requirements:
226
+ - - ! '>='
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ required_rubygems_version: !ruby/object:Gem::Requirement
230
+ none: false
231
+ requirements:
232
+ - - ! '>='
233
+ - !ruby/object:Gem::Version
234
+ version: '0'
235
+ requirements: []
236
+ rubyforge_project:
237
+ rubygems_version: 1.8.23
238
+ signing_key:
239
+ specification_version: 3
240
+ summary: ruote-nats is an implementation of the ruote participant and receivers to
241
+ process workitem on remote host using NATS
242
+ test_files:
243
+ - spec/command_receiver_spec.rb
244
+ - spec/participant_spec.rb
245
+ - spec/reply_receiver_spec.rb
246
+ - spec/shell_executor_spec.rb
247
+ - spec/spec_helper.rb
248
+ has_rdoc: