fare 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 +7 -0
- data/.gitignore +20 -0
- data/.rspec +4 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/README.md +470 -0
- data/Rakefile +28 -0
- data/bin/fare +48 -0
- data/fare.gemspec +35 -0
- data/features/multiqueue.feature +60 -0
- data/features/multistack.feature +65 -0
- data/features/step_definitions/aruba.rb +1 -0
- data/features/step_definitions/fare_steps.rb +40 -0
- data/features/subscriber.feature +95 -0
- data/features/support/env.rb +34 -0
- data/lib/fare.rb +96 -0
- data/lib/fare/configuration.rb +57 -0
- data/lib/fare/configuration_dsl.rb +134 -0
- data/lib/fare/configuration_when_locked.rb +82 -0
- data/lib/fare/event.rb +26 -0
- data/lib/fare/generate_lock_file.rb +131 -0
- data/lib/fare/load_configuration_file.rb +45 -0
- data/lib/fare/middleware/logging.rb +46 -0
- data/lib/fare/middleware/newrelic.rb +35 -0
- data/lib/fare/middleware/raven.rb +47 -0
- data/lib/fare/publisher.rb +65 -0
- data/lib/fare/queue_adapter.rb +30 -0
- data/lib/fare/rspec.rb +85 -0
- data/lib/fare/subscriber.rb +35 -0
- data/lib/fare/subscriber_cli.rb +270 -0
- data/lib/fare/subscriber_stack.rb +39 -0
- data/lib/fare/test_mode.rb +204 -0
- data/lib/fare/topic.rb +25 -0
- data/lib/fare/topic_adapter.rb +13 -0
- data/lib/fare/update_cli.rb +41 -0
- data/lib/fare/version.rb +3 -0
- data/spec/logger_spec.rb +45 -0
- data/spec/raven_spec.rb +52 -0
- data/spec/rspec_integration_spec.rb +45 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/stubbed_subscribing_spec.rb +66 -0
- metadata +264 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
module Fare
|
4
|
+
module Middleware
|
5
|
+
|
6
|
+
# Use this to log all events and stacktraces:
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# use Fare::Middleware::Logging, logger: Logger.new($stdout)
|
11
|
+
class Logging
|
12
|
+
|
13
|
+
def initialize(app, options = {})
|
14
|
+
@app = app
|
15
|
+
@logger = options.fetch(:logger)
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
attrs = env.fetch(:event).attributes
|
20
|
+
start = Time.now
|
21
|
+
begin
|
22
|
+
@app.call(env)
|
23
|
+
rescue Exception => exception
|
24
|
+
duration = Time.now - start
|
25
|
+
@logger.warn("Handled event: %s" % {
|
26
|
+
event: attrs,
|
27
|
+
result: "failure",
|
28
|
+
duration: duration,
|
29
|
+
error_class: exception.class.name,
|
30
|
+
error_message: exception.message,
|
31
|
+
backtrace: exception.backtrace.to_a,
|
32
|
+
}.to_json)
|
33
|
+
raise
|
34
|
+
else
|
35
|
+
duration = Time.now - start
|
36
|
+
@logger.info("Handled event: %s" % {
|
37
|
+
event: attrs,
|
38
|
+
result: "success",
|
39
|
+
duration: duration,
|
40
|
+
}.to_json)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'newrelic_rpm'
|
2
|
+
::NewRelic::Agent.manual_start
|
3
|
+
|
4
|
+
module Fare
|
5
|
+
module Middleware
|
6
|
+
|
7
|
+
# Add NewRelic monitoring to the subscriber.
|
8
|
+
# Make sure you have a newrelic.yml in your config dir.
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
#
|
12
|
+
# subscriber do
|
13
|
+
# setup do
|
14
|
+
# require "fare/middleware/newrelic"
|
15
|
+
# end
|
16
|
+
# always_run do
|
17
|
+
# use Fare::Middleware::NewRelic
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
class NewRelic
|
21
|
+
include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
22
|
+
|
23
|
+
def initialize(app, options = {})
|
24
|
+
@app = app
|
25
|
+
at_exit { ::NewRelic::Agent.shutdown }
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(env)
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
add_transaction_tracer :call, :category => :task
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Fare
|
2
|
+
module Middleware
|
3
|
+
|
4
|
+
# Use this to send errors to Sentry:
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
#
|
8
|
+
# use Fare::Middleware::Raven, dsn: "http://...", logger: logger, environment: "production"
|
9
|
+
class Raven
|
10
|
+
|
11
|
+
def initialize(app, options = {})
|
12
|
+
@app = app
|
13
|
+
require "raven" unless defined?(::Raven)
|
14
|
+
configure_sentry(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
::Raven.extra_context(serialize(env))
|
19
|
+
@app.call(env)
|
20
|
+
rescue Exception => exception
|
21
|
+
::Raven.capture_exception(exception)
|
22
|
+
raise
|
23
|
+
ensure
|
24
|
+
::Raven::Context.clear!
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def configure_sentry(options)
|
30
|
+
::Raven.configure do |config|
|
31
|
+
config.dsn = options.fetch(:dsn)
|
32
|
+
config.logger = options.fetch(:logger)
|
33
|
+
config.environments = [options.fetch(:environment)]
|
34
|
+
config.excluded_exceptions = []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# removes objects and makes normal hashes, so sentry can read the better
|
39
|
+
def serialize(env)
|
40
|
+
JSON.parse(env.to_json)
|
41
|
+
rescue
|
42
|
+
env
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Fare
|
2
|
+
UnknownTopicError = Class.new(RuntimeError)
|
3
|
+
|
4
|
+
class Publisher
|
5
|
+
|
6
|
+
attr_reader :configuration, :options
|
7
|
+
|
8
|
+
def initialize(configuration, options)
|
9
|
+
@configuration = configuration
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
ensure_topic_publishable!
|
15
|
+
topic.publish(event.serialize)
|
16
|
+
end
|
17
|
+
|
18
|
+
def topic
|
19
|
+
Fare.topic_adapter.fetch(topic_info.fetch("arn"))
|
20
|
+
end
|
21
|
+
|
22
|
+
def topic_info
|
23
|
+
@topic_info ||= configuration.find_publishable_topic(options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def event
|
27
|
+
Event.new(
|
28
|
+
id: "event-#{SecureRandom.uuid}",
|
29
|
+
subject: subject,
|
30
|
+
action: action,
|
31
|
+
payload: payload,
|
32
|
+
source: app_name,
|
33
|
+
version: version,
|
34
|
+
sent_at: Time.now.utc,
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def subject
|
39
|
+
options.fetch(:subject)
|
40
|
+
end
|
41
|
+
|
42
|
+
def action
|
43
|
+
options.fetch(:action)
|
44
|
+
end
|
45
|
+
|
46
|
+
def payload
|
47
|
+
options.fetch(:payload)
|
48
|
+
end
|
49
|
+
|
50
|
+
def version
|
51
|
+
topic_info.fetch("version")
|
52
|
+
end
|
53
|
+
|
54
|
+
def app_name
|
55
|
+
configuration.app_name
|
56
|
+
end
|
57
|
+
|
58
|
+
def ensure_topic_publishable!
|
59
|
+
unless topic_info
|
60
|
+
raise UnknownTopicError, "Topic with subject #{subject} and action #{action} not in lock file, maybe run `fare update`"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Fare
|
2
|
+
class QueueAdapter
|
3
|
+
|
4
|
+
def self.fetch(*args)
|
5
|
+
new(*args).queue
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :environment, :name
|
9
|
+
|
10
|
+
def initialize(environment, name)
|
11
|
+
@environment = environment
|
12
|
+
@name = name
|
13
|
+
end
|
14
|
+
|
15
|
+
def queue
|
16
|
+
sqs.queues.named(queue_name)
|
17
|
+
rescue AWS::SQS::Errors::NonExistentQueue
|
18
|
+
sqs.queues.create(queue_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def queue_name
|
22
|
+
"#{environment}-#{name}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def sqs
|
26
|
+
AWS::SQS.new
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/fare/rspec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
begin
|
2
|
+
require "json_expressions"
|
3
|
+
rescue LoadError
|
4
|
+
raise "Please install the gem `json_expressions` to use fare/rspec"
|
5
|
+
end
|
6
|
+
|
7
|
+
module Fare
|
8
|
+
module FareMatcher
|
9
|
+
|
10
|
+
def publish(subject, action, payload = nil)
|
11
|
+
Expectation.new(subject, action, payload)
|
12
|
+
end
|
13
|
+
|
14
|
+
class Expectation
|
15
|
+
|
16
|
+
attr_reader :subject, :action, :payload
|
17
|
+
|
18
|
+
def initialize(subject, action, payload)
|
19
|
+
@subject = subject
|
20
|
+
@action = action
|
21
|
+
@payload = payload
|
22
|
+
end
|
23
|
+
|
24
|
+
def supports_block_expectations?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def matches?(expect_block)
|
29
|
+
Fare.stubbed_messages.clear
|
30
|
+
expect_block.call
|
31
|
+
!event.nil? && payload_matches?
|
32
|
+
end
|
33
|
+
|
34
|
+
def does_not_match?(expect_block)
|
35
|
+
raise ArgumentError, "Checking payload with negative expectation is not possible" if payload
|
36
|
+
Fare.stubbed_messages.clear
|
37
|
+
expect_block.call
|
38
|
+
event.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message
|
42
|
+
if event.nil?
|
43
|
+
if Fare.stubbed_messages.size == 0
|
44
|
+
"There were no events published"
|
45
|
+
else
|
46
|
+
"Expected event #{event_name}, but got:\n#{Fare.stubbed_messages.list}"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
"Payload did not match: #{payload_matcher.last_error}\nActual payload was:\n#{event.payload}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def failure_message_when_negated
|
54
|
+
"Expected not to publish #{event_name}, but published it with payload: #{event.payload}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def event_name
|
58
|
+
"#{subject}##{action}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def payload_matches?
|
62
|
+
if payload
|
63
|
+
payload_matcher =~ event.payload
|
64
|
+
else
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def event
|
70
|
+
Fare.stubbed_messages.get(subject, action)
|
71
|
+
end
|
72
|
+
|
73
|
+
def payload_matcher
|
74
|
+
@payload_matcher ||= JsonExpressions::Matcher.new(payload)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
RSpec.configure do |config|
|
84
|
+
config.include Fare::FareMatcher
|
85
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "timeout"
|
2
|
+
|
3
|
+
module Fare
|
4
|
+
class Subscriber
|
5
|
+
UnknownSubscriber = Class.new(ArgumentError)
|
6
|
+
|
7
|
+
attr_reader :configuration
|
8
|
+
|
9
|
+
def initialize(configuration, options = {})
|
10
|
+
name = (options[:name] || configuration.app_name).to_s
|
11
|
+
subscriber_config = configuration.fetch_subscriber(name)
|
12
|
+
subscriber_config.load_setup
|
13
|
+
@sqs_queue = configuration.fetch_subscriber_queue(name)
|
14
|
+
@stacks = subscriber_config.stacks
|
15
|
+
end
|
16
|
+
|
17
|
+
def produce(queue)
|
18
|
+
message = @sqs_queue.receive_message(attributes: [:all])
|
19
|
+
if message
|
20
|
+
queue << message
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def consume(message)
|
25
|
+
event = Event.deserialize(message.body)
|
26
|
+
@stacks.each do |stack|
|
27
|
+
if stack.handles?(event)
|
28
|
+
stack.to_app.call(event: event)
|
29
|
+
message.delete
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require "daemonic"
|
2
|
+
|
3
|
+
module Fare
|
4
|
+
class SubscriberCLI
|
5
|
+
|
6
|
+
attr_reader :argv, :command
|
7
|
+
|
8
|
+
def initialize(argv)
|
9
|
+
@command = argv.shift
|
10
|
+
@argv = argv
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
case command
|
15
|
+
when nil, "-h", "--help", "help"
|
16
|
+
show_help
|
17
|
+
exit 0
|
18
|
+
when "start"
|
19
|
+
start
|
20
|
+
when "stop"
|
21
|
+
stop
|
22
|
+
when "status"
|
23
|
+
status
|
24
|
+
when "restart"
|
25
|
+
restart
|
26
|
+
else
|
27
|
+
puts "Unkown command: #{command}"
|
28
|
+
puts
|
29
|
+
show_help
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def start
|
37
|
+
fare_options = {
|
38
|
+
filename: Fare.default_config_file,
|
39
|
+
environment: (Fare.default_environment || "development"),
|
40
|
+
}
|
41
|
+
daemon_options = {
|
42
|
+
concurrency: 4,
|
43
|
+
startup_timeout: 20,
|
44
|
+
}
|
45
|
+
subscriber_options = {}
|
46
|
+
optparser = OptionParser.new do |parser|
|
47
|
+
|
48
|
+
parser.banner = "Usage: fare subscriber start [options]"
|
49
|
+
|
50
|
+
|
51
|
+
parser.on "-E", "--environment ENV", "Set the environment (default: #{fare_options[:environment]})" do |environment|
|
52
|
+
fare_options[:environment] = environment
|
53
|
+
end
|
54
|
+
|
55
|
+
parser.on "--filename FILENAME", "Location of the Fare configuration file (default: #{fare_options[:filename]})" do |filename|
|
56
|
+
fare_options[:filename] = filename
|
57
|
+
end
|
58
|
+
|
59
|
+
parser.on "--name NAME", "Which named subscriber to run (default is the unnamed one)" do |name|
|
60
|
+
subscriber_options[:name] = name
|
61
|
+
end
|
62
|
+
|
63
|
+
parser.separator ""
|
64
|
+
parser.separator "Process options:"
|
65
|
+
|
66
|
+
parser.on "-c", "--concurrency NUM", Integer, "Set the number of threads (default: #{daemon_options[:concurrency]}" do |concurrency|
|
67
|
+
daemon_options[:concurrency] = concurrency
|
68
|
+
end
|
69
|
+
|
70
|
+
parser.on "-P", "--pid FILE", "The location of the PID file (required when daemonizing)" do |pid|
|
71
|
+
daemon_options[:pid] = pid
|
72
|
+
end
|
73
|
+
|
74
|
+
parser.on "--[no-]daemonize", "Should the subscriber detach?" do |daemonize|
|
75
|
+
daemon_options[:daemonize] = daemonize
|
76
|
+
end
|
77
|
+
|
78
|
+
parser.on "--startup-timeout TIMEOUT", Integer, "How long to wait for the process to start (default: #{daemon_options[:startup_timeout]})" do |timeout|
|
79
|
+
daemon_options[:startup_timeout] = timeout
|
80
|
+
end
|
81
|
+
|
82
|
+
parser.separator ""
|
83
|
+
parser.separator "Logging options:"
|
84
|
+
|
85
|
+
parser.on "--log FILE", "Where to log to" do |log|
|
86
|
+
daemon_options[:log] = log
|
87
|
+
end
|
88
|
+
|
89
|
+
parser.on "--log-level LEVEL", %w(debug info warn fatal), "Set the log level (default: info)" do |level|
|
90
|
+
daemon_options[:log_level] = Logger.const_get(level.upcase)
|
91
|
+
end
|
92
|
+
|
93
|
+
parser.separator ""
|
94
|
+
parser.separator "Other options:"
|
95
|
+
|
96
|
+
parser.on_tail "-h", "--help", "Shows this help page" do
|
97
|
+
puts parser
|
98
|
+
exit
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
optparser.parse!(argv)
|
104
|
+
|
105
|
+
|
106
|
+
Daemonic.start(daemon_options) {
|
107
|
+
Fare.config(fare_options)
|
108
|
+
Subscriber.new(Fare.configuration, subscriber_options)
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def stop
|
113
|
+
daemon_options = {
|
114
|
+
stop_timeout: 10
|
115
|
+
}
|
116
|
+
optparser = OptionParser.new do |parser|
|
117
|
+
|
118
|
+
parser.banner = "Usage: fare subscriber stop [options]"
|
119
|
+
|
120
|
+
|
121
|
+
parser.separator ""
|
122
|
+
parser.separator "Process options:"
|
123
|
+
|
124
|
+
parser.on "-P", "--pid FILE", "The location of the PID file" do |pid|
|
125
|
+
daemon_options[:pid] = pid
|
126
|
+
end
|
127
|
+
|
128
|
+
parser.on "--stop-timeout TIMEOUT", Integer, "How long to wait for the process to stop (default: #{daemon_options[:stop_timeout]})" do |timeout|
|
129
|
+
daemon_options[:stop_timeout] = timeout
|
130
|
+
end
|
131
|
+
|
132
|
+
parser.separator ""
|
133
|
+
parser.separator "Other options:"
|
134
|
+
|
135
|
+
parser.on_tail "-h", "--help", "Shows this help page" do
|
136
|
+
puts parser
|
137
|
+
exit
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
optparser.parse!(argv)
|
143
|
+
|
144
|
+
Daemonic.stop(daemon_options)
|
145
|
+
end
|
146
|
+
|
147
|
+
def restart
|
148
|
+
fare_options = {
|
149
|
+
filename: Fare.default_config_file,
|
150
|
+
environment: (Fare.default_environment || "development"),
|
151
|
+
}
|
152
|
+
daemon_options = {
|
153
|
+
concurrency: 4,
|
154
|
+
stop_timeout: 10,
|
155
|
+
startup_timeout: 20,
|
156
|
+
}
|
157
|
+
subscriber_options = {}
|
158
|
+
optparser = OptionParser.new do |parser|
|
159
|
+
|
160
|
+
parser.banner = "Usage: fare subscriber start [options]"
|
161
|
+
|
162
|
+
parser.on "-E", "--environment ENV", "Set the environment (default: #{fare_options[:environment]})" do |environment|
|
163
|
+
fare_options[:environment] = environment
|
164
|
+
end
|
165
|
+
|
166
|
+
parser.on "--filename FILENAME", "Location of the Fare configuration file (default: #{fare_options[:filename]})" do |filename|
|
167
|
+
fare_options[:filename] = filename
|
168
|
+
end
|
169
|
+
|
170
|
+
parser.on "--name NAME", "Which named subscriber to run (default is the unnamed one)" do |name|
|
171
|
+
subscriber_options[:name] = name
|
172
|
+
end
|
173
|
+
|
174
|
+
parser.separator ""
|
175
|
+
parser.separator "Process options:"
|
176
|
+
|
177
|
+
parser.on "-c", "--concurrency NUM", Integer, "Set the number of threads (default: #{daemon_options[:concurrency]}" do |concurrency|
|
178
|
+
daemon_options[:concurrency] = concurrency
|
179
|
+
end
|
180
|
+
|
181
|
+
parser.on "-P", "--pid FILE", "The location of the PID file (required)" do |pid|
|
182
|
+
daemon_options[:pid] = pid
|
183
|
+
end
|
184
|
+
|
185
|
+
parser.on "--startup-timeout TIMEOUT", Integer, "How long to wait for the process to start (default: #{daemon_options[:startup_timeout]})" do |timeout|
|
186
|
+
daemon_options[:startup_timeout] = timeout
|
187
|
+
end
|
188
|
+
|
189
|
+
parser.on "--stop-timeout TIMEOUT", Integer, "How long to wait for the process to stop (default: #{daemon_options[:stop_timeout]})" do |timeout|
|
190
|
+
daemon_options[:stop_timeout] = timeout
|
191
|
+
end
|
192
|
+
|
193
|
+
parser.separator ""
|
194
|
+
parser.separator "Logging options:"
|
195
|
+
|
196
|
+
parser.on "--log FILE", "Where to log to" do |log|
|
197
|
+
daemon_options[:log] = log
|
198
|
+
end
|
199
|
+
|
200
|
+
parser.on "--log-level LEVEL", %w(debug info warn fatal), "Set the log level (default: info)" do |level|
|
201
|
+
daemon_options[:log_level] = Logger.const_get(level.upcase)
|
202
|
+
end
|
203
|
+
|
204
|
+
parser.separator ""
|
205
|
+
parser.separator "Other options:"
|
206
|
+
|
207
|
+
parser.on_tail "-h", "--help", "Shows this help page" do
|
208
|
+
puts parser
|
209
|
+
exit
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
optparser.parse!(argv)
|
215
|
+
|
216
|
+
Daemonic.restart(daemon_options) {
|
217
|
+
Fare.config(fare_options)
|
218
|
+
Subscriber.new(Fare.configuration, subscriber_options)
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
def status
|
223
|
+
daemon_options = {
|
224
|
+
}
|
225
|
+
optparser = OptionParser.new do |parser|
|
226
|
+
|
227
|
+
parser.banner = "Usage: fare subscriber status [options]"
|
228
|
+
|
229
|
+
parser.separator ""
|
230
|
+
parser.separator "Process options:"
|
231
|
+
|
232
|
+
parser.on "-P", "--pid FILE", "The location of the PID file" do |pid|
|
233
|
+
daemon_options[:pid] = pid
|
234
|
+
end
|
235
|
+
|
236
|
+
parser.separator ""
|
237
|
+
parser.separator "Other options:"
|
238
|
+
|
239
|
+
parser.on_tail "-h", "--help", "Shows this help page" do
|
240
|
+
puts parser
|
241
|
+
exit
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
optparser.parse!(argv)
|
247
|
+
|
248
|
+
Daemonic.status(daemon_options)
|
249
|
+
end
|
250
|
+
|
251
|
+
def show_help
|
252
|
+
puts <<-HELP.gsub(/^ +/, '')
|
253
|
+
Usage: fare subscriber COMMAND [OPTIONS]
|
254
|
+
|
255
|
+
Available commands:
|
256
|
+
|
257
|
+
fare subscriber start [options]
|
258
|
+
fare subscriber stop [options]
|
259
|
+
fare subscriber status [options]
|
260
|
+
fare subscriber restart [options]
|
261
|
+
|
262
|
+
You can run any command with the --help option.
|
263
|
+
|
264
|
+
Example: fare subscriber start --help
|
265
|
+
HELP
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
end
|
270
|
+
end
|