say_when 0.1.0

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.
Files changed (42) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +1 -0
  4. data/generators/say_when_migration/say_when_migration_generator.rb +11 -0
  5. data/generators/say_when_migration/templates/migration.rb +48 -0
  6. data/lib/generators/.DS_Store +0 -0
  7. data/lib/generators/say_when/migration/migration_generator.rb +13 -0
  8. data/lib/generators/say_when/migration/templates/migration.rb +47 -0
  9. data/lib/say_when/base_job.rb +96 -0
  10. data/lib/say_when/cron_expression.rb +621 -0
  11. data/lib/say_when/processor/active_messaging.rb +22 -0
  12. data/lib/say_when/processor/base.rb +17 -0
  13. data/lib/say_when/processor/simple.rb +15 -0
  14. data/lib/say_when/scheduler.rb +129 -0
  15. data/lib/say_when/storage/active_record/acts.rb +85 -0
  16. data/lib/say_when/storage/active_record/job.rb +85 -0
  17. data/lib/say_when/storage/active_record/job_execution.rb +17 -0
  18. data/lib/say_when/storage/memory/base.rb +34 -0
  19. data/lib/say_when/storage/memory/job.rb +48 -0
  20. data/lib/say_when/storage/mongoid/job.rb +15 -0
  21. data/lib/say_when/tasks.rb +22 -0
  22. data/lib/say_when/triggers/base.rb +11 -0
  23. data/lib/say_when/triggers/cron_strategy.rb +22 -0
  24. data/lib/say_when/triggers/once_strategy.rb +30 -0
  25. data/lib/say_when/version.rb +3 -0
  26. data/lib/say_when.rb +28 -0
  27. data/lib/tasks/say_when.rake +2 -0
  28. data/say_when.gemspec +26 -0
  29. data/spec/active_record_spec_helper.rb +11 -0
  30. data/spec/db/schema.rb +36 -0
  31. data/spec/db/test.db +0 -0
  32. data/spec/mongoid_spec_helper.rb +7 -0
  33. data/spec/say_when/cron_expression_spec.rb +72 -0
  34. data/spec/say_when/scheduler_spec.rb +76 -0
  35. data/spec/say_when/storage/active_record/job_spec.rb +84 -0
  36. data/spec/say_when/storage/memory/job_spec.rb +31 -0
  37. data/spec/say_when/storage/memory/trigger_spec.rb +54 -0
  38. data/spec/say_when/storage/mongoid/trigger_spec.rb +57 -0
  39. data/spec/spec.opts +4 -0
  40. data/spec/spec_helper.rb +46 -0
  41. data/spec/support/models.rb +31 -0
  42. metadata +224 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in say_when.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,11 @@
