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 CHANGED
@@ -1 +1 @@
1
- 0.10.0
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
@@ -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
- target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,*@orm.finder_args)
57
- raise TargetMissingError, "Target missing --Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'" unless target
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
- #The time class used by Updater. See time=
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] || @finder_method || orm::FINDER, #method to call on targets class to find/create target
489
- options[:finder_args] || inst.send(@finder_id || orm::ID) #value to pass to above method
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
@@ -5,4 +5,6 @@ module Updater
5
5
  end
6
6
 
7
7
  require 'updater/update.rb'
8
- require 'updater/setup.rb'
8
+ require 'updater/setup.rb'
9
+ require 'updater/chained.rb'
10
+ require 'updater/target.rb'
@@ -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
@@ -2,8 +2,6 @@ require File.join( File.dirname(__FILE__), "spec_helper" )
2
2
 
3
3
  include Updater
4
4
 
5
- require File.join( File.dirname(__FILE__), "fooclass" )
6
-
7
5
  describe "Chained Methods:" do
8
6
 
9
7
  before :each do
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
@@ -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
- - 0
9
- version: 0.10.0
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-06 00:00:00 -08:00
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