updater 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/lib/updater/chained.rb +43 -0
- data/lib/updater/target.rb +57 -0
- data/lib/updater/update.rb +22 -14
- data/lib/updater.rb +3 -1
- data/spec/chained_class_spec.rb +40 -0
- data/spec/chained_spec.rb +0 -2
- data/spec/fooclass.rb +6 -0
- data/spec/target_spec.rb +92 -0
- metadata +7 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.10.
|
1
|
+
0.10.1
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Updater
|
2
|
+
class Chained
|
3
|
+
class << self
|
4
|
+
def jobs(name)
|
5
|
+
name = name.to_s
|
6
|
+
@jobs ||= Hash.new {|_,n| find_or_create(n)}
|
7
|
+
@jobs[name]
|
8
|
+
end
|
9
|
+
|
10
|
+
def reschedule(job,options)
|
11
|
+
new_time = options[:at] || Update.time.now + options[:in]
|
12
|
+
Update.at(
|
13
|
+
new_time,job.target,job.method,job.method_args,
|
14
|
+
:finder=>job.finder,
|
15
|
+
:finder_args=>job.finder_args,
|
16
|
+
:name=>job.name,
|
17
|
+
:success=>job.success - [jobs(:reschedule)],
|
18
|
+
:failure=>job.failure - [jobs(:reschedule)],
|
19
|
+
:ensure=>job.ensure - [jobs(:reschedule)]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def __reset
|
24
|
+
@jobs = nil
|
25
|
+
@args_for == {}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def find_or_create(name)
|
31
|
+
Update.for(self,name) || create(name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def create(name)
|
35
|
+
Update.chain(self,name,args_for[name]||[:__job__,:__params__],:name=>name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def args_for
|
39
|
+
@args_for ||= {}
|
40
|
+
end
|
41
|
+
end # class << self
|
42
|
+
end # class Chained
|
43
|
+
end # module Update
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Updater
|
2
|
+
|
3
|
+
# By including this module in a client's classes, it is possible to schedule jobs with the
|
4
|
+
# inlcuded methods. This saves typing `Updater::Update.[in|at|immidate] `repeatedly.
|
5
|
+
# The class also allows you to set special finder and ID methods on a per class basis.
|
6
|
+
module Target
|
7
|
+
def self.included(model)
|
8
|
+
model.class_eval do
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# This will overide the default finder for Update and the chosen ORM. Set
|
12
|
+
# it the symbol of a class method that can find/instantiate instances of the class.
|
13
|
+
# It will be passed the value returned from the ID method called on an
|
14
|
+
# instance. The ID method can be overridden as well. See +updater_id_method+
|
15
|
+
attr_accessor :updater_finder_method
|
16
|
+
|
17
|
+
# This will overide the ID method set in both with Update and the chosen ORM.
|
18
|
+
# Set it to the symbol of an instance method. The value of this method will be given
|
19
|
+
# to the finder method in order to recreate the instance for the worker. The finder
|
20
|
+
# method can be overridden as well. See +updater_finder_method+
|
21
|
+
attr_accessor :updater_id_method
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
# Finds all the jobs whose target is this instance. If a name is given, it will
|
29
|
+
# return only the job with that name set. There can be only one job with a
|
30
|
+
# given name per unique target. Also note that jobs that have their finder
|
31
|
+
# or finder_args set on creation cannot be named and will not be found by
|
32
|
+
# this method. See aslo Update#for
|
33
|
+
def jobs_for(name = nil)
|
34
|
+
Update.for(self, name)
|
35
|
+
end
|
36
|
+
|
37
|
+
alias job_for jobs_for
|
38
|
+
|
39
|
+
# Place a job on the queue for immidiate execution. This method is aliased
|
40
|
+
# to `send_later` for compatibility with delayed_job. See Also Update#immidiate
|
41
|
+
def enqueue(*args)
|
42
|
+
Update.immidiate(self,*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
alias send_later enqueue
|
46
|
+
|
47
|
+
#Put a job on the queue to run at a spesified time. See Also Update#at
|
48
|
+
def send_at(time, *args)
|
49
|
+
Update.at(time,self,*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
#Put a job on the queue to run after a spesified duration (in seconds). See Also Update#in
|
53
|
+
def send_in(delta_seconds,*args)
|
54
|
+
Update.in(delta_seconds,self,*args)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/updater/update.rb
CHANGED
@@ -47,14 +47,22 @@ module Updater
|
|
47
47
|
@orm.send(method,*args)
|
48
48
|
end
|
49
49
|
|
50
|
+
def method
|
51
|
+
@orm.method
|
52
|
+
end
|
53
|
+
|
50
54
|
# Determins and if necessary find/creates the target for this instance.
|
51
55
|
#
|
52
56
|
# Warning: This value is intentionally NOT memoized. For instance type targets, it will result in a call to the datastore
|
53
57
|
# (or the recreation of an object) on EACH invocation. Methods that need to refer to the target more then once should
|
54
58
|
# take care to store this value locally after initial retreavel.
|
55
59
|
def target
|
56
|
-
|
57
|
-
|
60
|
+
begin
|
61
|
+
target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,*@orm.finder_args)
|
62
|
+
raise TargetMissingError unless target
|
63
|
+
rescue
|
64
|
+
raise TargetMissingError, "Target missing --Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'"
|
65
|
+
end
|
58
66
|
target
|
59
67
|
end
|
60
68
|
|
@@ -328,14 +336,6 @@ module Updater
|
|
328
336
|
raise
|
329
337
|
end
|
330
338
|
|
331
|
-
# Create a new job having the same charistics as the old, except that 'hash' will override the original.
|
332
|
-
def reschedule(update, hash={})
|
333
|
-
new_job = update.orm.dup
|
334
|
-
new_job.update_attributes(hash)
|
335
|
-
new_job.save
|
336
|
-
new(new_job)
|
337
|
-
end
|
338
|
-
|
339
339
|
# like +at+ but with time as time.now. Generally this will be used to run a long running operation in
|
340
340
|
# asyncronously in a differen process. See +at+ for details
|
341
341
|
def immidiate(*args)
|
@@ -368,7 +368,7 @@ module Updater
|
|
368
368
|
name ? ret.first : ret
|
369
369
|
end
|
370
370
|
|
371
|
-
|
371
|
+
#The time class used by Updater. See time=
|
372
372
|
def time
|
373
373
|
@time ||= Time
|
374
374
|
end
|
@@ -485,12 +485,20 @@ module Updater
|
|
485
485
|
def target_for(inst,options = {})
|
486
486
|
return [inst, options[:finder], options[:finder_args]] if (inst.kind_of?(Class) || inst.kind_of?(Module))
|
487
487
|
[ inst.class, #target's class
|
488
|
-
options[:finder] ||
|
489
|
-
|
488
|
+
options[:finder] || #method to call on targets class to find/create target
|
489
|
+
inst.class.respond_to?(:updater_finder_method) && inst.class.updater_finder_method ||
|
490
|
+
@finder_method ||
|
491
|
+
orm::FINDER,
|
492
|
+
options[:finder_args] || #value to pass to above method #TODO add test to require flattening
|
493
|
+
[inst.send(
|
494
|
+
@finder_id ||
|
495
|
+
inst.class.respond_to?(:updater_id_method) && inst.class.updater_id_method ||
|
496
|
+
orm::ID
|
497
|
+
)]
|
490
498
|
]
|
491
499
|
end
|
492
500
|
|
493
501
|
end # class << self
|
494
502
|
end #class Update
|
495
503
|
|
496
|
-
end #Module Updater
|
504
|
+
end #Module Updater
|
data/lib/updater.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), "spec_helper" )
|
2
|
+
|
3
|
+
include Updater
|
4
|
+
|
5
|
+
describe Chained do
|
6
|
+
before :each do
|
7
|
+
Chained.__reset
|
8
|
+
Update.clear_all
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "reschedule:" do
|
12
|
+
it "should return the job from #jobs" do
|
13
|
+
reschedule = Chained.jobs(:reschedule)
|
14
|
+
reschedule.should_not be_nil
|
15
|
+
reschedule.method.should == "reschedule"
|
16
|
+
reschedule.method_args.should == [:__job__,:__params__]
|
17
|
+
reschedule.name.should == "reschedule"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not schedule this job twice" do
|
21
|
+
reschedule = Chained.jobs(:reschedule)
|
22
|
+
Update.for(Chained).should == [reschedule]
|
23
|
+
reschedule = Chained.jobs(:reschedule)
|
24
|
+
Update.for(Chained).should == [reschedule]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should add an identical job back to the queue in the time spesified" do
|
28
|
+
job = Update.immidiate(Foo,:bar,[],:name=>'testing')
|
29
|
+
job.destroy #pretend it has alread run to completion
|
30
|
+
reschedule = Chained.jobs(:reschedule)
|
31
|
+
reschedule.params = {:in=>10}
|
32
|
+
reschedule.run(job)
|
33
|
+
reschedule.error.should be_nil
|
34
|
+
new_job = Update.for(Foo, "testing")
|
35
|
+
new_job.should_not be_nil
|
36
|
+
new_job.time.should > job.time
|
37
|
+
end
|
38
|
+
end #describe "reschedule:" do
|
39
|
+
|
40
|
+
end
|
data/spec/chained_spec.rb
CHANGED
data/spec/fooclass.rb
CHANGED
@@ -17,6 +17,8 @@ class Foo
|
|
17
17
|
storage[id]
|
18
18
|
end
|
19
19
|
|
20
|
+
alias special_foo_finder find
|
21
|
+
|
20
22
|
def reset
|
21
23
|
@storage = {}
|
22
24
|
end
|
@@ -33,6 +35,10 @@ class Foo
|
|
33
35
|
Foo.bar(:instance,*args)
|
34
36
|
end
|
35
37
|
|
38
|
+
def special_foo_identification
|
39
|
+
@id
|
40
|
+
end
|
41
|
+
|
36
42
|
def self.bar(*args)
|
37
43
|
|
38
44
|
end
|
data/spec/target_spec.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), "spec_helper" )
|
2
|
+
|
3
|
+
require File.join( File.dirname(__FILE__), "fooclass" )
|
4
|
+
|
5
|
+
class Foo
|
6
|
+
include Updater::Target
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Updater::Target do
|
10
|
+
before :each do
|
11
|
+
@foo = Foo.create(:name=>"foo instance")
|
12
|
+
end
|
13
|
+
|
14
|
+
after :each do
|
15
|
+
Updater::Update.clear_all
|
16
|
+
Foo.reset
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#jobs_for" do
|
20
|
+
specify "should not initially be any jobs for the target" do
|
21
|
+
@foo.jobs_for.should be_empty
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should contian all jobs regardless of how they got scheduled" do
|
25
|
+
expected = []
|
26
|
+
expected << @foo.enqueue(:bar)
|
27
|
+
expected << @foo.send_in(600, :bar)
|
28
|
+
expected << Updater::Update.in(1200, @foo, :bar)
|
29
|
+
expected.each do |expectation|
|
30
|
+
@foo.jobs_for.should include(expectation)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should find a job by name" do
|
35
|
+
@foo.enqueue(:bar)
|
36
|
+
job = @foo.enqueue(:bar,[],:name=>"baz")
|
37
|
+
@foo.send_in(600, :bar)
|
38
|
+
Updater::Update.in(1200, @foo, :bar)
|
39
|
+
@foo.job_for("baz").should == job
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "should schedual a job for the target instance" do
|
44
|
+
|
45
|
+
specify "immidiatly with #send_later" do #compatibiltiy with delayed_job
|
46
|
+
job = @foo.send_later :bar
|
47
|
+
job.should be_a_kind_of Updater::Update
|
48
|
+
job.target.should == @foo
|
49
|
+
@foo.jobs_for.should == [job]
|
50
|
+
end
|
51
|
+
|
52
|
+
specify "immidiatly with #enqueue" do
|
53
|
+
job = @foo.enqueue :bar
|
54
|
+
job.should be_a_kind_of Updater::Update
|
55
|
+
job.target.should == @foo
|
56
|
+
@foo.jobs_for.should == [job]
|
57
|
+
end
|
58
|
+
|
59
|
+
specify "at a certian time with #send_at" do
|
60
|
+
schedule_at = Time.now + 600
|
61
|
+
job = @foo.send_at schedule_at , :bar
|
62
|
+
job.target.should == @foo
|
63
|
+
job.time.should == schedule_at.to_i
|
64
|
+
@foo.jobs_for.should == [job]
|
65
|
+
end
|
66
|
+
|
67
|
+
specify "after a certian time with #send_in" do
|
68
|
+
Timecop.freeze do
|
69
|
+
job = @foo.send_in 600 , :bar
|
70
|
+
job.target.should == @foo
|
71
|
+
job.time.should == Time.now.to_i + 600
|
72
|
+
@foo.jobs_for.should == [job]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "resetting default finder and id values: " do
|
78
|
+
specify "finder" do
|
79
|
+
Foo.updater_finder_method = :special_foo_finder
|
80
|
+
job = @foo.enqueue :bar
|
81
|
+
job.finder.should == :special_foo_finder
|
82
|
+
end
|
83
|
+
|
84
|
+
specify "id" do
|
85
|
+
Foo.updater_id_method = :special_foo_identification
|
86
|
+
@foo.should_receive(:special_foo_identification).and_return("razzle-dazzle")
|
87
|
+
job = @foo.enqueue :bar
|
88
|
+
job.finder_args.should == ["razzle-dazzle"]
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 10
|
8
|
-
-
|
9
|
-
version: 0.10.
|
8
|
+
- 1
|
9
|
+
version: 0.10.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- John F. Miller
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-03-
|
17
|
+
date: 2011-03-21 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -95,8 +95,10 @@ files:
|
|
95
95
|
- lib/updater.rb
|
96
96
|
- lib/updater/setup.rb
|
97
97
|
- lib/updater/util.rb
|
98
|
+
- lib/updater/chained.rb
|
98
99
|
- lib/updater/update.rb
|
99
100
|
- lib/updater/fork_worker.rb
|
101
|
+
- lib/updater/target.rb
|
100
102
|
- lib/updater/tasks.rb
|
101
103
|
- lib/updater/thread_worker.rb
|
102
104
|
- lib/updater/orm/orm.rb
|
@@ -121,7 +123,9 @@ files:
|
|
121
123
|
- spec/named_request_spec.rb
|
122
124
|
- spec/update_runner_spec.rb
|
123
125
|
- spec/util_spec.rb
|
126
|
+
- spec/target_spec.rb
|
124
127
|
- spec/fork_worker_spec.rb
|
128
|
+
- spec/chained_class_spec.rb
|
125
129
|
- spec/errors_spec.rb
|
126
130
|
- bin/updater
|
127
131
|
has_rdoc: true
|