updater 0.9.4 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|