ngauthier-active-listener 0.3.0 → 0.3.2
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.
- data/VERSION.yml +2 -2
- data/lib/active-listener.rb +107 -11
- data/test/active_listener-events.yml +5 -0
- data/test/active_listener_test.rb +58 -4
- metadata +3 -3
data/VERSION.yml
CHANGED
data/lib/active-listener.rb
CHANGED
@@ -1,9 +1,23 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'yaml'
|
3
3
|
|
4
|
+
# =ActiveListener
|
5
|
+
# Set up an activelistener config file in your config directory describing the
|
6
|
+
# tasks #ActiveListener should execute. Then, in an initializer, run
|
7
|
+
# #ActiveListener.autostart
|
4
8
|
class ActiveListener
|
9
|
+
# All the #Events that an #ActiveListener is firing
|
5
10
|
attr_reader :events
|
6
11
|
|
12
|
+
# Run #autostart in an initializer to run #ActiveListener when your
|
13
|
+
# Rails application initializes.
|
14
|
+
#
|
15
|
+
# ActiveListener.autostart(
|
16
|
+
# :config => File.join(RAILS_ROOT, 'config', 'active-listener.yml'),
|
17
|
+
# :pid_file => File.join(RAILS_ROOT, 'log', 'active-listener-'+RAILS_ENV+'.pid'),
|
18
|
+
# :log_file => File.join(RAILS_ROOT, 'log', 'active-listener-'+RAILS_ENV+'.log'),
|
19
|
+
# :rake_root => RAILS_ROOT
|
20
|
+
# )
|
7
21
|
def self.autostart(opts = {})
|
8
22
|
begin
|
9
23
|
config_file = File.expand_path(opts[:config])
|
@@ -22,30 +36,47 @@ class ActiveListener
|
|
22
36
|
"--",
|
23
37
|
"#{config_file}",
|
24
38
|
"#{log_file}",
|
25
|
-
"#{rake_root}"
|
39
|
+
"#{rake_root}",
|
26
40
|
].join(" ")
|
27
41
|
`#{command}`
|
28
42
|
end
|
29
43
|
|
44
|
+
# Stop an #ActiveListener by specifying a pid file
|
45
|
+
#
|
46
|
+
# ActiveListener.stop(:pid_file => File.join(RAILS_ROOT, 'log', 'active-listener.pid'))
|
30
47
|
def self.stop(opts = {})
|
31
48
|
pid_file = opts[:pid_file]
|
32
49
|
`start-stop-daemon --stop --oknodo --pidfile #{File.expand_path(pid_file)}`
|
33
50
|
end
|
34
51
|
|
52
|
+
# Create an #ActiveListener in the foreground. This is useful for a non-rails project.
|
53
|
+
#
|
54
|
+
# ActiveListener.new(
|
55
|
+
# :log_file => File.join('log', 'active-listener.log'),
|
56
|
+
# :rake_root => '.'
|
57
|
+
# )
|
35
58
|
def initialize(opts = {})
|
36
59
|
self.events = []
|
37
60
|
self.log_file = opts[:log_file]
|
38
61
|
self.rake_root = opts[:rake_root]
|
39
62
|
clear_log
|
40
63
|
log("ActiveListener Initialized")
|
41
|
-
|
64
|
+
load_config(opts[:config])
|
42
65
|
end
|
43
66
|
|
67
|
+
# Add an event to event listener.
|
68
|
+
#
|
69
|
+
# @al.add_event(Event.new(:task => 'my_task', :period => '10'))
|
44
70
|
def add_event(evt)
|
45
71
|
self.events.push(evt)
|
46
72
|
log("Added Event #{evt.inspect}")
|
47
73
|
end
|
48
74
|
|
75
|
+
# Fire any events that have passed their period
|
76
|
+
#
|
77
|
+
# @al.fire_events
|
78
|
+
#
|
79
|
+
# This will only fire events that have not been run within their period time of their last run
|
49
80
|
def fire_events
|
50
81
|
self.events.select{|e| e.time_to_fire < 0}.each do |evt|
|
51
82
|
log("Firing event: #{evt.inspect}")
|
@@ -54,6 +85,10 @@ class ActiveListener
|
|
54
85
|
self.events.sort{|x,y| x.time_to_fire <=> y.time_to_fire}
|
55
86
|
end
|
56
87
|
|
88
|
+
# Returns the time in seconds until the next event needs to be fired. Useful for sleeping
|
89
|
+
#
|
90
|
+
# sleep(@al.time_to_next_event)
|
91
|
+
# @al.fire_events
|
57
92
|
def time_to_next_event
|
58
93
|
if self.events.first
|
59
94
|
sleep_time = self.events.first.time_to_fire+0.01
|
@@ -63,22 +98,37 @@ class ActiveListener
|
|
63
98
|
return sleep_time
|
64
99
|
end
|
65
100
|
|
66
|
-
|
67
|
-
|
68
|
-
|
101
|
+
# Not functional yet.
|
102
|
+
def self.trigger(port, event)
|
103
|
+
|
69
104
|
end
|
70
105
|
|
106
|
+
# An individual #ActiveListener #Event
|
71
107
|
class Event
|
108
|
+
# Create a new #Event
|
109
|
+
#
|
110
|
+
# Event.new(
|
111
|
+
# :task => 'my:rake:task',
|
112
|
+
# :period => 50
|
113
|
+
# )
|
72
114
|
def initialize(opts = {})
|
73
115
|
self.task = opts[:task] || opts["task"]
|
74
116
|
self.period = opts[:period] || opts["period"]
|
117
|
+
self.trigger = opts[:trigger] || opts["trigger"]
|
75
118
|
self.last_fire = Time.now.to_f
|
76
119
|
end
|
77
120
|
|
121
|
+
# The amount of time until this event will need to be fired
|
78
122
|
def time_to_fire
|
79
|
-
|
123
|
+
if period
|
124
|
+
return last_fire + period - Time.now.to_f
|
125
|
+
else
|
126
|
+
# oh does! forever!
|
127
|
+
return 1.0/0.0
|
128
|
+
end
|
80
129
|
end
|
81
130
|
|
131
|
+
# Fire the event. I.e. run the rake task
|
82
132
|
def fire(opts = {})
|
83
133
|
self.last_fire = Time.now.to_f
|
84
134
|
Dir.chdir(opts[:rake_root]) if opts[:rake_root]
|
@@ -89,18 +139,43 @@ class ActiveListener
|
|
89
139
|
end
|
90
140
|
end
|
91
141
|
|
142
|
+
# Manual firing trigger (not implemented)
|
143
|
+
attr_reader :trigger
|
144
|
+
# The amount of time in seconds between firing this task
|
145
|
+
attr_reader :period
|
146
|
+
# The last time this event was fired
|
147
|
+
attr_reader :last_fire
|
148
|
+
# A string representation of a rake task. "my:task"
|
149
|
+
attr_reader :task
|
150
|
+
|
92
151
|
private
|
93
152
|
|
94
|
-
|
153
|
+
# Set the rake task
|
154
|
+
attr_writer :task
|
155
|
+
# Set the period
|
156
|
+
attr_writer :period
|
157
|
+
# Set the trigger
|
158
|
+
attr_writer :trigger
|
159
|
+
# Set last_fire time
|
160
|
+
attr_writer :last_fire
|
95
161
|
|
96
162
|
end
|
97
163
|
|
98
164
|
private
|
99
165
|
|
166
|
+
# Set the events this #ActiveListener has
|
100
167
|
attr_writer :events
|
101
|
-
|
102
|
-
|
103
|
-
|
168
|
+
# Log file path
|
169
|
+
attr_accessor :log_file
|
170
|
+
# Directory to run rake tasks from
|
171
|
+
attr_accessor :rake_root
|
172
|
+
# Port for triggers (not implemented)
|
173
|
+
attr_accessor :port
|
174
|
+
|
175
|
+
# Parse a config file to load up events.
|
176
|
+
#
|
177
|
+
# @al.load_config('active-listener.yml')
|
178
|
+
def load_config(config_file)
|
104
179
|
return if config_file.nil?
|
105
180
|
unless File.exists?(config_file)
|
106
181
|
log("Config file not found at #{config_file}")
|
@@ -112,13 +187,21 @@ class ActiveListener
|
|
112
187
|
yml["tasks"].each do |task|
|
113
188
|
self.add_event(Event.new(task))
|
114
189
|
end
|
190
|
+
port = yml["port"]
|
191
|
+
# puts "The port: #{port}"
|
192
|
+
if port
|
193
|
+
self.port = port
|
194
|
+
spawn_listener_thread
|
195
|
+
end
|
115
196
|
end
|
116
197
|
|
198
|
+
# Delete the log file
|
117
199
|
def clear_log
|
118
200
|
return unless log_file
|
119
201
|
FileUtils.rm_f log_file
|
120
202
|
end
|
121
|
-
|
203
|
+
|
204
|
+
# Log text to the log file
|
122
205
|
def log(text)
|
123
206
|
return unless log_file
|
124
207
|
f = File.new(log_file, 'a')
|
@@ -127,4 +210,17 @@ class ActiveListener
|
|
127
210
|
f.close
|
128
211
|
end
|
129
212
|
|
213
|
+
# Trigger an event (not implemented)
|
214
|
+
def trigger(trigger)
|
215
|
+
self.events.select{|e| e.trigger == trigger}.each do |evt|
|
216
|
+
log("Event triggered: #{evt.inspect}")
|
217
|
+
log(evt.fire(:rake_root => rake_root))
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Listen on a port for triggers (not implemented)
|
222
|
+
def spawn_listener_thread
|
223
|
+
# puts "Hey a port! #{port}"
|
224
|
+
end
|
225
|
+
|
130
226
|
end
|
@@ -23,7 +23,7 @@ class ActiveListenerTest < Test::Unit::TestCase
|
|
23
23
|
end
|
24
24
|
|
25
25
|
should "sleep when it has no events" do
|
26
|
-
@al.
|
26
|
+
sleep(@al.time_to_next_event)
|
27
27
|
end
|
28
28
|
|
29
29
|
context "with a file timer" do
|
@@ -44,7 +44,7 @@ class ActiveListenerTest < Test::Unit::TestCase
|
|
44
44
|
|
45
45
|
should "touch a file" do
|
46
46
|
assert !File.exists?(@sample_file)
|
47
|
-
@al.
|
47
|
+
sleep(@al.time_to_next_event)
|
48
48
|
@al.fire_events
|
49
49
|
assert File.exists?(@sample_file)
|
50
50
|
end
|
@@ -59,7 +59,7 @@ class ActiveListenerTest < Test::Unit::TestCase
|
|
59
59
|
FileUtils.rm_f(@sample_file)
|
60
60
|
@al.fire_events
|
61
61
|
assert !File.exists?(@sample_file)
|
62
|
-
@al.
|
62
|
+
sleep(@al.time_to_next_event)
|
63
63
|
assert @al.events[0].time_to_fire < 0
|
64
64
|
assert !File.exists?(@sample_file)
|
65
65
|
@al.fire_events
|
@@ -81,7 +81,7 @@ class ActiveListenerTest < Test::Unit::TestCase
|
|
81
81
|
@al = ActiveListener.new(:config => @config_path)
|
82
82
|
assert @al.events.size > 0
|
83
83
|
assert !File.exists?(@sample_file)
|
84
|
-
@al.
|
84
|
+
sleep(@al.time_to_next_event)
|
85
85
|
@al.fire_events
|
86
86
|
assert File.exists?(@sample_file)
|
87
87
|
end
|
@@ -160,6 +160,60 @@ class ActiveListenerTest < Test::Unit::TestCase
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
+
context "An event-based listener" do
|
164
|
+
|
165
|
+
setup do
|
166
|
+
@al = ActiveListener.new({})
|
167
|
+
@al.add_event(ActiveListener::Event.new(
|
168
|
+
:task => 'test:touch_file',
|
169
|
+
:trigger => "MY_TRIGGER"
|
170
|
+
))
|
171
|
+
@sample_file = File.join(File.dirname(__FILE__),'sample.txt')
|
172
|
+
FileUtils.rm_f @sample_file
|
173
|
+
end
|
174
|
+
|
175
|
+
teardown do
|
176
|
+
FileUtils.rm_f @sample_file
|
177
|
+
end
|
178
|
+
|
179
|
+
should "not fire any events at the beginning" do
|
180
|
+
assert !File.exists?(@sample_file)
|
181
|
+
assert @al.time_to_next_event.infinite?
|
182
|
+
@al.fire_events
|
183
|
+
assert !File.exists?(@sample_file)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "An auto-started event based listener" do
|
188
|
+
setup do
|
189
|
+
ActiveListener.stop(
|
190
|
+
:pid_file => File.join(File.dirname(__FILE__), 'active_listener.pid')
|
191
|
+
)
|
192
|
+
sleep(0.5)
|
193
|
+
ActiveListener.autostart(
|
194
|
+
:config => File.join(File.dirname(__FILE__), 'active_listener-events.yml'),
|
195
|
+
:pid_file => File.join(File.dirname(__FILE__), 'active_listener.pid'),
|
196
|
+
:log_file => File.join(File.dirname(__FILE__), 'active_listener.log'),
|
197
|
+
:rake_root => File.join(File.dirname(__FILE__), '..')
|
198
|
+
)
|
199
|
+
@sample_file = File.join(File.dirname(__FILE__),'sample.txt')
|
200
|
+
end
|
201
|
+
|
202
|
+
teardown do
|
203
|
+
ActiveListener.stop(
|
204
|
+
:pid_file => File.join(File.dirname(__FILE__), 'active_listener.pid')
|
205
|
+
)
|
206
|
+
sleep(1)
|
207
|
+
FileUtils.rm_f(File.join(File.dirname(__FILE__),'sample.txt'))
|
208
|
+
end
|
209
|
+
|
210
|
+
should "be able to be triggered" do
|
211
|
+
#assert !File.exists?(@sample_file)
|
212
|
+
#ActiveListener.trigger(20150,"MY_TRIGGER")
|
213
|
+
#assert File.exists?(@sample_file)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
163
217
|
private
|
164
218
|
|
165
219
|
def pid_running(pid)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ngauthier-active-listener
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Gauthier
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-12 00:00:00 -08:00
|
13
13
|
default_executable: active-listener
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,12 +23,12 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- VERSION.yml
|
26
|
-
- README.html
|
27
26
|
- README.markdown
|
28
27
|
- bin/active-listener
|
29
28
|
- lib/activelistener
|
30
29
|
- lib/active-listener.rb
|
31
30
|
- test/test_helper.rb
|
31
|
+
- test/active_listener-events.yml
|
32
32
|
- test/active_listener.log
|
33
33
|
- test/active_listener.pid
|
34
34
|
- test/active_listener.yml
|