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