minicron 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +187 -0
- data/Rakefile +17 -0
- data/bin/minicron +26 -0
- data/lib/minicron.rb +179 -0
- data/lib/minicron/alert.rb +115 -0
- data/lib/minicron/alert/email.rb +50 -0
- data/lib/minicron/alert/pagerduty.rb +39 -0
- data/lib/minicron/alert/sms.rb +47 -0
- data/lib/minicron/cli.rb +367 -0
- data/lib/minicron/constants.rb +7 -0
- data/lib/minicron/cron.rb +192 -0
- data/lib/minicron/hub/app.rb +132 -0
- data/lib/minicron/hub/assets/app/application.js +151 -0
- data/lib/minicron/hub/assets/app/components/schedules.js +280 -0
- data/lib/minicron/hub/assets/app/controllers/executions.js +35 -0
- data/lib/minicron/hub/assets/app/controllers/hosts.js +129 -0
- data/lib/minicron/hub/assets/app/controllers/jobs.js +109 -0
- data/lib/minicron/hub/assets/app/controllers/schedules.js +80 -0
- data/lib/minicron/hub/assets/app/helpers.js +22 -0
- data/lib/minicron/hub/assets/app/models/execution.js +13 -0
- data/lib/minicron/hub/assets/app/models/host.js +15 -0
- data/lib/minicron/hub/assets/app/models/job.js +15 -0
- data/lib/minicron/hub/assets/app/models/job_execution_output.js +11 -0
- data/lib/minicron/hub/assets/app/models/schedule.js +32 -0
- data/lib/minicron/hub/assets/app/router.js +31 -0
- data/lib/minicron/hub/assets/app/routes/executions.js +36 -0
- data/lib/minicron/hub/assets/app/routes/hosts.js +42 -0
- data/lib/minicron/hub/assets/app/routes/index.js +9 -0
- data/lib/minicron/hub/assets/app/routes/jobs.js +52 -0
- data/lib/minicron/hub/assets/app/routes/schedules.js +37 -0
- data/lib/minicron/hub/assets/css/bootswatch.min.css +9 -0
- data/lib/minicron/hub/assets/css/main.scss +323 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/minicron/hub/assets/fonts/lato-bold-700.woff +0 -0
- data/lib/minicron/hub/assets/fonts/lato-italic-400.woff +0 -0
- data/lib/minicron/hub/assets/fonts/lato-regular-400.woff +0 -0
- data/lib/minicron/hub/assets/js/ansi_up-1.1.1.min.js +6 -0
- data/lib/minicron/hub/assets/js/auth/ember-auth-9.0.7.min.js +2 -0
- data/lib/minicron/hub/assets/js/auth/ember-auth-request-jquery-1.0.3.min.js +1 -0
- data/lib/minicron/hub/assets/js/bootstrap-3.1.1.min.js +6 -0
- data/lib/minicron/hub/assets/js/ember-1.4.1.min.js +18 -0
- data/lib/minicron/hub/assets/js/ember-data-1.0.0-beta.7.f87cba88.min.js +10 -0
- data/lib/minicron/hub/assets/js/faye-browser-1.0.1.min.js +2 -0
- data/lib/minicron/hub/assets/js/handlebars-1.3.0.min.js +29 -0
- data/lib/minicron/hub/assets/js/jquery-2.1.0.min.js +4 -0
- data/lib/minicron/hub/assets/js/moment-2.5.1.min.js +7 -0
- data/lib/minicron/hub/controllers/api/executions.rb +34 -0
- data/lib/minicron/hub/controllers/api/hosts.rb +150 -0
- data/lib/minicron/hub/controllers/api/job_execution_outputs.rb +30 -0
- data/lib/minicron/hub/controllers/api/jobs.rb +118 -0
- data/lib/minicron/hub/controllers/api/schedule.rb +184 -0
- data/lib/minicron/hub/controllers/index.rb +5 -0
- data/lib/minicron/hub/db/schema.rb +98 -0
- data/lib/minicron/hub/db/schema.sql +158 -0
- data/lib/minicron/hub/models/alert.rb +7 -0
- data/lib/minicron/hub/models/execution.rb +8 -0
- data/lib/minicron/hub/models/host.rb +7 -0
- data/lib/minicron/hub/models/job.rb +18 -0
- data/lib/minicron/hub/models/job_execution_output.rb +7 -0
- data/lib/minicron/hub/models/schedule.rb +25 -0
- data/lib/minicron/hub/serializers/execution.rb +75 -0
- data/lib/minicron/hub/serializers/host.rb +57 -0
- data/lib/minicron/hub/serializers/job.rb +104 -0
- data/lib/minicron/hub/serializers/job_execution_output.rb +48 -0
- data/lib/minicron/hub/serializers/schedule.rb +68 -0
- data/lib/minicron/hub/views/handlebars/application.erb +51 -0
- data/lib/minicron/hub/views/handlebars/errors.erb +29 -0
- data/lib/minicron/hub/views/handlebars/executions.erb +79 -0
- data/lib/minicron/hub/views/handlebars/hosts.erb +205 -0
- data/lib/minicron/hub/views/handlebars/jobs.erb +203 -0
- data/lib/minicron/hub/views/handlebars/loading.erb +3 -0
- data/lib/minicron/hub/views/handlebars/schedules.erb +354 -0
- data/lib/minicron/hub/views/index.erb +7 -0
- data/lib/minicron/hub/views/layouts/app.erb +15 -0
- data/lib/minicron/monitor.rb +116 -0
- data/lib/minicron/transport.rb +15 -0
- data/lib/minicron/transport/client.rb +80 -0
- data/lib/minicron/transport/faye/client.rb +103 -0
- data/lib/minicron/transport/faye/extensions/job_handler.rb +184 -0
- data/lib/minicron/transport/faye/server.rb +58 -0
- data/lib/minicron/transport/server.rb +62 -0
- data/lib/minicron/transport/ssh.rb +51 -0
- data/spec/invalid_config.toml +2 -0
- data/spec/minicron/cli_spec.rb +154 -0
- data/spec/minicron/transport/client_spec.rb +8 -0
- data/spec/minicron/transport/faye/client_spec.rb +53 -0
- data/spec/minicron/transport/server_spec.rb +70 -0
- data/spec/minicron/transport_spec.rb +13 -0
- data/spec/minicron_spec.rb +133 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/valid_config.toml +48 -0
- metadata +577 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Minicron
|
5
|
+
# The transport module deals with interactions between the server and client
|
6
|
+
module Transport
|
7
|
+
# Calculate the job hash based on the command and host
|
8
|
+
#
|
9
|
+
# @param command [String] the job command e.g 'ls -la'
|
10
|
+
# @param fqdn [String] the fqdn of the server running the job e.g `db1.example.com`
|
11
|
+
def self.get_job_hash(command, fqdn)
|
12
|
+
Digest::MD5.hexdigest(command + fqdn)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'minicron/transport/faye/client'
|
2
|
+
|
3
|
+
module Minicron
|
4
|
+
module Transport
|
5
|
+
class Client < Minicron::Transport::FayeClient
|
6
|
+
# Instantiate a new instance of the client
|
7
|
+
#
|
8
|
+
# @param host [String] The host to be communicated with
|
9
|
+
def initialize(scheme, host, port, path)
|
10
|
+
@scheme = scheme
|
11
|
+
@host = host
|
12
|
+
@path = path == '/' ? '/faye' : "#{path}/faye"
|
13
|
+
@port = port
|
14
|
+
@seq = 1
|
15
|
+
super(@scheme, @host, @port, @path)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Used to set up a job on the server
|
19
|
+
#
|
20
|
+
# @param job_hash [String]
|
21
|
+
# @param command [Integer]
|
22
|
+
# @param fqdn [String]
|
23
|
+
# @param hostname [String]
|
24
|
+
# @return [Hash]
|
25
|
+
def setup(job_hash, command, fqdn, hostname)
|
26
|
+
# Send a request to set up the job
|
27
|
+
publish("/job/#{job_hash}/status", {
|
28
|
+
:action => 'SETUP',
|
29
|
+
:command => command,
|
30
|
+
:fqdn => fqdn,
|
31
|
+
:hostname => hostname
|
32
|
+
})
|
33
|
+
|
34
|
+
# Wait for the response..
|
35
|
+
ensure_delivery
|
36
|
+
|
37
|
+
# TODO: Handle errors here!
|
38
|
+
# Get the job and execution id from the response
|
39
|
+
ids = JSON.parse(responses.first[:body]).first['channel'].split('/')[3]
|
40
|
+
|
41
|
+
# Split them up
|
42
|
+
ids = ids.split('-')
|
43
|
+
|
44
|
+
# Return them as a hash
|
45
|
+
{
|
46
|
+
:job_id => ids[0],
|
47
|
+
:execution_id => ids[1]
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Helper that wraps the publish function making it quicker to use
|
52
|
+
#
|
53
|
+
# @option options [String] job_id
|
54
|
+
# @option options [String, Symbol] type status or output
|
55
|
+
# @option options [Integer] execution_id
|
56
|
+
def send(options = {})
|
57
|
+
# Publish the message to the correct channel
|
58
|
+
publish("/job/#{options[:job_id]}/#{options[:execution_id]}/#{options[:type]}", options[:message])
|
59
|
+
end
|
60
|
+
|
61
|
+
# Publishes a message on the given channel to the server
|
62
|
+
#
|
63
|
+
# @param channel [String]
|
64
|
+
# @param message [String]
|
65
|
+
def publish(channel, message)
|
66
|
+
# Set up the data to send to faye
|
67
|
+
data = {:channel => channel, :data => {
|
68
|
+
:ts => Time.now.utc.strftime("%Y-%m-%d %H:%M:%S"),
|
69
|
+
:message => message,
|
70
|
+
:seq => @seq
|
71
|
+
}}
|
72
|
+
|
73
|
+
# Increment the sequence id
|
74
|
+
@seq += 1
|
75
|
+
|
76
|
+
request({ :message => data.to_json })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'em-http-request'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module Minicron
|
6
|
+
module Transport
|
7
|
+
class FayeClient
|
8
|
+
attr_accessor :url
|
9
|
+
attr_accessor :queue
|
10
|
+
attr_accessor :responses
|
11
|
+
|
12
|
+
# Instantiate a new instance of the client
|
13
|
+
#
|
14
|
+
# @param scheme [String] http or https
|
15
|
+
# @param host [String] The host to be communicated with
|
16
|
+
# @param port [String] The port number the server runs on
|
17
|
+
# @param path [String] The path to the server, optional
|
18
|
+
def initialize(scheme, host, port, path) # TODO: Add options hash for other options
|
19
|
+
@scheme = scheme
|
20
|
+
@host = host
|
21
|
+
@path = path
|
22
|
+
@port = port
|
23
|
+
@url = "#{scheme}://#{host}:#{port}#{path}"
|
24
|
+
@queue = {}
|
25
|
+
@responses = []
|
26
|
+
@retries = 3
|
27
|
+
@retry_counts = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Starts EventMachine in a new thread if it isn't already running
|
31
|
+
def ensure_em_running
|
32
|
+
Thread.new { EM.run } unless EM.reactor_running?
|
33
|
+
sleep 0.1 until EM.reactor_running?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sends a request to the @url and adds it to the request queue
|
37
|
+
#
|
38
|
+
# @param body [String]
|
39
|
+
def request(body)
|
40
|
+
# Make sure eventmachine is running
|
41
|
+
ensure_em_running
|
42
|
+
|
43
|
+
# Make the request
|
44
|
+
req = EventMachine::HttpRequest.new(
|
45
|
+
@url,
|
46
|
+
:connect_timeout => Minicron.config['client']['connect_timeout'],
|
47
|
+
:inactivity_timeout => Minicron.config['client']['inactivity_timeout']
|
48
|
+
).post(:body => body)
|
49
|
+
|
50
|
+
# Generate an id for the request
|
51
|
+
req_id = Digest::MD5.hexdigest(body.to_s)
|
52
|
+
|
53
|
+
# Put the request in the queue
|
54
|
+
queue[req_id] = req
|
55
|
+
|
56
|
+
# Set up the retry count for this request if it didn't already exist
|
57
|
+
@retry_counts[req_id] ||= 0
|
58
|
+
|
59
|
+
# Did the request succeed? If so remove it from the queue
|
60
|
+
req.callback do
|
61
|
+
@responses.push({
|
62
|
+
:status => req.response_header.status,
|
63
|
+
:header => req.response_header,
|
64
|
+
:body => req.response
|
65
|
+
})
|
66
|
+
|
67
|
+
queue.delete(req_id)
|
68
|
+
end
|
69
|
+
|
70
|
+
# If not retry the request up to @retries times
|
71
|
+
req.errback do |error|
|
72
|
+
@responses.push({
|
73
|
+
:status => req.response_header.status,
|
74
|
+
:header => req.response_header,
|
75
|
+
:body => req.response
|
76
|
+
})
|
77
|
+
|
78
|
+
if @retry_counts[req_id] < @retries
|
79
|
+
@retry_counts[req_id] += 1
|
80
|
+
request(body)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Blocks until all messages in the sending queue have completed
|
86
|
+
def ensure_delivery
|
87
|
+
# Keep waiting until the queue is empty but only if we need to
|
88
|
+
if queue.length > 0
|
89
|
+
until queue.length == 0
|
90
|
+
sleep 0.05
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
# Tidy up after we are done with the client
|
98
|
+
def tidy_up
|
99
|
+
EM.stop
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'minicron/alert'
|
2
|
+
require 'minicron/hub/models/host'
|
3
|
+
require 'minicron/hub/models/job'
|
4
|
+
require 'minicron/hub/models/execution'
|
5
|
+
require 'minicron/hub/models/job_execution_output'
|
6
|
+
|
7
|
+
module Minicron
|
8
|
+
module Transport
|
9
|
+
# An extension to the Faye server to store some of the data it receives
|
10
|
+
#
|
11
|
+
# TODO: A lot of this need more validation checks and error handling
|
12
|
+
# currently it's just assumed the correct data is passed and the server
|
13
|
+
# can crash if it isn't
|
14
|
+
class FayeJobHandler
|
15
|
+
# Called by Faye when a message is recieved
|
16
|
+
#
|
17
|
+
# @param message [Hash] The message data
|
18
|
+
# @param request the rack request object
|
19
|
+
# @param callback
|
20
|
+
def incoming(message, request, callback)
|
21
|
+
segments = message['channel'].split('/')
|
22
|
+
|
23
|
+
# Is it a job messages
|
24
|
+
if segments[1] == 'job'
|
25
|
+
data = message['data']['message']
|
26
|
+
|
27
|
+
# Is it a setup message?
|
28
|
+
if segments[3] == 'status' && data['action'] == 'SETUP'
|
29
|
+
message = handle_setup(request, message, segments)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Is it a start message?
|
33
|
+
if segments[4] == 'status' && data[0..4] == 'START'
|
34
|
+
handle_start(request, message, segments)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Is it job output?
|
38
|
+
if segments[4] == 'output'
|
39
|
+
message = handle_output(request, message, segments)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Is it a finish message?
|
43
|
+
if segments[4] == 'status' && data[0..5] == 'FINISH'
|
44
|
+
handle_finish(request, message, segments)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Is it an exit message?
|
48
|
+
if segments[4] == 'status' && data[0..3] == 'EXIT'
|
49
|
+
handle_exit(request, message, segments)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the message back to faye
|
54
|
+
callback.call(message)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Handle SETUP messages
|
58
|
+
#
|
59
|
+
# @param request the rack request object
|
60
|
+
# @param message [Hash] the decoded message sent with the request
|
61
|
+
# @param segments [Hash] the message channel split by /
|
62
|
+
def handle_setup(request, message, segments)
|
63
|
+
data = message['data']['message']
|
64
|
+
|
65
|
+
# Try and find the host
|
66
|
+
host = Minicron::Hub::Host.where(:fqdn => data['fqdn']).first
|
67
|
+
|
68
|
+
# Create it if it didn't exist!
|
69
|
+
if not host
|
70
|
+
host = Minicron::Hub::Host.create(
|
71
|
+
:name => data['hostname'],
|
72
|
+
:fqdn => data['fqdn'],
|
73
|
+
:host => request.ip
|
74
|
+
)
|
75
|
+
|
76
|
+
# Generate a new SSH key - TODO: add passphrase
|
77
|
+
key = Minicron.generate_ssh_key('host', host.id, host.fqdn)
|
78
|
+
|
79
|
+
# And finally we store the public key in te db with the host for convenience
|
80
|
+
Minicron::Hub::Host.where(:id => host.id).update_all(
|
81
|
+
:public_key => key.ssh_public_key
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Validate or create the job
|
86
|
+
job = Minicron::Hub::Job.where(:job_hash => segments[2]).first_or_create do |j|
|
87
|
+
j.job_hash = segments[2]
|
88
|
+
j.command = data['command']
|
89
|
+
j.host_id = host.id
|
90
|
+
end
|
91
|
+
|
92
|
+
# Create an execution for this job
|
93
|
+
execution = Minicron::Hub::Execution.create(
|
94
|
+
:job_id => job.id
|
95
|
+
)
|
96
|
+
|
97
|
+
# Alter the response channel to include the execution id for the
|
98
|
+
# client to use in later requests
|
99
|
+
segments[3] = "#{job.id}-#{execution.id}/status"
|
100
|
+
message['channel'] = segments.join('/')
|
101
|
+
|
102
|
+
# And finally return the message
|
103
|
+
message
|
104
|
+
end
|
105
|
+
|
106
|
+
# Handle START messages
|
107
|
+
#
|
108
|
+
# @param request the rack request object
|
109
|
+
# @param message [Hash] the decoded message sent with the request
|
110
|
+
# @param segments [Hash] the message channel split by /
|
111
|
+
def handle_start(request, message, segments)
|
112
|
+
data = message['data']['message']
|
113
|
+
|
114
|
+
# Update the execution and add the start time
|
115
|
+
Minicron::Hub::Execution.where(:id => segments[3]).update_all(
|
116
|
+
:started_at => data[6..-1]
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Handle job output
|
121
|
+
#
|
122
|
+
# @param request the rack request object
|
123
|
+
# @param message [Hash] the decoded message sent with the request
|
124
|
+
# @param segments [Hash] the message channel split by /
|
125
|
+
def handle_output(request, message, segments)
|
126
|
+
data = message['data']['message']
|
127
|
+
ts = message['data']['ts']
|
128
|
+
seq = message['data']['seq']
|
129
|
+
|
130
|
+
# Store the job execution output
|
131
|
+
output = Minicron::Hub::JobExecutionOutput.create(
|
132
|
+
:execution_id => segments[3],
|
133
|
+
:output => data,
|
134
|
+
:timestamp => ts,
|
135
|
+
:seq => seq
|
136
|
+
)
|
137
|
+
|
138
|
+
# Append the id to the message so we can use it on the frontend
|
139
|
+
message['data']['job_execution_output_id'] = output.id
|
140
|
+
|
141
|
+
# And finally return the message
|
142
|
+
message
|
143
|
+
end
|
144
|
+
|
145
|
+
# Handle FINISH messages
|
146
|
+
#
|
147
|
+
# @param request the rack request object
|
148
|
+
# @param message [Hash] the decoded message sent with the request
|
149
|
+
# @param segments [Hash] the message channel split by /
|
150
|
+
def handle_finish(request, message, segments)
|
151
|
+
data = message['data']['message']
|
152
|
+
|
153
|
+
# Update the execution and add the finish time
|
154
|
+
Minicron::Hub::Execution.where(:id => segments[3]).update_all(
|
155
|
+
:finished_at => data[7..-1]
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Handle EXIT messages
|
160
|
+
#
|
161
|
+
# @param request the rack request object
|
162
|
+
# @param message [Hash] the decoded message sent with the request
|
163
|
+
# @param segments [Hash] the message channel split by /
|
164
|
+
def handle_exit(request, message, segments)
|
165
|
+
data = message['data']['message']
|
166
|
+
|
167
|
+
# Update the execution and add the exit status
|
168
|
+
Minicron::Hub::Execution.where(:id => segments[3]).update_all(
|
169
|
+
:exit_status => data[5..-1]
|
170
|
+
)
|
171
|
+
|
172
|
+
# If the exit status was above 0 we need to trigger a failure alert
|
173
|
+
if data[5..-1].to_i > 0
|
174
|
+
alert = Minicron::Alert.new
|
175
|
+
alert.send_all(
|
176
|
+
:kind => 'fail',
|
177
|
+
:execution_id => segments[3],
|
178
|
+
:job_id => segments[2]
|
179
|
+
)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'rack'
|
3
|
+
require 'faye'
|
4
|
+
require 'minicron/transport/faye/extensions/job_handler'
|
5
|
+
|
6
|
+
module Minicron
|
7
|
+
module Transport
|
8
|
+
class FayeServer
|
9
|
+
attr_reader :server
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
# Load the Faye thin adapter, this needs to happen first
|
13
|
+
Faye::WebSocket.load_adapter('thin')
|
14
|
+
|
15
|
+
# Show debug verbose output if requested
|
16
|
+
if Minicron.config['global']['verbose']
|
17
|
+
log = Logger.new(STDOUT)
|
18
|
+
log.level = Logger::DEBUG
|
19
|
+
Faye.logger = log
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set up our Faye rack app
|
23
|
+
@server = Faye::RackAdapter.new(
|
24
|
+
:mount => '', # This is relative to the map faye_path set in server.rb
|
25
|
+
:timeout => 25
|
26
|
+
)
|
27
|
+
|
28
|
+
@server.add_extension(Minicron::Transport::FayeJobHandler.new)
|
29
|
+
|
30
|
+
# Add all the events we want to listen out for
|
31
|
+
add_faye_events
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def add_faye_events
|
36
|
+
@server.on(:handshake) do |client_id|
|
37
|
+
p [:handshake, client_id] if Minicron.config['global']['verbose']
|
38
|
+
end
|
39
|
+
|
40
|
+
@server.on(:subscribe) do |client_id, channel|
|
41
|
+
p [:subscribe, client_id, channel] if Minicron.config['global']['verbose']
|
42
|
+
end
|
43
|
+
|
44
|
+
@server.on(:unsubscribe) do |client_id, channel|
|
45
|
+
p [:unsubscribe, client_id, channel] if Minicron.config['global']['verbose']
|
46
|
+
end
|
47
|
+
|
48
|
+
@server.on(:publish) do |client_id, channel, data|
|
49
|
+
p [:published, client_id, channel, data] if Minicron.config['global']['verbose']
|
50
|
+
end
|
51
|
+
|
52
|
+
@server.on(:disconnect) do |client_id|
|
53
|
+
p [:disconnect, client_id] if Minicron.config['global']['verbose']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module Minicron
|
5
|
+
module Transport
|
6
|
+
# Used to mangage the web server minicron runs on
|
7
|
+
class Server
|
8
|
+
attr_reader :server
|
9
|
+
|
10
|
+
# Starts the thin server
|
11
|
+
#
|
12
|
+
# @param host [String] the host e.g 0.0.0.0
|
13
|
+
# @param port [Integer]
|
14
|
+
# @param path [String] The absolute path to the server e.g /server
|
15
|
+
def start!(host, port, path)
|
16
|
+
return false if running?
|
17
|
+
|
18
|
+
# Start the faye or rails apps depending on the path
|
19
|
+
server = Thin::Server.new(host, port) do
|
20
|
+
use Rack::CommonLogger
|
21
|
+
use Rack::ShowExceptions
|
22
|
+
|
23
|
+
# The 'hub', aka our sinatra web interface
|
24
|
+
map '/' do
|
25
|
+
require Minicron::LIB_PATH + '/minicron/hub/app'
|
26
|
+
use Minicron::Hub::ExceptionHandling
|
27
|
+
run Minicron::Hub::App.new
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the path faye should start relative to
|
31
|
+
faye_path = path == '/' ? '/faye' : "#{path}/faye"
|
32
|
+
|
33
|
+
# The faye server the server and browser clients talk to
|
34
|
+
map faye_path do
|
35
|
+
require Minicron::LIB_PATH + '/minicron/transport/faye/server'
|
36
|
+
run Minicron::Transport::FayeServer.new.server
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
server.start
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
# Stops the thin server if it's running
|
45
|
+
# @return [Boolean] whether the server was stopped or not
|
46
|
+
def stop!
|
47
|
+
return false unless running? && server != nil
|
48
|
+
|
49
|
+
server.stop
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a bool based on whether
|
54
|
+
# @return [Boolean]
|
55
|
+
def running?
|
56
|
+
return false unless server != nil
|
57
|
+
|
58
|
+
server.running?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|