updater 0.3.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/updater/fork_worker.rb +4 -4
- data/lib/updater/orm/datamapper.rb +8 -4
- data/lib/updater/orm/orm.rb +239 -0
- data/lib/updater/setup.rb +113 -0
- data/lib/updater/simulated.db +0 -0
- data/lib/updater/tasks.rb +15 -3
- data/lib/updater/update.rb +15 -5
- data/spec/fooclass.rb +4 -0
- metadata +7 -4
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ GEM_VERSION = File.read(VERSION_FILE).strip
|
|
9
9
|
AUTHOR = "John F. Miller"
|
10
10
|
EMAIL = "emperor@antarestrader.com"
|
11
11
|
HOMEPAGE = "http://blog.antarestrader.com"
|
12
|
-
SUMMARY = "
|
12
|
+
SUMMARY = "A Gem for queuing methods for later calling which is ORM Agnostic, and has advanced Error Handling"
|
13
13
|
|
14
14
|
spec = Gem::Specification.new do |s|
|
15
15
|
s.name = GEM_NAME
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2
|
data/lib/updater/fork_worker.rb
CHANGED
@@ -29,7 +29,8 @@ module Updater
|
|
29
29
|
@logger = Logger.new(STDOUT)
|
30
30
|
@logger.level = Logger::WARN
|
31
31
|
end
|
32
|
-
logger.
|
32
|
+
logger.warn "***Setting Up Master Process***"
|
33
|
+
logger.warn " Pid = #{Process.pid}"
|
33
34
|
@max_workers = options[:workers] || 3
|
34
35
|
logger.info "Max Workers set to #{@max_workers}"
|
35
36
|
@timeout = options[:timeout] || 60
|
@@ -92,8 +93,6 @@ module Updater
|
|
92
93
|
# * :sockets: 0 or more IO objects that should wake up master to alert it that new data is availible
|
93
94
|
|
94
95
|
def start(stream,options = {})
|
95
|
-
logger.info "=== ForkWorker Start ==="
|
96
|
-
logger.info " Pid = #{Process.pid}"
|
97
96
|
initial_setup(options) #need this for logger
|
98
97
|
logger.info "*** Starting Master Process***"
|
99
98
|
@stream = stream
|
@@ -318,7 +317,8 @@ module Updater
|
|
318
317
|
@pipe.last.write '.'
|
319
318
|
trap(:QUIT,"IGNORE")
|
320
319
|
end
|
321
|
-
trap(:TERM) { Update.clear_locks(self); exit }
|
320
|
+
trap(:TERM) { Update.clear_locks(self); Process.exit!(0) }
|
321
|
+
logger.info "#{name} is on-line"
|
322
322
|
while @continue do
|
323
323
|
heartbeat
|
324
324
|
begin
|
@@ -25,7 +25,7 @@ module Updater
|
|
25
25
|
property :finder_args, Yaml
|
26
26
|
property :method, String
|
27
27
|
property :method_args, Object, :lazy=>false
|
28
|
-
property :name, String
|
28
|
+
property :name, String, :length=>255
|
29
29
|
property :lock_name, String
|
30
30
|
property :persistant, Boolean
|
31
31
|
|
@@ -68,6 +68,10 @@ module Updater
|
|
68
68
|
target = target.orm if target.kind_of? Updater::Update
|
69
69
|
chains.new(:target=>target,:occasion=>mode)
|
70
70
|
end
|
71
|
+
when nil
|
72
|
+
chains=[]
|
73
|
+
else
|
74
|
+
raise ArgumentError
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
@@ -135,7 +139,7 @@ module Updater
|
|
135
139
|
DMChained.all.destroy!
|
136
140
|
end
|
137
141
|
|
138
|
-
def for(mytarget, myfinder, myfinder_args, myname)
|
142
|
+
def for(mytarget, myfinder, myfinder_args, myname=nil)
|
139
143
|
#TODO
|
140
144
|
end
|
141
145
|
|
@@ -164,8 +168,8 @@ module Updater
|
|
164
168
|
belongs_to :caller, :model=>Updater::ORM::DataMapper, :child_key=>[:caller_id]
|
165
169
|
belongs_to :target, :model=>Updater::ORM::DataMapper, :child_key=>[:target_id]
|
166
170
|
|
167
|
-
property :params,
|
168
|
-
property :occasion, String, :nullable=>false
|
171
|
+
property :params, Object, :nullable=>true #:required=>false
|
172
|
+
property :occasion, String, :nullable=>false #:required=>true
|
169
173
|
end
|
170
174
|
|
171
175
|
end#ORM
|
@@ -0,0 +1,239 @@
|
|
1
|
+
module Updater
|
2
|
+
module ORM
|
3
|
+
|
4
|
+
# This is the root class for ORM inplimentations. It provides some very
|
5
|
+
# basicfunctionality that may be useful for implimenting actuall ORM's
|
6
|
+
# but cannot itself be run or instantiated. The documentation for this
|
7
|
+
# class also serves as the cannonical reference for the ORM API.
|
8
|
+
#
|
9
|
+
# for purposes of this documentation instances of a class inheriting form
|
10
|
+
# this class will be refered to as 'jobs.'
|
11
|
+
#
|
12
|
+
# In addation to the methods listed below, it MUST provide accessors for the
|
13
|
+
# 12 fields below. Most ORMs will add these when the fields are setup
|
14
|
+
#
|
15
|
+
# == Fields
|
16
|
+
#
|
17
|
+
# These fields with thier getters and setters (except id which is read only) are expected
|
18
|
+
# to be implimented in every ORM implimention. Other fields may be implimented as
|
19
|
+
# well, but clients SHOULD NOT depend on or manipulate them. ORM will need to
|
20
|
+
# impliment some persistant way to lock records, and should do so in such a way as the
|
21
|
+
# name of the worker can be tracked, and jobs cleared for that worker should it crach
|
22
|
+
# if the underlying datastore allows.
|
23
|
+
#
|
24
|
+
# id: a unique value asigned to each job. For purposes of the API it is a black box
|
25
|
+
# which should be paseed to the ClassMethods#get method to retrieve the job. If
|
26
|
+
# the ORM uses a different name for this value such as _id or key, a reader method
|
27
|
+
# must be implimented as id.
|
28
|
+
#
|
29
|
+
# time [Integer]: This is the time in seconds at which the job should be run. It is
|
30
|
+
# always in reference to Updater::Update.time (by default Time). This value will be
|
31
|
+
# nil for chained methods.
|
32
|
+
#
|
33
|
+
# target [Class]: The class of the target for this job. the API spesifies that it must be
|
34
|
+
# a Ruby class currently in scope in both the workers' and clients' frames of reference.
|
35
|
+
# (see configuration documentation for how to achieve this.) The writer must accept an
|
36
|
+
# actual class, which it may store in the datastore as a string (by calling to_s on it). The
|
37
|
+
# reader method must return the actual class by if ecessary calling Object.const_get(str)
|
38
|
+
# with the stored value.
|
39
|
+
#
|
40
|
+
# finder [String]: A method to call on the Target in orderto get the target instance.
|
41
|
+
# The API limits its length to no more then 50 charactors. If the class itself is the
|
42
|
+
# target, this value will either not be set or set to nil. The reader should MUST return
|
43
|
+
# nil in this case.
|
44
|
+
#
|
45
|
+
# finder_args [Array]: A possibly complex array of valuse that will be paseed to the
|
46
|
+
# finder method in order to retrieve the target instance. The API spesifies that the
|
47
|
+
# array and all subelements must impliment the #to_yaml and #to_json method in
|
48
|
+
# addation to being Marshalable. If the class itself is the
|
49
|
+
# target, this value will either not be set or set to nil. The reader should MUST return
|
50
|
+
# nil in this case.
|
51
|
+
#
|
52
|
+
# method [String]: The method to be sent to the target instance. The API limits this value
|
53
|
+
# to 50 charictars. It MAY NOT be nil or empty.
|
54
|
+
#
|
55
|
+
# method_args [Array]: A possibly complex array of values to pass to the spesified method of
|
56
|
+
# the target instance. It must be marshalable. The ORM layer is responcible to Marshal.dump
|
57
|
+
# and Marshal.load these values.
|
58
|
+
#
|
59
|
+
# name [String]: If the ORM impliments the +for+ method, then it MUST store a name which the
|
60
|
+
# API spesifies SHOULD be unique per target. The ORM SHOULD NOT enforce this restriction, but
|
61
|
+
# MAY assume it. ORM's that do not impliment +for+ must none the less have a #name= method
|
62
|
+
# that returns the value passed to it (as is normal with setter methods) and must not raise an error
|
63
|
+
# when a hash of values includes name. It must also respond to the name method with nil. When
|
64
|
+
# inplimented, name may be no longer then 255 characters.
|
65
|
+
#
|
66
|
+
# persistant [Boolean]: if this value is set to true a worker will not call destroy after running the job.
|
67
|
+
# If it is nil or not set it may be assumed to be false, and ORM may return nil instead of false in this
|
68
|
+
# case.
|
69
|
+
#
|
70
|
+
# == Chained Jobs
|
71
|
+
#
|
72
|
+
# Chained Jobs are run after a job and allow for various function to take place such as logging and
|
73
|
+
# error handleing. There are three(3) categories for chaining :failure, :success, and :ensure. The
|
74
|
+
# ORM must impliment a getter and setter for each as described below. This version does not
|
75
|
+
# inpliment it, but ORMs should be be designed in such a way that :prior and :instead chains can be
|
76
|
+
# added in future version of this API.
|
77
|
+
#
|
78
|
+
# === Getters:
|
79
|
+
# getters should return an array of structures (Struct or equivelent) representing the chained jobs
|
80
|
+
# for this job. The structure should have three(3) members and MAY be read-only.
|
81
|
+
#
|
82
|
+
# caller: An instance of the ORM class for the job in question (i.e. self)
|
83
|
+
#
|
84
|
+
# target: An instance of the ORM class for the chained job
|
85
|
+
#
|
86
|
+
# params: a Hash or other object that will be substituted for the special value '__params__' when calling
|
87
|
+
# the target job.
|
88
|
+
#
|
89
|
+
# The object returned may have other methods and functionality. Clients SHOULD NOT antisipate or use
|
90
|
+
# these methods.
|
91
|
+
#
|
92
|
+
# === Setters:
|
93
|
+
# setters must accept five(5) differnt types of input. Except as described below setters are NOT distructive,
|
94
|
+
# that is job.failure=logme adds logme to the list of failure jobs and does not remove jobs that may have previously
|
95
|
+
# been chained. Clients should call save after using the setter to write the changes to disk
|
96
|
+
#
|
97
|
+
# ORM or Updater::Update: Add this job to the chain, with no parameters. Updater::Update#orm will give the job.
|
98
|
+
#
|
99
|
+
# Array<ORM or Updater::Update>: Add each job in the array to the chain
|
100
|
+
#
|
101
|
+
# Hash(<ORM or Updater::Update>, params): Add the keys to the chain with the valuse as params. Clients
|
102
|
+
# should note that it is not possible to add multiple calls to the same job using this method.
|
103
|
+
#
|
104
|
+
# nil: remove all jobs from this chain. Clients Note, that this is the only way to remove a previously added
|
105
|
+
# job from a chain.
|
106
|
+
class Base
|
107
|
+
|
108
|
+
# Every ORM should set this constant to a symbol that matches the most
|
109
|
+
# obvious method used to retrive a known instance. :get or:find are likely
|
110
|
+
# candidates.
|
111
|
+
FINDER= nil
|
112
|
+
|
113
|
+
# every ORM should set this to a method when called on an object producted by
|
114
|
+
# that ORM will give a value that can be passed to the FINDER method to retrieve
|
115
|
+
# the object from the datastore. :id, _id, or :key are likely candidates
|
116
|
+
ID = nil
|
117
|
+
|
118
|
+
# Workers will call this method on a job before running it to insure that in the case
|
119
|
+
# of multiple workers hiting the same queue only one will run the job. The worker
|
120
|
+
# MUST pass itself to Lock, and the implimentation MAY use the name of the worker
|
121
|
+
# to identify who has locked this job.
|
122
|
+
#
|
123
|
+
# If a worker is successfully able to lock this job, or has already locked the Job, this
|
124
|
+
# method MUST return a true value. If a lock was unsuccessful, it MUST return the
|
125
|
+
# value false, and MAY use the 'say' method of the suplied worker to explain why a lock
|
126
|
+
# could not be aquired.
|
127
|
+
def lock(worker)
|
128
|
+
NotImplementedError
|
129
|
+
end
|
130
|
+
|
131
|
+
#write any changes made to the job back to the datastore.
|
132
|
+
def save
|
133
|
+
NotImplementedError
|
134
|
+
end
|
135
|
+
|
136
|
+
#Remove this job from the datastore.
|
137
|
+
def destroy
|
138
|
+
NotImplementedError
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
class ClassMethods
|
144
|
+
|
145
|
+
# When passed the value returned by the #id method of a job, this method must return
|
146
|
+
# that job from the datastore.
|
147
|
+
def get(id)
|
148
|
+
NotImplementedError
|
149
|
+
end
|
150
|
+
|
151
|
+
# The hash keys are symbols for the one of the 12 field values listed in the intro to the
|
152
|
+
# ORM::Base class. The values are the actual values that should be returned by the
|
153
|
+
# accessor methods. Depending on the datastore some values may need to be marshaled
|
154
|
+
# converted, etc.. before being written to the datastore.
|
155
|
+
def create(hash)
|
156
|
+
NotImplementedError
|
157
|
+
end
|
158
|
+
|
159
|
+
# This method returns all jobs that are now ready to run, that is thier time valuse is less
|
160
|
+
# then or equal to the value returned by calling now on the registered time class (tnow).
|
161
|
+
def current
|
162
|
+
NotImplementedError
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns a count of how many jobs are currently ready to run.
|
166
|
+
def current_load
|
167
|
+
NotImplementedError
|
168
|
+
end
|
169
|
+
|
170
|
+
# Runurns a count of the number of jobs scheduled to run at a later time, that is there
|
171
|
+
# time value is strictly greater then the value returned by calling now on the registered
|
172
|
+
# time class(tnow)
|
173
|
+
def delayed
|
174
|
+
NotImplementedError
|
175
|
+
end
|
176
|
+
|
177
|
+
# Returns a count of how may jobs are curently scheduled between start and finish seconds
|
178
|
+
# from now. e.g future(0,60) would tell you how many jobs will run in the next minute. This
|
179
|
+
# function is used to adjust the number of workers needed as well as for monitering.
|
180
|
+
def future(start, finish)
|
181
|
+
NotImplementedError
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns the number os seconds until the next job will be ready to run. If there are no
|
185
|
+
# Jobs in the queue it returns nil, if there is at least one job ready to run it MUST return
|
186
|
+
# 0. This may be an apporximation or the value may be cached for brief periods to improve
|
187
|
+
# datastore performance.
|
188
|
+
def queue_time
|
189
|
+
NotImplementedError
|
190
|
+
end
|
191
|
+
|
192
|
+
# Locks to a worker and returns a job that is ready to run. Workers will call this when they are
|
193
|
+
# ready for another job. In general it should lock jobs in the order they were recieved or scheduled,
|
194
|
+
# but strict ordering is not a requirement. (c.f. delayed_job). If there are current jobs, this method
|
195
|
+
# MUST return one which has been locked successfully, internally trying successive current jobs if
|
196
|
+
# the first one fails to lock. It MUST NOT raise an error or return nil if the datastore is temerarly
|
197
|
+
# busy. Instead it must wait until it can either get access to and lock a record, or prove that no jobs
|
198
|
+
# are current.
|
199
|
+
#
|
200
|
+
# In the event that there are no current jobs left in the datastore this method should retunr nil. The
|
201
|
+
# should inturperate this as a sign that the queue is empty and consult +queue_time+ to determine
|
202
|
+
# how long to wait for the next job.
|
203
|
+
def lock_next(worker)
|
204
|
+
NotImplementedError
|
205
|
+
end
|
206
|
+
|
207
|
+
# This method unlocks and makes availible any and all jobs which have been locked by the worker.
|
208
|
+
# Workers are uniquely identified by the +name+ method. This is an indication that the worker has
|
209
|
+
# died or been killed and cannot complete its job.
|
210
|
+
def clear_locks(worker)
|
211
|
+
NotImplementedError
|
212
|
+
end
|
213
|
+
|
214
|
+
# Compleatly remove all jobs and associeted data from the datastore including chained
|
215
|
+
# Methods.
|
216
|
+
def clear_all
|
217
|
+
NotImplementedError
|
218
|
+
end
|
219
|
+
|
220
|
+
# Optional, but strongly recomended.
|
221
|
+
#
|
222
|
+
# For any datastore that permits, return and Array of all delayed, chained, and current but not locked jobs that reference
|
223
|
+
# mytarget, myfinder, and myfinder_args, that is they clearly have the spesified Target. Optionally, limit the result to
|
224
|
+
# return the first job that also has a name value of myname. The name value is spesified as unique per target so the
|
225
|
+
# which record is returned in the case that multiple jobs fro the same target share the same name is undefined.
|
226
|
+
def for(mytarget, myfinder, myfinder_args, myname=nil)
|
227
|
+
NotImplementedError
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
#Short hand method that retruns the current time value that this queue is using.
|
233
|
+
def tnow
|
234
|
+
Updater::Update.time.now.to_i
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'yaml'
|
3
|
+
require 'socket'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
module Updater
|
7
|
+
class Setup
|
8
|
+
class << self
|
9
|
+
def start
|
10
|
+
new(config_file).start
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop
|
14
|
+
new(config_file).stop
|
15
|
+
end
|
16
|
+
|
17
|
+
def monitor
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def config_file
|
22
|
+
if ENV['UPDATE_CONFIG'] && File.exists(ENV['UPDATE_CONFIG'])
|
23
|
+
ENV['UPDATE_CONFIG']
|
24
|
+
else
|
25
|
+
(Dir.glob('{config,.}/updater.config') + Dir.glob('.updater')).first
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ROOT = File.dirname(self.config_file)
|
31
|
+
|
32
|
+
def initialize(file_or_hash)
|
33
|
+
@options = file_or_hash.kind_of?(Hash) ? file_or_hash : load_file(file_or_hash)
|
34
|
+
@options[:pid_file] ||= File.join(ROOT,'updater.pid')
|
35
|
+
@options[:host] ||= "localhost"
|
36
|
+
@logger = Logger.new(@options[:log_file] || STDOUT)
|
37
|
+
level = Logger::SEV_LABEL.index(@options[:log_level].upcase) if @options[:log_level]
|
38
|
+
@logger.level = level || Logger::WARN
|
39
|
+
end
|
40
|
+
|
41
|
+
def start
|
42
|
+
@logger.warn "Starting Loop"
|
43
|
+
pid = Process.fork do
|
44
|
+
_start
|
45
|
+
end
|
46
|
+
@logger.warn "Rake Successfully started Master Loop at pid #{pid}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def stop
|
50
|
+
Process.kill("TERM",File.read(@options[:pid_file]).to_i)
|
51
|
+
end
|
52
|
+
|
53
|
+
def client
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def _start
|
60
|
+
#set ORM
|
61
|
+
require 'updater/orm/datamapper'
|
62
|
+
Updater::Update.orm = ORM::DataMapper
|
63
|
+
|
64
|
+
#init DataStore
|
65
|
+
DataMapper.logger = @logger
|
66
|
+
DataMapper.setup(:default, :adapter=>'sqlite3', :database=>'./simulated.db')
|
67
|
+
|
68
|
+
#load Models
|
69
|
+
|
70
|
+
models = @options[:models] || Dir.glob('./app/models/**/*.rb')
|
71
|
+
models.each do |file|
|
72
|
+
require file
|
73
|
+
end
|
74
|
+
|
75
|
+
#establish Connections
|
76
|
+
#Unix Socket -- name at @options[:socket]
|
77
|
+
if @options[:socket]
|
78
|
+
File.unlink @options[:socket] if File.exists? @options[:socket]
|
79
|
+
@options[:sockets] ||= []
|
80
|
+
@options[:sockets] << UNIXServer.new(@options[:socket])
|
81
|
+
end
|
82
|
+
|
83
|
+
#UDP potentially unsafe user monitor server for Authenticated Connections (TODO)
|
84
|
+
if @options[:udp]
|
85
|
+
@options[:sockets] ||= []
|
86
|
+
udp = UDPSocket.new
|
87
|
+
udp.bind(@options[:host],@options[:udp])
|
88
|
+
@options[:sockets] << udp
|
89
|
+
end
|
90
|
+
|
91
|
+
#TCP Unsafe user monitor server for Authenticated Connections (TODO)
|
92
|
+
if @options[:tcp]
|
93
|
+
@options[:sockets] ||= []
|
94
|
+
@options[:sockets] << TCPServer.new(@options[:host],@options[:tcp])
|
95
|
+
end
|
96
|
+
|
97
|
+
#Log PID
|
98
|
+
File.open(@options[:pid_file],'w') { |f| f.write(Process.pid.to_s)}
|
99
|
+
#start Worker
|
100
|
+
require 'updater/fork_worker'
|
101
|
+
worker_class = ForkWorker
|
102
|
+
worker_class.logger = @logger
|
103
|
+
worker_class.start(@options)
|
104
|
+
end
|
105
|
+
|
106
|
+
def load_file(file)
|
107
|
+
return {} if file.nil?
|
108
|
+
file = File.open(file) if file.kind_of?(String)
|
109
|
+
@config_file = File.expand_path(file.path)
|
110
|
+
YAML.load(ERB.new(File.read(file)).result(binding)) || {}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
Binary file
|
data/lib/updater/tasks.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
|
+
require 'updater'
|
2
|
+
require 'updater/setup'
|
1
3
|
namespace :updater do
|
2
|
-
desc "
|
3
|
-
task :
|
4
|
-
|
4
|
+
desc "Start processing jobs using the settings in updater.config"
|
5
|
+
task :start do
|
6
|
+
Updater::Setup.start
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Stop procedssing jobs"
|
10
|
+
task :stop do
|
11
|
+
Updater::Setup.stop
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Start monitering the Job queue <Planed>"
|
15
|
+
task :monitor do
|
16
|
+
puts "No Implimentation (yet). This feature will be comming \"any day now.\""
|
5
17
|
end
|
6
18
|
end
|
data/lib/updater/update.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
module Updater
|
2
|
+
class TargetMissingError < StandardError
|
3
|
+
end
|
2
4
|
|
3
5
|
#the basic class that drives updater
|
4
6
|
class Update
|
@@ -9,9 +11,9 @@ module Updater
|
|
9
11
|
#Run the action on this traget compleating any chained actions
|
10
12
|
def run(job=nil,params=nil)
|
11
13
|
ret = true #put return in scope
|
12
|
-
t = target #do not trap errors here
|
13
|
-
final_args = sub_args(job,params,@orm.method_args)
|
14
14
|
begin
|
15
|
+
t = target
|
16
|
+
final_args = sub_args(job,params,@orm.method_args)
|
15
17
|
t.send(@orm.method.to_sym,*final_args)
|
16
18
|
rescue => e
|
17
19
|
@error = e
|
@@ -20,7 +22,7 @@ module Updater
|
|
20
22
|
ensure
|
21
23
|
run_chain :success if ret
|
22
24
|
run_chain :ensure
|
23
|
-
@orm.destroy
|
25
|
+
@orm.destroy unless @orm.persistant
|
24
26
|
end
|
25
27
|
ret
|
26
28
|
end
|
@@ -30,7 +32,9 @@ module Updater
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def target
|
33
|
-
@orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,@orm.finder_args)
|
35
|
+
target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,@orm.finder_args)
|
36
|
+
raise TargetMissingError, "Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'" unless target
|
37
|
+
target
|
34
38
|
end
|
35
39
|
|
36
40
|
def initialize(orm_inst)
|
@@ -195,6 +199,7 @@ module Updater
|
|
195
199
|
# use +at+ and friends for everyday use cases.
|
196
200
|
def schedule(hash)
|
197
201
|
new(@orm.create(hash))
|
202
|
+
signal_worker
|
198
203
|
end
|
199
204
|
|
200
205
|
# Create a new job having the same charistics as the old, except that 'hash' will override the original.
|
@@ -290,7 +295,7 @@ module Updater
|
|
290
295
|
Process::kill 0, @pid
|
291
296
|
@pid
|
292
297
|
rescue Errno::ESRCH, ArgumentError
|
293
|
-
raise ArgumentError "PID was invalid"
|
298
|
+
raise ArgumentError, "PID was invalid"
|
294
299
|
end
|
295
300
|
|
296
301
|
def pid
|
@@ -298,6 +303,11 @@ module Updater
|
|
298
303
|
end
|
299
304
|
|
300
305
|
private
|
306
|
+
def signal_worker
|
307
|
+
if @pid
|
308
|
+
Process::kill "USR2", @pid
|
309
|
+
end
|
310
|
+
end
|
301
311
|
|
302
312
|
# Given some instance return the information needed to recreate that target
|
303
313
|
def target_for(inst)
|
data/spec/fooclass.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: updater
|
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
|
- John F. Miller
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-18 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: 0.2.3
|
54
54
|
version:
|
55
|
-
description:
|
55
|
+
description: A Gem for queuing methods for later calling which is ORM Agnostic, and has advanced Error Handling
|
56
56
|
email: emperor@antarestrader.com
|
57
57
|
executables: []
|
58
58
|
|
@@ -68,12 +68,15 @@ files:
|
|
68
68
|
- Rakefile
|
69
69
|
- VERSION
|
70
70
|
- lib/updater.rb
|
71
|
+
- lib/updater/setup.rb
|
71
72
|
- lib/updater/util.rb
|
72
73
|
- lib/updater/update.rb
|
73
74
|
- lib/updater/fork_worker.rb
|
74
75
|
- lib/updater/update_dm.rb
|
76
|
+
- lib/updater/simulated.db
|
75
77
|
- lib/updater/tasks.rb
|
76
78
|
- lib/updater/thread_worker.rb
|
79
|
+
- lib/updater/orm/orm.rb
|
77
80
|
- lib/updater/orm/datamapper.rb
|
78
81
|
- spec/fork_worker_instance_spec.rb
|
79
82
|
- spec/thread_worker_spec.rb
|
@@ -117,6 +120,6 @@ rubyforge_project:
|
|
117
120
|
rubygems_version: 1.3.5
|
118
121
|
signing_key:
|
119
122
|
specification_version: 3
|
120
|
-
summary:
|
123
|
+
summary: A Gem for queuing methods for later calling which is ORM Agnostic, and has advanced Error Handling
|
121
124
|
test_files: []
|
122
125
|
|