updater 0.9.3.2 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/updater/fork_worker.rb +2 -1
- data/lib/updater/orm/mongo.rb +21 -12
- data/lib/updater/setup.rb +42 -15
- data/lib/updater/update.rb +44 -5
- data/lib/updater.rb +2 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/update_spec.rb +1 -1
- metadata +3 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.4
|
data/lib/updater/fork_worker.rb
CHANGED
@@ -73,6 +73,7 @@ module Updater
|
|
73
73
|
stop(false)
|
74
74
|
false
|
75
75
|
when :USR2, :DATA #wake up a child and get to work
|
76
|
+
logger.info {"Master Process recieved job ready signal"}
|
76
77
|
@pipe.last.write_nonblock('.')
|
77
78
|
true
|
78
79
|
when :TTIN
|
@@ -142,7 +143,7 @@ module Updater
|
|
142
143
|
timeout = calc_timeout
|
143
144
|
logger.debug { "Sleeping for #{timeout}" }
|
144
145
|
ready, _1, _2 = IO.select(@wakeup_set, nil, nil, timeout)
|
145
|
-
return unless ready && ready.first #timeout hit, just wakeup and run maintance
|
146
|
+
return unless ready && ready.first #timeout hit or self_pipe alerted, just wakeup and run maintance
|
146
147
|
add_connection(ready.first) and return if ready.first.respond_to?(:accept) #open a new incomming connection
|
147
148
|
@signal_queue << :DATA unless ready.first == @self_pipe.first
|
148
149
|
loop {ready.first.read_nonblock(16 * 1024)}
|
data/lib/updater/orm/mongo.rb
CHANGED
@@ -32,7 +32,7 @@ module Updater
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def _id=(val)
|
35
|
-
val = BSON::
|
35
|
+
val = BSON::ObjectId.from_string(val.to_s) unless val.kind_of? BSON::ObjectId
|
36
36
|
@hash[:_id] = val
|
37
37
|
end
|
38
38
|
|
@@ -59,7 +59,7 @@ module Updater
|
|
59
59
|
job
|
60
60
|
end
|
61
61
|
end
|
62
|
-
_id = self.class.collection.save
|
62
|
+
_id = self.class.collection.save(@hash, :safe=>true)
|
63
63
|
end
|
64
64
|
|
65
65
|
def destroy
|
@@ -106,10 +106,10 @@ module Updater
|
|
106
106
|
|
107
107
|
private
|
108
108
|
# this method is calld from he chain asignment methods eg. failure=(chain)
|
109
|
-
# chain is an array which may contain BSON::
|
110
|
-
# For BSON::
|
109
|
+
# chain is an array which may contain BSON::ObjectId's or Updater::Update's or both
|
110
|
+
# For BSON::ObjectId's we cannot initialize them as this could leed to infinate loops.
|
111
111
|
# (an object pool would solve this problem, but feels like overkill)
|
112
|
-
# The final result must be a @hash containing all the BSON::
|
112
|
+
# The final result must be a @hash containing all the BSON::ObjectId' (forign keys)
|
113
113
|
# and possibly @failure containting all instanciated UpdaterUpdates read to be called
|
114
114
|
# or @failure set to nil with the chain instanciated on first use.
|
115
115
|
def build_chain_arrays(arr, build = false)
|
@@ -131,20 +131,20 @@ module Updater
|
|
131
131
|
[nil,output[:ids]]
|
132
132
|
end
|
133
133
|
|
134
|
-
# This method takes something that may be a reference to an instance(BSON::
|
134
|
+
# This method takes something that may be a reference to an instance(BSON::ObjectId/String),
|
135
135
|
# an instance its self (Updater::Update), or a Hash
|
136
|
-
# and returns a touple of the Updater::Update,BSON::
|
137
|
-
# This method will bot instanciate object from BSON::
|
136
|
+
# and returns a touple of the Updater::Update,BSON::ObjectId.
|
137
|
+
# This method will bot instanciate object from BSON::ObjectId's
|
138
138
|
# nor will it save Hashes inorder to obtain an ID (it will creat a new Updater::Update from the hash).
|
139
139
|
# Instead it will return nil in the appropriate place.
|
140
140
|
def rationalize_instance(val)
|
141
|
-
val = BSON::
|
142
|
-
case val #aval is the actual runable object, hval is a BSON::
|
141
|
+
val = BSON::ObjectId.fron_string(val) if val.kind_of? String
|
142
|
+
case val #aval is the actual runable object, hval is a BSON::ObjectId that we can put into the Database
|
143
143
|
when Updater::Update
|
144
144
|
val.params ? [val,[val.id,val.params]] : [val,val.id]
|
145
145
|
when Hash
|
146
146
|
[Updater::Update.new(val),val['_id']]
|
147
|
-
when BSON::
|
147
|
+
when BSON::ObjectId
|
148
148
|
[nil,val]
|
149
149
|
when Array
|
150
150
|
rationalize_instance(val[0]).tap do |ret|
|
@@ -227,7 +227,7 @@ module Updater
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def get(id)
|
230
|
-
id = BSON::
|
230
|
+
id = BSON::ObjectId.from_string(id) if id.kind_of? String
|
231
231
|
new(@collection.find_one(id))
|
232
232
|
end
|
233
233
|
|
@@ -249,6 +249,7 @@ module Updater
|
|
249
249
|
|
250
250
|
def queue_time
|
251
251
|
nxt = @collection.find_one({:lock_name=>nil, :time=>{'$ne'=>nil}}, :sort=>[[:time, :asc]], :fields=>[:time])
|
252
|
+
# logger.debug {" the queue is empty"} unless nxt
|
252
253
|
return nil unless nxt
|
253
254
|
return 0 if nxt['time'] <= tnow
|
254
255
|
return nxt['time'] - tnow
|
@@ -267,6 +268,14 @@ module Updater
|
|
267
268
|
@collection.update({:lock_name=>worker.name},{'$unset'=>{:lock_name=>1}},:multi=>true)
|
268
269
|
end
|
269
270
|
|
271
|
+
def for(target,finder,args,name)
|
272
|
+
if name
|
273
|
+
@collection.find(:target=>target.to_s, :finder_args=>args,:name=>name)
|
274
|
+
else
|
275
|
+
@collection.find(:target=>target.to_s, :finder_args=>args)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
270
279
|
private
|
271
280
|
def tnow
|
272
281
|
Updater::Update.time.now.to_i
|
data/lib/updater/setup.rb
CHANGED
@@ -6,26 +6,33 @@ require 'erb'
|
|
6
6
|
module Updater
|
7
7
|
class Setup
|
8
8
|
class << self
|
9
|
+
#start a new server
|
9
10
|
def start(options={})
|
10
11
|
new(config_file(options), options).start
|
11
12
|
end
|
12
13
|
|
14
|
+
#stop the server
|
13
15
|
def stop(options={})
|
14
16
|
new(config_file(options), options).stop
|
15
17
|
end
|
16
18
|
|
19
|
+
# Used for testing. Will run through the entire setup process, but
|
20
|
+
# not actually start the server, but will log the resulting options.
|
17
21
|
def noop(options={})
|
18
22
|
new(config_file(options), options).noop
|
19
23
|
end
|
20
24
|
|
25
|
+
# Connect a client to a server
|
21
26
|
def client_setup(options = {})
|
22
27
|
new(config_file(options), options).client_setup
|
23
28
|
end
|
24
29
|
|
30
|
+
# pendeing
|
25
31
|
def monitor
|
26
32
|
|
27
33
|
end
|
28
|
-
|
34
|
+
|
35
|
+
# Retruns tha locaion of the config file.
|
29
36
|
def config_file(options = {})
|
30
37
|
if options[:config_file] && File.exists?(options[:config_file])
|
31
38
|
options[:config_file]
|
@@ -48,7 +55,7 @@ module Updater
|
|
48
55
|
@logger = @options[:logger] || Logger.new(@options[:log_file] || STDOUT)
|
49
56
|
level = Logger::SEV_LABEL.index(@options[:log_level].upcase) if @options[:log_level]
|
50
57
|
@logger.level = level || Logger::WARN unless @options[:logger] #only set this if we were not handed a logger
|
51
|
-
@logger.debug "Debugging output enabled"
|
58
|
+
@logger.debug "Debugging output enabled" unless @options[:logger]
|
52
59
|
Update.logger = @logger
|
53
60
|
end
|
54
61
|
|
@@ -80,25 +87,45 @@ module Updater
|
|
80
87
|
@logger.info "Updater Client is being initialized..."
|
81
88
|
set_orm
|
82
89
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
socket = UDPSocket.new()
|
88
|
-
socket.connect(@options[:host],@options[:udp])
|
89
|
-
Updater::Update.socket = socket
|
90
|
-
elsif @options[:tcp]
|
91
|
-
Updater::Update.socket = TCPSocket.new(@options[:host],@options[:tcp])
|
92
|
-
elsif @options[:remote]
|
93
|
-
raise NotImplimentedError #For future Authenticated Http Rest Server
|
94
|
-
end
|
90
|
+
Updater::Update.socket = socket_for_client
|
91
|
+
|
92
|
+
|
93
|
+
init_orm
|
95
94
|
|
96
95
|
#set PID
|
97
96
|
if File.exists? @options[:pid_file]
|
98
97
|
Updater::Update.pid = File.read(@options[:pid_file]).strip
|
99
98
|
end
|
100
99
|
|
101
|
-
|
100
|
+
Updater::Update.config_file = @config_file
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
def socket_for_client
|
105
|
+
if @options[:socket] && File.exists?(@options[:socket])
|
106
|
+
@logger.debug "Using UNIX Socket \"#{@options[:socket]}\""
|
107
|
+
return UNIXSocket.new(@options[:socket]) if File.exists?(@options[:socket]) && File.stat(@options[:socket]).socket?
|
108
|
+
end
|
109
|
+
if @options[:udp]
|
110
|
+
socket = UDPSocket.new()
|
111
|
+
socket.connect(@options[:host],@options[:udp])
|
112
|
+
begin
|
113
|
+
socket.write '.' #must test UDP sockets
|
114
|
+
return socket
|
115
|
+
rescue Errno::ECONNREFUSED
|
116
|
+
end
|
117
|
+
end
|
118
|
+
if @options[:tcp]
|
119
|
+
begin
|
120
|
+
return TCPSocket.new(@options[:host],@options[:tcp])
|
121
|
+
rescue Errno::ECONNREFUSED
|
122
|
+
end
|
123
|
+
end
|
124
|
+
if @options[:remote]
|
125
|
+
return nil
|
126
|
+
raise NotImplimentedError #For future Authenticated Http Rest Server
|
127
|
+
end
|
128
|
+
return nil
|
102
129
|
end
|
103
130
|
|
104
131
|
private
|
data/lib/updater/update.rb
CHANGED
@@ -212,6 +212,8 @@ module Updater
|
|
212
212
|
if inst
|
213
213
|
worker.logger.debug " running job #{inst.id}"
|
214
214
|
new(inst).run
|
215
|
+
else
|
216
|
+
worker.logger.debug " could not find a ready job in the datastore"
|
215
217
|
end
|
216
218
|
@orm.queue_time
|
217
219
|
ensure
|
@@ -405,6 +407,9 @@ module Updater
|
|
405
407
|
@orm.clear_all
|
406
408
|
end
|
407
409
|
|
410
|
+
# The name of the file to look for information if we loose the server
|
411
|
+
attr_accessor :config_file
|
412
|
+
|
408
413
|
#Sets the process id of the worker process if known. If this
|
409
414
|
#is set then an attempt will be made to signal the worker any
|
410
415
|
#time a new update is made.
|
@@ -431,12 +436,46 @@ module Updater
|
|
431
436
|
|
432
437
|
private
|
433
438
|
def signal_worker
|
434
|
-
|
435
|
-
|
436
|
-
@socket
|
437
|
-
|
438
|
-
|
439
|
+
errored = false
|
440
|
+
begin
|
441
|
+
if @socket
|
442
|
+
@socket.write '.'
|
443
|
+
logger.debug "Signaled Master Process Via Socket"
|
444
|
+
elsif @pid
|
445
|
+
Process::kill "USR2", @pid
|
446
|
+
logger.debug "Signaled Master Process Via PID"
|
447
|
+
else
|
448
|
+
signal_worker if connection_refresh
|
449
|
+
end
|
450
|
+
rescue SystemCallError
|
451
|
+
logger.warn "Lost Client Connection to Updater Server"
|
452
|
+
if connection_refresh && !errored
|
453
|
+
errored = true
|
454
|
+
retry
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
def connection_refresh
|
460
|
+
logger.debug "Connection Refresh Attempted"
|
461
|
+
@socket.close if @socket
|
462
|
+
@socket = nil; @pid = nil #assume the old server died
|
463
|
+
@connection_refresh ||= [1,Time.now-1]
|
464
|
+
delay, time = @connection_refresh
|
465
|
+
if Time.now >= time+delay
|
466
|
+
Setup.new(@config_file, :logger=>logger).client_setup
|
467
|
+
if @pid || @socket #assume we were successful and retry
|
468
|
+
@connection_refresh = nil
|
469
|
+
return true
|
470
|
+
else
|
471
|
+
logger.debug "Connection Refresh Failed"
|
472
|
+
#we are still not able to connect, don't try again for a while
|
473
|
+
@connection_refresh= [[delay*2,10*60].min,Time.now]
|
474
|
+
return false
|
475
|
+
end
|
439
476
|
end
|
477
|
+
logger.debug "Connection Refresh Waiting until #{time+delay}"
|
478
|
+
return false
|
440
479
|
end
|
441
480
|
|
442
481
|
# Given some instance return the information needed to recreate that target
|
data/lib/updater.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/update_spec.rb
CHANGED
metadata
CHANGED
@@ -5,9 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.9.3.2
|
8
|
+
- 4
|
9
|
+
version: 0.9.4
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- John F. Miller
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date:
|
17
|
+
date: 2011-02-14 00:00:00 -08:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|