1
+ class SayWhenMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate'
5
+ end
6
+ end
7
+
8
+ def file_name
9
+ "say_when_migration"
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ class SayWhenMigration < ActiveRecord::Migration
2
+ def self.up
3
+
4
+ create_table :say_when_jobs, :force => true do |t|
5
+
6
+ t.string :group
7
+ t.string :name
8
+
9
+ t.string :status
10
+
11
+ t.string :trigger_strategy
12
+ t.text :trigger_options
13
+
14
+ t.timestamp :last_fire_at
15
+ t.timestamp :next_fire_at
16
+
17
+ t.timestamp :start_at
18
+ t.timestamp :end_at
19
+
20
+ t.string :job_class
21
+ t.string :job_method
22
+ t.text :data
23
+
24
+ t.string :scheduled_type
25
+ t.integer :scheduled_id
26
+
27
+ t.timestamps
28
+ end
29
+
30
+ create_table :say_when_job_executions, :force => true do |t|
31
+ t.integer :job_id
32
+ t.string :status
33
+ t.text :result
34
+ t.datetime :start_at
35
+ t.datetime :end_at
36
+ end
37
+
38
+ add_index :say_when_jobs, :status
39
+ add_index :say_when_jobs, :next_fire_at
40
+ add_index :say_when_job_executions, :job_id
41
+ end
42
+
43
+
44
+ def self.down
45
+ drop_table :say_when_job_executions
46
+ drop_table :say_when_jobs
47
+ end
48
+ end
Binary file
@@ -0,0 +1,13 @@
1
+ module SayWhen
2
+ class MigrationGenerator < Rails::Generator::Base
3
+ def manifest
4
+ record do |m|
5
+ m.migration_template 'migration.rb', 'db/migrate'
6
+ end
7
+ end
8
+
9
+ def file_name
10
+ "say_when_migration"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ class SayWhenMigration < ActiveRecord::Migration
2
+ def self.up
3
+
4
+ create_table :say_when_jobs, :force => true do |t|
5
+
6
+ t.string :group
7
+ t.string :name
8
+
9
+ t.string :status
10
+
11
+ t.string :trigger_strategy
12
+ t.text :trigger_options
13
+
14
+ t.timestamp :last_fire_at
15
+ t.timestamp :next_fire_at
16
+
17
+ t.timestamp :start_at
18
+ t.timestamp :end_at
19
+
20
+ t.string :job_class
21
+ t.string :job_method
22
+ t.text :data
23
+
24
+ t.string :scheduled_type
25
+ t.integer :scheduled_id
26
+
27
+ t.timestamps
28
+ end
29
+
30
+ create_table :say_when_job_executions, :force => true do |t|
31
+ t.integer :job_id
32
+ t.string :status
33
+ t.text :result
34
+ t.datetime :start_at
35
+ t.datetime :end_at
36
+ end
37
+
38
+ add_index :say_when_jobs, :status
39
+ add_index :say_when_jobs, :next_fire_at
40
+ end
41
+
42
+ def self.down
43
+ drop_table :say_when_job_executions
44
+ drop_table :say_when_jobs
45
+ end
46
+
47
+ end
@@ -0,0 +1,96 @@
1
+ module SayWhen
2
+ module BaseJob
3
+
4
+ # ready to be run, just waiting for its turn
5
+ STATE_WAITING = 'waiting'
6
+
7
+ # has been acquired b/c it is time to be triggered
8
+ STATE_ACQUIRED = 'acquired'
9
+
10
+ # # related job for the trigger is executing
11
+ # STATE_EXECUTING = 'executing'
12
+
13
+ # "Complete" means the trigger has no remaining fire times
14
+ STATE_COMPLETE = 'complete'
15
+
16
+ # A Trigger arrives at the error state when the scheduler
17
+ # attempts to fire it, but cannot due to an error creating and executing
18
+ # its related job.
19
+ STATE_ERROR = 'error'
20
+
21
+ def lock
22
+ @_lock ||= Mutex.new
23
+ end
24
+
25
+ def trigger
26
+ @trigger ||= load_trigger
27
+ end
28
+
29
+ def fired
30
+ self.lock.synchronize {
31
+ fired = Time.now
32
+ next_fire = trigger.next_fire_at(fired) rescue nil
33
+ self.last_fire_at = fired
34
+ self.next_fire_at = next_fire
35
+
36
+ if next_fire.nil?
37
+ self.status = STATE_COMPLETE
38
+ else
39
+ self.status = STATE_WAITING
40
+ end
41
+ }
42
+ end
43
+
44
+ def release
45
+ self.lock.synchronize {
46
+ if self.status == STATE_ACQUIRED
47
+ self.status = STATE_WAITING
48
+ end
49
+ }
50
+ end
51
+
52
+ def execute
53
+ self.execute_job(data)
54
+ end
55
+
56
+ def load_trigger
57
+ strategy = trigger_strategy || :once
58
+ require "say_when/triggers/#{strategy}_strategy"
59
+ trigger_class_name = "SayWhen::Triggers::#{strategy.to_s.camelize}Strategy"
60
+ trigger_class = trigger_class_name.constantize
61
+ trigger_class.new(trigger_options)
62
+ end
63
+
64
+ def execute_job(options)
65
+ task_method = (self.job_method || 'execute').to_s
66
+ task = get_task(task_method)
67
+ task.send(task_method, options)
68
+ end
69
+
70
+ def get_task(task_method)
71
+ task = nil
72
+
73
+ if self.job_class
74
+ tc = self.job_class.constantize
75
+ if tc.respond_to?(task_method)
76
+ task = tc
77
+ else
78
+ to = tc.new
79
+ if to.respond_to?(task_method)
80
+ task = to
81
+ else
82
+ raise "Neither '#{self.job_class}' class nor instance respond to '#{task_method}'"
83
+ end
84
+ end
85
+ elsif self.scheduled
86
+ if self.scheduled.respond_to?(task_method)
87
+ task = self.scheduled
88
+ else
89
+ raise "Scheduled '#{self.scheduled.inspect}' does not respond to '#{task_method}'"
90
+ end
91
+ end
92
+ task
93
+ end
94
+
95
+ end
96
+ end