updater 0.9.3.2 → 0.9.4

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 CHANGED
@@ -1 +1 @@
1
- 0.9.3.2
1
+ 0.9.4
@@ -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)}
@@ -32,7 +32,7 @@ module Updater
32
32
  end
33
33
 
34
34
  def _id=(val)
35
- val = BSON::ObjectID.from_string(val.to_s) unless val.kind_of? BSON::ObjectID
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 @hash
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::ObjectID's or Updater::Update's or both
110
- # For BSON::ObjectID's we cannot initialize them as this could leed to infinate loops.
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::ObjectID' (forign keys)
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::ObjectID/String),
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::ObjectID.
137
- # This method will bot instanciate object from BSON::ObjectID's
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::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
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::ObjectID
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::ObjectID.from_string(id) if id.kind_of? String
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
- if @options[:socket] && File.exists?(@options[:socket])
84
- @logger.debug "Using UNIX Socket \"#{@options[:socket]}\""
85
- Updater::Update.socket = UNIXSocket.new(@options[:socket])
86
- elsif @options[:udp]
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
@@ -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
- # TODO: If worker process goes down or has to be reset, try to reconnect
435
- if @socket
436
- @socket.write '.'
437
- elsif @pid
438
- Process::kill "USR2", @pid
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
@@ -4,4 +4,5 @@ module Updater
4
4
  VERSION = File.read(File.join(File.dirname(__FILE__),'..','VERSION')).strip
5
5
  end
6
6
 
7
- require 'updater/update.rb'
7
+ require 'updater/update.rb'
8
+ require 'updater/setup.rb'
data/spec/spec_helper.rb CHANGED
@@ -8,7 +8,7 @@ require "dm-core"
8
8
  require 'dm-migrations'
9
9
 
10
10
  require 'updater'
11
- #require 'updater/thread_worker'
11
+ require 'updater/thread_worker'
12
12
  require 'updater/fork_worker'
13
13
  require 'updater/orm/datamapper'
14
14
 
data/spec/update_spec.rb CHANGED
@@ -13,7 +13,7 @@ describe Update do
13
13
 
14
14
  end
15
15
 
16
- context "Gemspec: " do
16
+ describe "Gemspec: " do
17
17
  it"should match version" do
18
18
  gs = File.open(File.join(ROOT,'updater.gemspec')) do |f|
19
19
  eval f.read
metadata CHANGED
@@ -5,9 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 3
9
- - 2
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: 2010-08-26 00:00:00 -07:00
17
+ date: 2011-02-14 00:00:00 -08:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency