tochtli 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +14 -0
- data/Gemfile +32 -0
- data/History.md +138 -0
- data/README.md +46 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/assets/communication.png +0 -0
- data/assets/layers.png +0 -0
- data/examples/01-screencap-service/Gemfile +3 -0
- data/examples/01-screencap-service/README.md +5 -0
- data/examples/01-screencap-service/client.rb +15 -0
- data/examples/01-screencap-service/common.rb +15 -0
- data/examples/01-screencap-service/server.rb +26 -0
- data/examples/02-log-analyzer/Gemfile +3 -0
- data/examples/02-log-analyzer/README.md +5 -0
- data/examples/02-log-analyzer/client.rb +95 -0
- data/examples/02-log-analyzer/common.rb +33 -0
- data/examples/02-log-analyzer/sample.log +10001 -0
- data/examples/02-log-analyzer/server.rb +133 -0
- data/lib/tochtli.rb +177 -0
- data/lib/tochtli/active_record_connection_cleaner.rb +9 -0
- data/lib/tochtli/application.rb +135 -0
- data/lib/tochtli/base_client.rb +135 -0
- data/lib/tochtli/base_controller.rb +360 -0
- data/lib/tochtli/controller_manager.rb +99 -0
- data/lib/tochtli/engine.rb +15 -0
- data/lib/tochtli/message.rb +114 -0
- data/lib/tochtli/rabbit_client.rb +36 -0
- data/lib/tochtli/rabbit_connection.rb +249 -0
- data/lib/tochtli/reply_queue.rb +129 -0
- data/lib/tochtli/simple_validation.rb +23 -0
- data/lib/tochtli/test.rb +9 -0
- data/lib/tochtli/test/client.rb +28 -0
- data/lib/tochtli/test/controller.rb +66 -0
- data/lib/tochtli/test/integration.rb +78 -0
- data/lib/tochtli/test/memory_cache.rb +22 -0
- data/lib/tochtli/test/test_case.rb +191 -0
- data/lib/tochtli/test/test_unit.rb +22 -0
- data/lib/tochtli/version.rb +3 -0
- data/log_generator.rb +11 -0
- data/test/base_client_test.rb +68 -0
- data/test/controller_functional_test.rb +87 -0
- data/test/controller_integration_test.rb +274 -0
- data/test/controller_manager_test.rb +75 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/config/application.rb +36 -0
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/database.yml +3 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/rabbit.yml +4 -0
- data/test/dummy/db/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/key_matcher_test.rb +100 -0
- data/test/log/.gitkeep +0 -0
- data/test/message_test.rb +80 -0
- data/test/rabbit_client_test.rb +71 -0
- data/test/rabbit_connection_test.rb +151 -0
- data/test/test_helper.rb +32 -0
- data/test/version_test.rb +8 -0
- data/tochtli.gemspec +129 -0
- metadata +259 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 56acd327a8d04ef8de6ca2ab8a2b677e27e276e4
|
4
|
+
data.tar.gz: c0f076e6906b0ef7a401585be0946ec1b8b0d1f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4653fc71fcd32d2a9a21bb9929d9994564b2b3b5e1a680e04faf414705ad7bf9b9bcc8e12e274d653183f2fec2780adb3d872a93c004123c611820479d95cd97
|
7
|
+
data.tar.gz: 4e799d6d4888f1182772ca63dfdcd534fa2255f50926a98bb2a3df8ba1fd0b5b8b897361227e785dfdb5287269400ecac5cae7be9925f6cd2babf2350889fdb9
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'bunny', '~> 1.7.0'
|
4
|
+
gem 'uber'
|
5
|
+
gem 'virtus'
|
6
|
+
gem 'facets', require: false
|
7
|
+
gem 'hooks'
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem 'dalli', '~> 2.6.4'
|
11
|
+
gem 'jeweler', '~> 2.0.1'
|
12
|
+
|
13
|
+
gem 'mini_cache'
|
14
|
+
gem 'yard', '~> 0.8'
|
15
|
+
|
16
|
+
if ENV['RAILS_VER']
|
17
|
+
gem 'sqlite3'
|
18
|
+
rails_ver = ENV['RAILS_VER'] # Setup rails version for tests
|
19
|
+
gem 'rails', rails_ver
|
20
|
+
if rails_ver.to_i < 4
|
21
|
+
gem 'test-unit', '>= 3.0.9'
|
22
|
+
end
|
23
|
+
gem 'tzinfo-data' if RUBY_PLATFORM =~ /mswin|mingw/ && rails_ver >= '4.0' # require tzinfo-data only for Rails 4 on windows
|
24
|
+
gem 'minitest', rails_ver < '4.0' ? '~> 4.7.5' : '~> 5.4.2'
|
25
|
+
gem 'minitest-rails', rails_ver < '4.0' ? '~> 1.0.1' : '~> 2.1.1'
|
26
|
+
else
|
27
|
+
#gem 'rails', '>= 3.2.15'
|
28
|
+
gem 'minitest', '>= 4.7.5'
|
29
|
+
gem 'minitest-reporters', '>= 0.5.0'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/History.md
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
## 0.5.0 / 2015-08-19
|
2
|
+
|
3
|
+
* Usage examples
|
4
|
+
* Key pattern support for a controller routing (ex. on Message, :action, routing_key: 'my.key.*')
|
5
|
+
* Tochtli::BaseController#rabbit_connection delegation
|
6
|
+
* Tochtli::BaseController callbacks: (before|after)_(setup|start|stop|restart) with `hooks` gem
|
7
|
+
* Tochtli::BaseController#restart supports multiple queues
|
8
|
+
* Tochtli::Message#routing_key as a block
|
9
|
+
* Default Tochtli.logger logs on STDERR with WARN level
|
10
|
+
* Tochtli.cache is not obligatory
|
11
|
+
* Get rid of Tochtli::Test cases - replace with concerns (ex. include Tochtli::Test::Client not inherit from)
|
12
|
+
|
13
|
+
## 0.4.0 / 2015-07-10
|
14
|
+
|
15
|
+
* Remove ActiveSupport dependencies (use Facets if Rails not loaded)
|
16
|
+
* Replace ActiveSupport::Cache with MiniCache and fix validation tests
|
17
|
+
* Use RabbitConnection#on_return method with all exchanges
|
18
|
+
* YARD introduced
|
19
|
+
* Tochtli::SimpleValidation for validation error messages
|
20
|
+
* RabbitClient#rabbit_config removed
|
21
|
+
* Removed RabbitClient#publish_and_wait (use SyncMessageHandler
|
22
|
+
* Fix #2: Client error on dropped message
|
23
|
+
* No more automatic routing. All routes have to be defined in the controller. (got rid of the MessageMap)
|
24
|
+
* Message attributes rewritten with Virtus.
|
25
|
+
* Message#bind_topic renamed to route_to
|
26
|
+
* BaseController#subscribe renamed to bind
|
27
|
+
* BaseClient#instance (singleton support) removed
|
28
|
+
* Tochtli::Test::IntegrationHelpers module with methods extracted from Tochtli::Test::Integration
|
29
|
+
* setup and teardown -> before_setup and after_teardown (no need for def setup; super; ... in tests)
|
30
|
+
|
31
|
+
## 0.3.0 / 2015-05-21
|
32
|
+
|
33
|
+
### 4 major enhancements:
|
34
|
+
|
35
|
+
* Process each message in a separate controller instance (`BaseController::Dispatcher` introduced)
|
36
|
+
* Use separate channels and work pools per controller
|
37
|
+
* ControllerManager#start selectively starts controllers
|
38
|
+
* BaseController#start accepts queue name. Multiple queues are supported per single controller.
|
39
|
+
|
40
|
+
### 8 minor enhancements:
|
41
|
+
|
42
|
+
* `queue` & `queue_exists?` methods for TestRabbitConnection
|
43
|
+
* Single reply queue per rabbit connection
|
44
|
+
* configuration_store removed from `RabbitClient` (should be used separately)
|
45
|
+
* `RabbitConnection.logger` default set to `Tochtli.logger`
|
46
|
+
* ActiveRecordConnectionCleaner - a middleware for active connection cleanup
|
47
|
+
* Tochtli.application with middlewares introduced
|
48
|
+
* Network failure recovery rewritten (using automatic bunny recovery with additional reply queue binding recovery)
|
49
|
+
* Bunny logger redirected to RabbitConnection logger with level dependent on Tochtli.debug_bunny (by default WARN)
|
50
|
+
|
51
|
+
### 1 bug fix:
|
52
|
+
|
53
|
+
* `RabbitConnection` logger setup with configuration
|
54
|
+
|
55
|
+
## 0.2.0 / 2015-05-08
|
56
|
+
|
57
|
+
### 1 major enhancement:
|
58
|
+
|
59
|
+
* `RabbitConnection` connection cache. `RabbitConnection.open(configuration_name)` as a standard connection access method.
|
60
|
+
|
61
|
+
### 11 minor enhancements:
|
62
|
+
|
63
|
+
* BaseController callbacks around :start and :setup
|
64
|
+
* Public BaseController#setup method (for manual routing control in tests)
|
65
|
+
* Tochtli::BaseClient tests, expect_published helper method
|
66
|
+
* Tochtli::Message required_attributes and optional_attributes declarations
|
67
|
+
* Tochtli::ServiceCache caches the store object with method: Tochtli::ServiceCache.store
|
68
|
+
* Tochtli::BaseClient singleton methods accept any number of arguments (passed to constructor)
|
69
|
+
* Get rid of ClientProxy. Error handling unified in BaseClient.
|
70
|
+
* Default logger for BaseClient (Tochtli.logger)
|
71
|
+
* Tochtli::Message validation callbacks
|
72
|
+
* Tochtli::Message#ignore_excess_attributes for open messages
|
73
|
+
* assert_published accepts block and yields message
|
74
|
+
|
75
|
+
## 0.1.7 / 2015-04-01
|
76
|
+
|
77
|
+
### 1 minor enhancement:
|
78
|
+
|
79
|
+
* Tochtli::BaseClient introduced (with MessageHandler and SyncMessageHandler)
|
80
|
+
|
81
|
+
## 0.1.6 / 2015-03-02
|
82
|
+
|
83
|
+
### 1 bug fix:
|
84
|
+
|
85
|
+
* Protect RabbitConnection from crash when Rails.root is not set
|
86
|
+
|
87
|
+
## 0.1.5 / 2015-02-06
|
88
|
+
|
89
|
+
### 2 minor enhancement:
|
90
|
+
|
91
|
+
* Test fix: timeout raised
|
92
|
+
* Rails 4.2 compatibility fix
|
93
|
+
|
94
|
+
## 0.1.4 / 2014-11-17
|
95
|
+
|
96
|
+
### 1 minor enhancement:
|
97
|
+
|
98
|
+
* Switched to minitest
|
99
|
+
|
100
|
+
### 1 bug fix:
|
101
|
+
|
102
|
+
* Blocking client proxy should not block on immediate reply (refs #13829)
|
103
|
+
|
104
|
+
## 0.1.3 / 2014-10-28
|
105
|
+
|
106
|
+
### 1 minor enhancement:
|
107
|
+
|
108
|
+
* Remove Rails dependencies
|
109
|
+
|
110
|
+
## 0.1.2 / 2014-10-10
|
111
|
+
|
112
|
+
### 4 minor enhancements:
|
113
|
+
|
114
|
+
* Update corrupted gemspec
|
115
|
+
* Move add_engine_migrations method to hoe-puzzleflow
|
116
|
+
* User always PuzzleFlow gem server
|
117
|
+
* User always PuzzleFlow gem server
|
118
|
+
* rakefile cleaning
|
119
|
+
|
120
|
+
## 0.1.1 / 2014-09-30
|
121
|
+
|
122
|
+
### 1 major enhancement:
|
123
|
+
|
124
|
+
* hoe introduced with git and geminabox integration
|
125
|
+
|
126
|
+
### 1 minor enhancements:
|
127
|
+
|
128
|
+
* do not show ruby warnings (reset RUBY_FLAGS)
|
129
|
+
* hoe-puzzleflow used to unify hoe spec with other PuzzleFlow gems
|
130
|
+
|
131
|
+
## 0.1.0 / 2014-09-29
|
132
|
+
|
133
|
+
### 1 major enhancement
|
134
|
+
|
135
|
+
* Birthday!
|
136
|
+
|
137
|
+
|
138
|
+
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/PuzzleFlow/tochtli.svg?branch=master)](https://travis-ci.org/PuzzleFlow/tochtli)
|
2
|
+
|
3
|
+
# What's Tochtli?
|
4
|
+
|
5
|
+
Tochtli is a set of conventions and tools that simplifies the implementation of components communicating over the RabbitMQ broker.
|
6
|
+
Internally it depends on [bunny](https://github.com/ruby-amqp/bunny) gem.
|
7
|
+
|
8
|
+
## Idea
|
9
|
+
|
10
|
+
![Tochtli Diagram](assets/communication.png)
|
11
|
+
|
12
|
+
The communication between application and service looks like on the above picture.
|
13
|
+
The _application_ calls the _client_ (regular object) methods which expose the _service API_.
|
14
|
+
The _request_ (a message) is created and sent by the _client_ to the _service queue_ (dedicated queue per service controller).
|
15
|
+
_RabbitMQ_ is used as a message broker and delivers the _request_ to the _service controller_.
|
16
|
+
The _controller_ implements the actions that are performed on the _request_ and may result in the _response_.
|
17
|
+
The _response_ message is published on the _reply queue_ (private for a client connection).
|
18
|
+
The _client_ receives the _response_ and returns the expected result to the _application_.
|
19
|
+
The client methods can be implemented in the blocking and non-blocking (asynchronous) way.
|
20
|
+
|
21
|
+
## Layers
|
22
|
+
|
23
|
+
![Tochtli Layers](assets/layers.png)
|
24
|
+
|
25
|
+
The stable service interface really helps to reduce costs of a inevitable change that should only affect the internal implementation.
|
26
|
+
In the proposed above layered structure the application interacts only with the public client class methods.
|
27
|
+
It's not very hard to implement client methods in a such way that they will allow for future changes which won't cause compatibility issues.
|
28
|
+
The expected resistance on the service API changes is a reason way application has no access to the messages definition.
|
29
|
+
Only clients and service controllers operate on the message layer (the common layer).
|
30
|
+
The bottom layer contains tools that allow for communication between the client and the server.
|
31
|
+
There is an option for the message broker agnosticism in the future, because client and service implementation should not directly depend on the particular tool (ex. bunny).
|
32
|
+
|
33
|
+
# What's next?
|
34
|
+
|
35
|
+
Read more about Tochtli and go through the tutorial on [Tochtli homepage](http://puzzleflow.github.io/tochtli).
|
36
|
+
|
37
|
+
# Contributing
|
38
|
+
|
39
|
+
- Fork the project.
|
40
|
+
- Make your feature addition or bug fix.
|
41
|
+
- Add tests for it. This is important so I don't break it in a future version unintentionally.
|
42
|
+
- Send me a pull request.
|
43
|
+
|
44
|
+
# License
|
45
|
+
|
46
|
+
Released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#!/usr/bin/env rake
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
require 'rake'
|
14
|
+
|
15
|
+
require 'rake/testtask'
|
16
|
+
require 'jeweler'
|
17
|
+
require 'yard'
|
18
|
+
|
19
|
+
Jeweler::Tasks.new do |gem|
|
20
|
+
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
21
|
+
gem.name = "tochtli"
|
22
|
+
gem.homepage = "http://github.com/puzzleflow/tochtli"
|
23
|
+
gem.license = "MIT"
|
24
|
+
gem.summary = %Q{Tochtli a core components for SOA}
|
25
|
+
gem.description = %Q{Lightweight framework for service oriented applications based on bunny (RabbitMQ)}
|
26
|
+
gem.email = "rafal.bigaj@puzzleflow.com"
|
27
|
+
gem.authors = ["Rafal Bigaj"]
|
28
|
+
# dependencies defined in Gemfile
|
29
|
+
end
|
30
|
+
Jeweler::RubygemsDotOrgTasks.new
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |test|
|
33
|
+
test.libs << 'lib' << 'test'
|
34
|
+
test.pattern = 'test/**/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Code coverage detail"
|
39
|
+
task :simplecov do
|
40
|
+
ENV['COVERAGE'] = "true"
|
41
|
+
Rake::Task['test'].execute
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
YARD::Rake::YardocTask.new do |t|
|
47
|
+
t.files = ['lib/**/*.rb', 'README*'] # optional
|
48
|
+
t.options = ['--any', '--extra', '--opts'] # optional
|
49
|
+
t.stats_options = ['--list-undoc'] # optional
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
Binary file
|
data/assets/layers.png
ADDED
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
Tochtli.logger.progname = 'CLIENT'
|
4
|
+
|
5
|
+
class ScreenerClient < Tochtli::BaseClient
|
6
|
+
def create_screen(url, file_name)
|
7
|
+
handler = SyncMessageHandler.new
|
8
|
+
message = CreateScreenMessage.new(url: url, file: file_name)
|
9
|
+
rabbit_client.publish message, handler: handler
|
10
|
+
handler.wait!(20)
|
11
|
+
puts "Done in #{handler.reply.time} seconds"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ScreenerClient.new.create_screen(ARGV[0], ARGV[1])
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require
|
3
|
+
|
4
|
+
Tochtli.logger = Logger.new('tochtli.log')
|
5
|
+
|
6
|
+
class CreateScreenMessage < Tochtli::Message
|
7
|
+
route_to 'screener.create'
|
8
|
+
|
9
|
+
attribute :url, String
|
10
|
+
attribute :file, String
|
11
|
+
end
|
12
|
+
|
13
|
+
class CreateScreenReplyMessage < Tochtli::Message
|
14
|
+
attribute :time, Float
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
Tochtli.logger.progname = 'SERVER'
|
4
|
+
|
5
|
+
class ScreenerController < Tochtli::BaseController
|
6
|
+
bind 'screener.*'
|
7
|
+
|
8
|
+
on CreateScreenMessage, :create
|
9
|
+
|
10
|
+
def create
|
11
|
+
start_time = Time.now
|
12
|
+
f = Screencap::Fetcher.new(message.url)
|
13
|
+
f.fetch output: File.join(__dir__, 'images', message.file)
|
14
|
+
total_time = Time.now - start_time
|
15
|
+
reply CreateScreenReplyMessage.new(time: total_time)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Tochtli::ControllerManager.setup
|
20
|
+
Tochtli::ControllerManager.start
|
21
|
+
|
22
|
+
trap('SIGINT') { exit }
|
23
|
+
at_exit { Tochtli::ControllerManager.stop }
|
24
|
+
|
25
|
+
puts 'Press Ctrl-C to stop worker...'
|
26
|
+
sleep
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
Tochtli.logger.progname = 'CLIENT'
|
4
|
+
|
5
|
+
module LogAnalyzer
|
6
|
+
class Client < Tochtli::BaseClient
|
7
|
+
def send_new_log(path)
|
8
|
+
publish NewLog.new(path: path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def react_on_events(client_id, severities, handler=nil, &block)
|
12
|
+
handler = block unless handler
|
13
|
+
severities = Array(severities)
|
14
|
+
routing_keys = severities.map {|severity| "log.events.#{severity}" }
|
15
|
+
Tochtli::ControllerManager.start EventsController,
|
16
|
+
queue_name: "log_analyzer/events/#{client_id}", # custom queue name
|
17
|
+
routing_keys: routing_keys, # make custom binding (only selected severities)
|
18
|
+
env: { handler: handler }
|
19
|
+
end
|
20
|
+
|
21
|
+
def monitor_status(monitor=nil, &block)
|
22
|
+
monitor = block unless monitor
|
23
|
+
Tochtli::ControllerManager.start MonitorController, env: { monitor: monitor }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
class EventsController < Tochtli::BaseController
|
30
|
+
on EventOccurred, :handle, routing_key: 'log.events.*'
|
31
|
+
|
32
|
+
def handle
|
33
|
+
handler.call(message.severity, message.timestamp, message.message)
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def handler
|
39
|
+
raise "Internal Error: handler not set for EventsController" unless env.has_key?(:handler)
|
40
|
+
env[:handler]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class MonitorController < Tochtli::BaseController
|
45
|
+
bind 'log.status'
|
46
|
+
|
47
|
+
self.queue_name = '' # auto generate
|
48
|
+
self.queue_durable = false
|
49
|
+
self.queue_exclusive = true
|
50
|
+
self.queue_auto_delete = true
|
51
|
+
|
52
|
+
on CurrentStatus do
|
53
|
+
monitor.call(message.to_hash)
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def monitor
|
59
|
+
raise "Internal Error: monitor not set for MonitorController" unless env.has_key?(:monitor)
|
60
|
+
env[:monitor]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
client = LogAnalyzer::Client.new
|
66
|
+
command = ARGV[0]
|
67
|
+
|
68
|
+
def hold
|
69
|
+
puts 'Press Ctrl-C to stop...'
|
70
|
+
sleep
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
case command
|
75
|
+
when 's'
|
76
|
+
client.send_new_log ARGV[1]
|
77
|
+
when 'm'
|
78
|
+
client.monitor_status {|status| p status }
|
79
|
+
hold
|
80
|
+
when 'c'
|
81
|
+
client.react_on_events ARGV[1], [:fatal, :error], lambda {|severity, timestamp, message|
|
82
|
+
puts "[#{timestamp}] Got #{severity}: #{message}"
|
83
|
+
}
|
84
|
+
hold
|
85
|
+
else
|
86
|
+
puts "Unknown command: #{command.inspect}"
|
87
|
+
puts
|
88
|
+
puts "Usage: bundle exec ruby client [command] [params]"
|
89
|
+
puts
|
90
|
+
puts "Commands:"
|
91
|
+
puts " s [path] - send log from file to server"
|
92
|
+
puts " m - start status monitor"
|
93
|
+
puts " c [client ID] - catch fatal and error events"
|
94
|
+
end
|
95
|
+
|