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 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