updater 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/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
|
|