updater 0.9.4 → 0.10.0
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 +8 -9
- data/VERSION +1 -1
- data/lib/updater/fork_worker.rb +1 -1
- data/lib/updater/orm/activerocord.rb +23 -0
- data/lib/updater/orm/datamapper.rb +28 -8
- data/lib/updater/orm/mock.rb +155 -0
- data/lib/updater/orm/mongo.rb +50 -15
- data/lib/updater/orm/orm.rb +3 -1
- data/lib/updater/setup.rb +24 -7
- data/lib/updater/thread_worker.rb +5 -0
- data/lib/updater/update.rb +8 -5
- data/spec/chained_spec.rb +3 -2
- data/spec/datamapper_orm_spec.rb +7 -0
- data/spec/errors_spec.rb +1 -1
- data/spec/fooclass.rb +42 -11
- data/spec/fooclass_spec.rb +38 -0
- data/spec/fork_worker_instance_spec.rb +0 -19
- data/spec/fork_worker_spec.rb +1 -0
- data/spec/mock_orm_spec.rb +7 -0
- data/spec/mongo_orm_spec.rb +7 -0
- data/spec/named_request_spec.rb +1 -4
- data/spec/orm_lint.rb +292 -0
- data/spec/params_sub_spec.rb +2 -1
- data/spec/results.html +1567 -0
- data/spec/schedule_spec.rb +18 -9
- data/spec/spec_helper.rb +7 -8
- data/spec/thread_worker_spec.rb +0 -37
- data/spec/update_runner_spec.rb +4 -6
- data/spec/update_spec.rb +1 -1
- data/spec/util_spec.rb +0 -2
- metadata +16 -15
- data/lib/updater/orm/mongo.rb~ +0 -188
- data/lib/updater/setup.rb~ +0 -175
- data/lib/updater/simulated.db +0 -0
- data/lib/updater/thread_worker.rb~ +0 -92
- data/lib/updater/update_dm.rb +0 -298
- data/spec/lock_spec.rb +0 -64
- data/spec/spec_helper.rb~ +0 -23
data/Rakefile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake/gempackagetask'
|
3
|
-
|
4
|
-
require 'spec/rake/spectask'
|
3
|
+
require 'rspec/core/rake_task'
|
5
4
|
|
6
5
|
|
7
6
|
VERSION_FILE = File.join(File.dirname(__FILE__), 'VERSION')
|
@@ -26,7 +25,7 @@ spec = Gem::Specification.new do |s|
|
|
26
25
|
s.email = EMAIL
|
27
26
|
s.homepage = HOMEPAGE
|
28
27
|
s.add_development_dependency('datamapper', '>= 0.10.2')
|
29
|
-
s.add_development_dependency('rspec', '
|
28
|
+
s.add_development_dependency('rspec', '>= 2.0.0')
|
30
29
|
s.add_development_dependency('timecop', '>= 0.2.1')
|
31
30
|
s.add_development_dependency('chronic', '>= 0.2.3')
|
32
31
|
s.require_path = 'lib'
|
@@ -40,21 +39,21 @@ Rake::GemPackageTask.new(spec) do |pkg|
|
|
40
39
|
pkg.gem_spec = spec
|
41
40
|
end
|
42
41
|
|
43
|
-
|
44
|
-
|
42
|
+
RSpec::Core::RakeTask.new do |t|
|
43
|
+
ruby_opts="-w"
|
45
44
|
t.rcov = false
|
46
45
|
end
|
47
46
|
|
48
|
-
|
47
|
+
RSpec::Core::RakeTask.new do |t|
|
49
48
|
t.name="failing"
|
50
49
|
#todo Make this run only failing specs
|
51
|
-
|
50
|
+
ruby_opts="-w"
|
52
51
|
t.rcov = false
|
53
52
|
end
|
54
53
|
|
55
|
-
|
54
|
+
RSpec::Core::RakeTask.new do |t|
|
56
55
|
t.name="rcov"
|
57
|
-
|
56
|
+
ruby_opts="-w"
|
58
57
|
t.rcov = true
|
59
58
|
end
|
60
59
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.10.0
|
data/lib/updater/fork_worker.rb
CHANGED
@@ -231,7 +231,7 @@ module Updater
|
|
231
231
|
|
232
232
|
def add_worker(worker_number)
|
233
233
|
worker = WorkerMonitor.new(worker_number,Updater::Util.tempio)
|
234
|
-
Update.orm.before_fork
|
234
|
+
Update.orm.before_fork if Update.orm.respond_to? :before_fork
|
235
235
|
pid = Process.fork do
|
236
236
|
fork_cleanup
|
237
237
|
self.new(@pipe,worker).run
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Updater
|
2
|
+
module ORm
|
3
|
+
|
4
|
+
class ActiveRecord
|
5
|
+
raise NoImplimentationError
|
6
|
+
def lock(worker)
|
7
|
+
return true if locked? && locked_by == worker.name
|
8
|
+
#all this to make sure the check and the lock are simultanious:
|
9
|
+
ccnt = self.class.where(id: self.id, lock: nil).update_all(:lock=>worker.name)
|
10
|
+
if 0 != cnt
|
11
|
+
@lock_name = worker.name
|
12
|
+
true
|
13
|
+
else
|
14
|
+
worker.say( "Worker #{worker.name} Failed to aquire lock on job #{id}" )
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "dm-core"
|
2
2
|
require "dm-types"
|
3
|
+
require "dm-migrations"
|
3
4
|
|
4
5
|
module Updater
|
5
6
|
module ORM
|
@@ -31,6 +32,10 @@ module Updater
|
|
31
32
|
|
32
33
|
has n, :chains, :model=>'Updater::ORM::DMChained', :child_key=>[:caller_id]
|
33
34
|
|
35
|
+
def method
|
36
|
+
self[:method]
|
37
|
+
end
|
38
|
+
|
34
39
|
#attempt to lock this record for the worker
|
35
40
|
def lock(worker)
|
36
41
|
return true if locked? && locked_by == worker.name
|
@@ -55,28 +60,33 @@ module Updater
|
|
55
60
|
define_method "#{mode}=" do |chain|
|
56
61
|
case chain
|
57
62
|
when self.class
|
58
|
-
chains.new(:target=>chain,:occasion=>mode)
|
63
|
+
self.chains.new(:target=>chain,:occasion=>mode)
|
59
64
|
when Updater::Update
|
60
|
-
chains.new(:target=>chain.orm,:occasion=>mode)
|
65
|
+
self.chains.new(:target=>chain.orm,:occasion=>mode)
|
61
66
|
when Hash
|
62
67
|
chain.each do |target, params|
|
63
68
|
target = target.orm if target.kind_of? Updater::Update
|
64
|
-
chains.new(:target=>target,:params=>params, :occasion=>mode)
|
69
|
+
self.chains.new(:target=>target,:params=>params, :occasion=>mode)
|
65
70
|
end
|
66
71
|
when Array
|
67
72
|
chain.each do |target|
|
73
|
+
target, params = target
|
68
74
|
target = target.orm if target.kind_of? Updater::Update
|
69
|
-
chains.new(:target=>target,:occasion=>mode)
|
75
|
+
self.chains.new(:target=>target,:occasion=>mode, :params=>params)
|
70
76
|
end
|
77
|
+
when Integer
|
78
|
+
self.chains.new(:target_id=>chain,:occasion=>mode)
|
71
79
|
when nil
|
72
|
-
chains=[]
|
80
|
+
self.chains=[]
|
73
81
|
else
|
74
|
-
raise ArgumentError
|
82
|
+
raise ArgumentError, "Cannot add #{chain.inspect} to a chain (%s:%s)" % [__FILE__,__LINE__]
|
75
83
|
end
|
84
|
+
save
|
85
|
+
chain
|
76
86
|
end
|
77
87
|
|
78
88
|
define_method mode do
|
79
|
-
chains.all(:occasion=>mode).map {|job|
|
89
|
+
chains.all(:occasion=>mode).map {|job| Update.new(job.target).tap {|u| u.params = job.params}}
|
80
90
|
end
|
81
91
|
end
|
82
92
|
|
@@ -145,7 +155,7 @@ module Updater
|
|
145
155
|
search = all(
|
146
156
|
:target=>mytarget,
|
147
157
|
:finder=>myfinder,
|
148
|
-
:finder_args=>myfinder_args,
|
158
|
+
:finder_args=>myfinder_args.to_yaml,
|
149
159
|
:lock_name=>nil
|
150
160
|
)
|
151
161
|
myname ? search.all(:name=>myname ) : search
|
@@ -154,7 +164,17 @@ module Updater
|
|
154
164
|
#For the server only, setup the connection to the database
|
155
165
|
def setup(options)
|
156
166
|
::DataMapper.logger = options.delete(:logger)
|
167
|
+
auto_migrate = options.delete(:auto_migrate)
|
157
168
|
::DataMapper.setup(:default,options)
|
169
|
+
::DataMapper.auto_migrate! if auto_migrate
|
170
|
+
end
|
171
|
+
|
172
|
+
def logger
|
173
|
+
::DataMapper.logger
|
174
|
+
end
|
175
|
+
|
176
|
+
def logger=(input)
|
177
|
+
::DataMapper.logger = input
|
158
178
|
end
|
159
179
|
|
160
180
|
# For pooled connections it is necessary to empty the pool of the parents connections so that they
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Updater
|
2
|
+
module ORM
|
3
|
+
class Mock
|
4
|
+
|
5
|
+
FINDER = :find
|
6
|
+
|
7
|
+
ID = :id
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :logger
|
11
|
+
|
12
|
+
def index
|
13
|
+
@index ||= 0
|
14
|
+
@index += 1
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(id)
|
18
|
+
storage[id]
|
19
|
+
end
|
20
|
+
|
21
|
+
def create(hash)
|
22
|
+
new(hash).tap {|n| storage[n.id] = n}
|
23
|
+
end
|
24
|
+
|
25
|
+
def current
|
26
|
+
storage.values.find_all{|x|
|
27
|
+
x.time && x.time <= tnow && !x.lock_name
|
28
|
+
}.sort{|a,b| a.time <=> b.time}
|
29
|
+
end
|
30
|
+
|
31
|
+
def current_load
|
32
|
+
current.length
|
33
|
+
end
|
34
|
+
|
35
|
+
def _delayed
|
36
|
+
storage.values.find_all{|x|
|
37
|
+
x.time && x.time > tnow
|
38
|
+
}.sort{|a,b| a.time <=> b.time}
|
39
|
+
end
|
40
|
+
|
41
|
+
def delayed
|
42
|
+
_delayed.length
|
43
|
+
end
|
44
|
+
|
45
|
+
def future(start, finish)
|
46
|
+
_delayed.find_all{|x| x.time >= start+tnow && x.time < finish+tnow}
|
47
|
+
end
|
48
|
+
|
49
|
+
def queue_time
|
50
|
+
return 0 unless current.empty?
|
51
|
+
return nil if (d = _delayed).empty? #tricky assignment in conditional
|
52
|
+
d.first.time - tnow
|
53
|
+
end
|
54
|
+
|
55
|
+
def lock_next(worker)
|
56
|
+
job = current.first
|
57
|
+
job.lock(worker) if job
|
58
|
+
job
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear_locks(worker)
|
62
|
+
storage.values.each{|x| x.lock_name = nil if x.lock_name == worker.name}
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def clear_all
|
67
|
+
@storage = {}
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup(options)
|
71
|
+
@storage = {}
|
72
|
+
end
|
73
|
+
|
74
|
+
def for(target, finder, finder_args, name=nil)
|
75
|
+
@storage.values.find_all do |x|
|
76
|
+
naming = name ? x.name == name : true
|
77
|
+
naming && x.finder == finder && x.finder_args == finder_args && x.target == target && !x.lock_name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def storage
|
82
|
+
@storage ||= {}
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
def tnow
|
87
|
+
Updater::Update.time.now.to_i
|
88
|
+
end
|
89
|
+
end #class << self
|
90
|
+
|
91
|
+
attr_reader :id
|
92
|
+
|
93
|
+
attr_accessor :time, :target, :finder, :finder_args, :method, :method_args, :name, :lock_name, :persistant
|
94
|
+
|
95
|
+
def initialize(hash = {})
|
96
|
+
@id = self.class.index
|
97
|
+
hash.each do |k,v|
|
98
|
+
self.send("#{k}=",v)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def lock(worker)
|
103
|
+
return false if @lock_name && @lock_name != worker.name
|
104
|
+
@lock_name = worker.name
|
105
|
+
end
|
106
|
+
|
107
|
+
def save
|
108
|
+
self.class.storage[id] = self
|
109
|
+
end
|
110
|
+
|
111
|
+
def destroy
|
112
|
+
self.class.storage.delete(id)
|
113
|
+
end
|
114
|
+
|
115
|
+
%w{failure success ensure}.each do |mode|
|
116
|
+
eval(<<-EOF, binding ,__FILE__, __LINE__+1)
|
117
|
+
def #{mode}
|
118
|
+
@#{mode} ||= []
|
119
|
+
end
|
120
|
+
|
121
|
+
def #{mode}=(chain)
|
122
|
+
return @#{mode} = nil if chain.nil?
|
123
|
+
@#{mode} ||= []
|
124
|
+
mchain = chain.kind_of?(Array) ? chain : [chain]
|
125
|
+
@#{mode} += mchain.map { |x| rationalize_instance(x) }.flatten
|
126
|
+
# attach_intellegent_insertion(@#{mode},:#{mode},self) if @#{mode}
|
127
|
+
chain
|
128
|
+
end
|
129
|
+
EOF
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def rationalize_instance(val)
|
135
|
+
case val
|
136
|
+
when Updater::Update
|
137
|
+
val
|
138
|
+
when self.class
|
139
|
+
Updater::Update.new(val)
|
140
|
+
when Integer
|
141
|
+
Updater::Update.new(self.class.storage[val])
|
142
|
+
when Hash
|
143
|
+
val.map do |target, params|
|
144
|
+
rationalize_instance(target).tap{|u| u.params = params}
|
145
|
+
end
|
146
|
+
when Array #an array within an array
|
147
|
+
rationalize_instance(val[0]).tap {|u| u.params = val[1]}
|
148
|
+
else
|
149
|
+
raise ArgumentError, "Cannot add #{val.inspect} to a chain (%s:%s)" % [__FILE__,__LINE__]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/lib/updater/orm/mongo.rb
CHANGED
@@ -71,7 +71,16 @@ module Updater
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def lock(worker)
|
74
|
-
|
74
|
+
return true if @lock_name && @lock_name == worker.name
|
75
|
+
hash = Hash.new
|
76
|
+
hash['findandmodify'] = self.class.collection.name
|
77
|
+
hash['query'] = {:_id=>id,:lock_name=>nil}
|
78
|
+
hash['update'] = {'$set'=>{:lock_name=>worker.name}}
|
79
|
+
hash['new'] = true
|
80
|
+
|
81
|
+
ret = self.class.db.command hash, :check_response=>false
|
82
|
+
@lock_name = worker.name if ret['ok'] == 1
|
83
|
+
return ret['ok'] == 1
|
75
84
|
end
|
76
85
|
|
77
86
|
# Non API Standard. This method returns the collection used by this instance.
|
@@ -97,23 +106,32 @@ module Updater
|
|
97
106
|
end
|
98
107
|
|
99
108
|
def #{mode}=(chain)
|
100
|
-
|
101
|
-
|
109
|
+
return @#{mode} = @hash[:#{mode}] = nil if chain.nil?
|
110
|
+
mchain = chain.kind_of?(Array) ? chain : [chain]
|
111
|
+
inst, hsh = build_chain_arrays(mchain)
|
112
|
+
@#{mode} = (@#{mode} || [] ) + inst if inst
|
113
|
+
@hash[:#{mode}] = (@hash[:#{mode}] || []) + hsh
|
102
114
|
attach_intellegent_insertion(@#{mode},:#{mode},self) if @#{mode}
|
115
|
+
chain
|
103
116
|
end
|
104
117
|
EOF
|
105
118
|
end
|
106
119
|
|
120
|
+
def ==(other)
|
121
|
+
other.class == self.class && id == other.id
|
122
|
+
end
|
123
|
+
|
107
124
|
private
|
108
|
-
#
|
125
|
+
# This method is calleppd from he chain asignment methods eg. failure=(chain)
|
109
126
|
# 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
|
127
|
+
# For BSON::ObjectId's we cannot initialize them as this could lead to infinate loops.
|
111
128
|
# (an object pool would solve this problem, but feels like overkill)
|
112
129
|
# The final result must be a @hash containing all the BSON::ObjectId' (forign keys)
|
113
130
|
# and possibly @failure containting all instanciated UpdaterUpdates read to be called
|
114
131
|
# or @failure set to nil with the chain instanciated on first use.
|
115
132
|
def build_chain_arrays(arr, build = false)
|
116
|
-
|
133
|
+
arr = arr[0].to_a if arr[0].is_a? Hash
|
134
|
+
build ||= arr.any? {|j| k,_ = j; Updater::Update === k || self.class === k}
|
117
135
|
output = arr.inject({:ids=>[],:instances=>[]}) do |accl,j|
|
118
136
|
inst, id = rationalize_instance(j)
|
119
137
|
if inst.nil? && build
|
@@ -134,7 +152,7 @@ module Updater
|
|
134
152
|
# This method takes something that may be a reference to an instance(BSON::ObjectId/String),
|
135
153
|
# an instance its self (Updater::Update), or a Hash
|
136
154
|
# and returns a touple of the Updater::Update,BSON::ObjectId.
|
137
|
-
# This method will
|
155
|
+
# This method will not instanciate object from BSON::ObjectId's
|
138
156
|
# nor will it save Hashes inorder to obtain an ID (it will creat a new Updater::Update from the hash).
|
139
157
|
# Instead it will return nil in the appropriate place.
|
140
158
|
def rationalize_instance(val)
|
@@ -142,8 +160,10 @@ module Updater
|
|
142
160
|
case val #aval is the actual runable object, hval is a BSON::ObjectId that we can put into the Database
|
143
161
|
when Updater::Update
|
144
162
|
val.params ? [val,[val.id,val.params]] : [val,val.id]
|
145
|
-
when Hash
|
146
|
-
[Updater::Update.new(val),val['_id']]
|
163
|
+
#~ when Hash # I think this ought to be deleted outright, but I whant to pass the functional test before I delete it.
|
164
|
+
#~ [Updater::Update.new(val),val['_id']]
|
165
|
+
when self.class
|
166
|
+
[Updater::Update.new(val), val.id]
|
147
167
|
when BSON::ObjectId
|
148
168
|
[nil,val]
|
149
169
|
when Array
|
@@ -228,11 +248,15 @@ module Updater
|
|
228
248
|
|
229
249
|
def get(id)
|
230
250
|
id = BSON::ObjectId.from_string(id) if id.kind_of? String
|
231
|
-
|
251
|
+
inst = @collection.find_one(id)
|
252
|
+
inst && new(inst)
|
232
253
|
end
|
233
254
|
|
234
255
|
def current
|
235
|
-
raise NotImplementedError, "Mongo does not support lazy evaluation"
|
256
|
+
# raise NotImplementedError, "Mongo does not support lazy evaluation"
|
257
|
+
@collection.find(:time=>{'$lte'=>tnow}).map do |x|
|
258
|
+
new(x)
|
259
|
+
end
|
236
260
|
end
|
237
261
|
|
238
262
|
def current_load
|
@@ -268,12 +292,23 @@ module Updater
|
|
268
292
|
@collection.update({:lock_name=>worker.name},{'$unset'=>{:lock_name=>1}},:multi=>true)
|
269
293
|
end
|
270
294
|
|
271
|
-
def for(target,finder,args,name)
|
295
|
+
def for(target,finder,args,name=nil)
|
272
296
|
if name
|
273
|
-
@collection.find(
|
297
|
+
@collection.find(
|
298
|
+
:target=>target.to_s,
|
299
|
+
:finder_args=>args,
|
300
|
+
:finder=>finder,
|
301
|
+
:lock_name=>nil,
|
302
|
+
:name=>name
|
303
|
+
)
|
274
304
|
else
|
275
|
-
@collection.find(
|
276
|
-
|
305
|
+
@collection.find(
|
306
|
+
:target=>target.to_s,
|
307
|
+
:finder_args=>args,
|
308
|
+
:finder=>finder,
|
309
|
+
:lock_name=>nil,
|
310
|
+
)
|
311
|
+
end.map {|x| new(x) }
|
277
312
|
end
|
278
313
|
|
279
314
|
private
|
data/lib/updater/orm/orm.rb
CHANGED
@@ -30,7 +30,7 @@ module Updater
|
|
30
30
|
# always in reference to Updater::Update.time (by default Time). This value will be
|
31
31
|
# nil for chained methods.
|
32
32
|
#
|
33
|
-
# target [Class]: The class of the target for this job.
|
33
|
+
# target [Class]: The class of the target for this job. The API spesifies that it must be
|
34
34
|
# a Ruby class currently in scope in both the workers' and clients' frames of reference.
|
35
35
|
# (see configuration documentation for how to achieve this.) The writer must accept an
|
36
36
|
# actual class, which it may store in the datastore as a string (by calling to_s on it). The
|
@@ -232,6 +232,8 @@ module Updater
|
|
232
232
|
end
|
233
233
|
|
234
234
|
def after_fork
|
235
|
+
|
236
|
+
end
|
235
237
|
|
236
238
|
# Optional, but strongly recomended.
|
237
239
|
#
|
data/lib/updater/setup.rb
CHANGED
@@ -6,6 +6,7 @@ require 'erb'
|
|
6
6
|
module Updater
|
7
7
|
class Setup
|
8
8
|
class << self
|
9
|
+
attr_accessor :init
|
9
10
|
#start a new server
|
10
11
|
def start(options={})
|
11
12
|
new(config_file(options), options).start
|
@@ -27,6 +28,10 @@ module Updater
|
|
27
28
|
new(config_file(options), options).client_setup
|
28
29
|
end
|
29
30
|
|
31
|
+
def test_setup(options = {})
|
32
|
+
new(options).test_setup
|
33
|
+
end
|
34
|
+
|
30
35
|
# pendeing
|
31
36
|
def monitor
|
32
37
|
|
@@ -83,14 +88,14 @@ module Updater
|
|
83
88
|
end
|
84
89
|
|
85
90
|
# The client is responcible for loading classes and making connections. We will simply setup the Updater spesifics.
|
86
|
-
def client_setup
|
87
|
-
@logger.info "Updater Client is being initialized..."
|
91
|
+
def client_setup(init = true)
|
92
|
+
@logger.info "Updater Client is being initialized... (#{__FILE__}:#{__LINE__})"
|
93
|
+
@logger.debug " Call Stack:\n - #{caller[0..3].join("\n - ")}"
|
88
94
|
set_orm
|
89
95
|
|
90
96
|
Updater::Update.socket = socket_for_client
|
91
97
|
|
92
|
-
|
93
|
-
init_orm
|
98
|
+
init_orm if init
|
94
99
|
|
95
100
|
#set PID
|
96
101
|
if File.exists? @options[:pid_file]
|
@@ -101,6 +106,16 @@ module Updater
|
|
101
106
|
self
|
102
107
|
end
|
103
108
|
|
109
|
+
def test_setup
|
110
|
+
@options[:orm] ||= 'mock'
|
111
|
+
set_orm
|
112
|
+
init_orm
|
113
|
+
|
114
|
+
Updater::Update.socket = @options[:socket] ||= File.open('/dev/null','w')
|
115
|
+
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
104
119
|
def socket_for_client
|
105
120
|
if @options[:socket] && File.exists?(@options[:socket])
|
106
121
|
@logger.debug "Using UNIX Socket \"#{@options[:socket]}\""
|
@@ -145,13 +160,15 @@ module Updater
|
|
145
160
|
require 'updater/orm/activerecord'
|
146
161
|
Updater::Update.orm = ORM::ActiveRecord
|
147
162
|
else
|
148
|
-
require "
|
149
|
-
Updater::Update.orm =
|
163
|
+
require "updater/orm/#{orm}"
|
164
|
+
Updater::Update.orm = Updater::ORM.const_get(orm.capitalize)
|
150
165
|
end
|
151
166
|
@logger.info "Data store '#{orm}' selected"
|
152
167
|
end
|
153
168
|
|
154
169
|
def init_orm
|
170
|
+
return false if self.class.init
|
171
|
+
self.class.init = true
|
155
172
|
default_options = {:adapter=>'sqlite3', :database=>'./default.db'}
|
156
173
|
Updater::Update.orm.setup((@options[:database] || @options[:orm_setup] || default_options).merge(:logger=>@logger))
|
157
174
|
end
|
@@ -206,7 +223,7 @@ module Updater
|
|
206
223
|
#Log PID
|
207
224
|
File.open(@options[:pid_file],'w') { |f| f.write(Process.pid.to_s)}
|
208
225
|
|
209
|
-
client_setup
|
226
|
+
client_setup(false)
|
210
227
|
|
211
228
|
#start Worker
|
212
229
|
worker = @options[:worker] || 'fork' #todo make this line windows safe
|
@@ -9,6 +9,7 @@ module Updater
|
|
9
9
|
class ThreadWorker
|
10
10
|
attr_accessor :pid
|
11
11
|
attr_accessor :name
|
12
|
+
attr_accessor :logger
|
12
13
|
|
13
14
|
def initialize(options={})
|
14
15
|
@quiet = options[:quiet]
|
@@ -53,6 +54,10 @@ module Updater
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
57
|
+
def logger
|
58
|
+
@logger ||= Logger.new(nil)
|
59
|
+
end
|
60
|
+
|
56
61
|
private
|
57
62
|
|
58
63
|
def run_job_loop
|
data/lib/updater/update.rb
CHANGED
@@ -53,14 +53,17 @@ module Updater
|
|
53
53
|
# (or the recreation of an object) on EACH invocation. Methods that need to refer to the target more then once should
|
54
54
|
# take care to store this value locally after initial retreavel.
|
55
55
|
def target
|
56
|
-
target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder
|
56
|
+
target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,*@orm.finder_args)
|
57
57
|
raise TargetMissingError, "Target missing --Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'" unless target
|
58
58
|
target
|
59
59
|
end
|
60
60
|
|
61
61
|
# orm_inst must be set to an instacne of the class Update.orm
|
62
62
|
def initialize(orm_inst)
|
63
|
-
|
63
|
+
if orm_inst.nil? || !orm_inst.kind_of?(self.class.orm)
|
64
|
+
raise ArgumentError,
|
65
|
+
"Update has been set to use %s but recieved a %s (%s:%s)\n recieved %s." % [self.class.orm.inspect, orm_inst.class.inspect, __FILE__,__LINE__-1,orm_inst.inspect]
|
66
|
+
end
|
64
67
|
@orm = orm_inst
|
65
68
|
end
|
66
69
|
|
@@ -80,7 +83,7 @@ module Updater
|
|
80
83
|
end
|
81
84
|
|
82
85
|
def ==(other)
|
83
|
-
id
|
86
|
+
other.kind_of?(self.class) && id == other.id
|
84
87
|
end
|
85
88
|
|
86
89
|
# If this is true, the job will NOT be removed after it is run. This is usually true for chained Jobs.
|
@@ -172,7 +175,7 @@ module Updater
|
|
172
175
|
#
|
173
176
|
# MongoDB is one significant exception to this rule. The Updater Mongo ORM layer uses the
|
174
177
|
# 10gen MongoDB dirver directly without an ORM such as Mongoid or Mongo_Mapper. If the
|
175
|
-
# application uses
|
178
|
+
# application uses one of thes ORMs #finder_method and #finder_id should be explicitly set.
|
176
179
|
attr_accessor :finder_method
|
177
180
|
|
178
181
|
# This is the application level default method to call on an instance type target. It should
|
@@ -480,7 +483,7 @@ module Updater
|
|
480
483
|
|
481
484
|
# Given some instance return the information needed to recreate that target
|
482
485
|
def target_for(inst,options = {})
|
483
|
-
return [inst,
|
486
|
+
return [inst, options[:finder], options[:finder_args]] if (inst.kind_of?(Class) || inst.kind_of?(Module))
|
484
487
|
[ inst.class, #target's class
|
485
488
|
options[:finder] || @finder_method || orm::FINDER, #method to call on targets class to find/create target
|
486
489
|
options[:finder_args] || inst.send(@finder_id || orm::ID) #value to pass to above method
|
data/spec/chained_spec.rb
CHANGED
@@ -8,15 +8,16 @@ describe "Chained Methods:" do
|
|
8
8
|
|
9
9
|
before :each do
|
10
10
|
Update.clear_all
|
11
|
-
Foo.
|
11
|
+
Foo.reset
|
12
12
|
@u = Update.chain(Foo,:chained,[:__job__,:__params__])
|
13
13
|
@v = Update.chain(Foo,:chained2,[:__job__,:__params__])
|
14
|
+
#pending "Chained Worker not implimented in datamapper, Waiting form ORM code refactor"
|
14
15
|
end
|
15
16
|
|
16
17
|
[:failure, :success, :ensure].each do |mode|
|
17
18
|
specify "adding '#{mode.to_s}' chain" do
|
18
19
|
v = Update.immidiate(Foo,:method1,[],mode=>@u)
|
19
|
-
v.
|
20
|
+
v.send(mode).should_not be_empty
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|