ruote-nats 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: