acts_as_executor 1.0.0.beta2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/acts_as_executor.gemspec +8 -1
  2. data/lib/acts_as_executor.rb +18 -31
  3. data/lib/acts_as_executor/common/future_task.rb +2 -2
  4. data/lib/acts_as_executor/common/instance_support_methods.rb +15 -0
  5. data/lib/acts_as_executor/executor/factory.rb +18 -22
  6. data/lib/acts_as_executor/executor/model/class_methods.rb +33 -0
  7. data/lib/acts_as_executor/executor/model/instance_methods.rb +87 -0
  8. data/lib/acts_as_executor/executor/model/instance_support_methods.rb +36 -0
  9. data/lib/acts_as_executor/task/clazz.rb +26 -0
  10. data/lib/acts_as_executor/task/model/class_methods.rb +13 -0
  11. data/lib/acts_as_executor/task/model/instance_methods.rb +64 -0
  12. data/lib/acts_as_executor/task/model/instance_support_methods.rb +32 -0
  13. data/lib/acts_as_executor/validators/class_exists_validator.rb +1 -1
  14. data/lib/acts_as_executor/validators/class_includes_validator.rb +10 -0
  15. data/lib/acts_as_executor/version.rb +1 -1
  16. data/lib/generators/{executor_generator.rb → acts_as_executor_generator.rb} +1 -5
  17. data/lib/generators/templates/migration/create_executors.rb +2 -2
  18. data/spec/acts_as_executor_spec.rb +22 -0
  19. data/spec/common/future_task_spec.rb +21 -0
  20. data/spec/common/instance_support_methods_spec.rb +25 -0
  21. data/spec/common/units_spec.rb +19 -0
  22. data/spec/executor/factory_spec.rb +31 -0
  23. data/spec/executor/model/class_methods_spec.rb +49 -0
  24. data/spec/executor/model/instance_methods_spec.rb +150 -0
  25. data/spec/executor/model/instance_support_methods_spec.rb +70 -0
  26. data/spec/spec_helper.rb +8 -0
  27. data/spec/support/blueprints.rb +20 -0
  28. data/spec/support/classes.rb +55 -0
  29. data/spec/support/custom_matchers.rb +26 -0
  30. data/spec/support/database_connection.rb +4 -0
  31. data/spec/task/clazz_spec.rb +42 -0
  32. data/spec/task/model/class_methods_spec.rb +13 -0
  33. data/spec/task/model/instance_methods_spec.rb +80 -0
  34. data/spec/task/model/instance_support_methods_spec.rb +56 -0
  35. data/spec/task/schedules_spec.rb +11 -0
  36. data/spec/validators/class_exists_validator_spec.rb +21 -0
  37. data/spec/validators/class_includes_validator_spec.rb +21 -0
  38. metadata +88 -21
  39. data/README.rdoc +0 -67
  40. data/lib/acts_as_executor/executor/kinds.rb +0 -16
  41. data/lib/acts_as_executor/executor/model/actions.rb +0 -65
  42. data/lib/acts_as_executor/executor/model/associations.rb +0 -11
  43. data/lib/acts_as_executor/executor/model/attributes.rb +0 -16
  44. data/lib/acts_as_executor/executor/model/base.rb +0 -24
  45. data/lib/acts_as_executor/executor/model/helpers.rb +0 -25
  46. data/lib/acts_as_executor/executor/model/validations.rb +0 -13
  47. data/lib/acts_as_executor/task/model/actions.rb +0 -34
  48. data/lib/acts_as_executor/task/model/associations.rb +0 -11
  49. data/lib/acts_as_executor/task/model/attributes.rb +0 -16
  50. data/lib/acts_as_executor/task/model/base.rb +0 -15
  51. data/lib/acts_as_executor/task/model/helpers.rb +0 -14
  52. data/lib/acts_as_executor/task/model/validations.rb +0 -16
  53. data/lib/generators/templates/initializer/acts_as_executor.rb +0 -4
@@ -1,67 +0,0 @@
1
- =acts_as_executor
2
- acts_as_executor seamlessly integrates Java's Executor framework with JRuby on Rails, giving an application the ability to interact with executors in a familiar Rails'eque way.
3
-
4
- ==Features
5
- * Database persisted, executor and task configurations
6
- * Create and delete both executors and tasks dynamically at runtime
7
- * Automatic management of completed tasks
8
-
9
- ==Getting Started
10
- Rails 3 Gemfile
11
- gem "acts_as_executor"
12
- Install via
13
- gem install acts_as_executor --pre
14
- # or
15
- bundle install
16
-
17
- ====Generate & Migrate
18
- rails generate executor <ModelName>
19
-
20
- e.g.
21
- rails generate executor Executor
22
- create config/initializers/acts_as_executor.rb
23
- create app/models/executor.rb
24
- create app/models/executor_task.rb
25
- create db/migrate/20110601230311_create_executors.rb
26
- rake db:migrate
27
-
28
- ====Create Executor
29
- Executor.create(:name => "cached_executor",
30
- :kind => ActsAsExecutor::Executor::Kinds::CACHED)
31
- ====Create Scheduled Executor
32
- Executor.create(:name => "scheduled_executor",
33
- :kind => ActsAsExecutor::Executor::Kinds::SCHEDULED,
34
- :size => 3)
35
- ====Create Task
36
- e = Executor.find_by_name("cached_executor")
37
- e.tasks.create(:clazz => "HelloWorldTask",
38
- :arguments => { :message => "This is my message")
39
- ====Create Scheduled Task
40
- e = Executor.find_by_name("scheduled_executor")
41
- e.tasks.create(:clazz => "HelloWorldTask",
42
- :arguments => { :message => "This is my scheduled message" },
43
- :schedule => ActsAsExecutor::Task::Schedules::FIXED_DELAY,
44
- :start => 1,
45
- :every => 5,
46
- :units => ActsAsExecutor::Common::Units::MINUTES)
47
-
48
- ====Example Task
49
- class HelloWorldTask
50
- include Java::java.lang.Runnable
51
-
52
- attr_accessor :message
53
-
54
- def run
55
- p "Hello World. " + message
56
- end
57
- end
58
-
59
- ==Notes
60
- Upon a task completing its execution on a non-scheduled executor, the task will be delete from the database. Due to the possiblity that multiple threads may be attempting to delete records simultaneously, it is recommended NOT to use SQLite as a database provider. In this scenario, database locking may occur causing records to fail deletion and thus exist for tasks that have actually completed thier execution.
61
-
62
- ==What's New in Release 1.0.0.beta2
63
- * Support for all executor types, scheduled and non-scheduled
64
- * Executors can be created and deleted at runtime
65
- * Tasks can be created and added to executors at runtime
66
- * Automatic management of completed tasks on non-scheduled executors
67
- * Custom logger can now be set via initializer
@@ -1,16 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- class Kinds
4
- CACHED = "cached"
5
- FIXED = "fixed"
6
- SINGLE = "single"
7
-
8
- SCHEDULED = "scheduled"
9
- SINGLE_SCHEDULED = "single_scheduled"
10
-
11
- ALL = [ CACHED, FIXED, SINGLE, SCHEDULED, SINGLE_SCHEDULED ]
12
- ALL_SCHEDULED = [ SCHEDULED, SINGLE_SCHEDULED ]
13
- REQUIRING_SIZE = [ FIXED, SCHEDULED ]
14
- end
15
- end
16
- end
@@ -1,65 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- module Model
4
- module Actions
5
- def self.included base
6
- base.after_find :startup, :if => :startup_now?
7
- base.after_save :startup, :if => :startup_now?
8
-
9
- base.after_destroy :shutdown, :if => :shutdown_now?
10
- end
11
-
12
- def startup
13
- ActsAsExecutor.log.debug "Executor \"" + name + "\" starting up..."
14
- self.executor = ActsAsExecutor::Executor::Factory.create kind, size
15
- ActsAsExecutor.log.info "Executor \"" + name + "\" has completed startup"
16
-
17
- tasks.all
18
- end
19
-
20
- def shutdown
21
- ActsAsExecutor.log.debug "Executor \"" + name + "\" shutting down..."
22
- begin
23
- self.executor.shutdown
24
- rescue Java::java.lang.RuntimePermission
25
- ActsAsExecutor.log.error "Executor \"" + name + "\" has experienced a RuntimePermission error"
26
- rescue Java::java.lang.SecurityException
27
- ActsAsExecutor.log.error "Executor \"" + name + "\" has experienced a SecurityException error"
28
- end
29
- ActsAsExecutor.log.info "Executor \"" + name + "\" has completed shutdown"
30
- end
31
-
32
- def execute clazz, schedule, start, every, units
33
- begin
34
- if schedulable?
35
- units = Java::java.util.concurrent.TimeUnit.value_of(units.upcase)
36
- case schedule
37
- when ActsAsExecutor::Task::Schedules::ONE_SHOT
38
- future = self.executor.schedule clazz, start, units
39
- when ActsAsExecutor::Task::Schedules::FIXED_DELAY
40
- future = self.executor.schedule_with_fixed_delay clazz, start, every, units
41
- when ActsAsExecutor::Task::Schedules::FIXED_RATE
42
- future = self.executor.schedule_at_fixed_rate clazz, start, every, units
43
- end
44
- else
45
- case clazz
46
- when Java::java.util.concurrent.Callable
47
- future = ActsAsExecutor::Common::FutureTask.new clazz
48
- when Java::java.lang.Runnable
49
- future = ActsAsExecutor::Common::FutureTask.new clazz, nil
50
- end
51
- self.executor.execute future
52
- end
53
- return future
54
- rescue Java::java.lang.NullPointerException => e
55
- ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task threw a NullPointerException. " + e.to_s
56
- rescue Java::java.lang.IllegalArgumentException => e
57
- ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task threw a IllegalArgumentException. " + e.to_s
58
- rescue Java::java.util.concurrent.RejectedExecutionException => e
59
- ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task threw a RejectedExecutionException. " + e.to_s
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,11 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- module Model
4
- module Associations
5
- def self.included base
6
- base.has_many :tasks, :class_name => base.table_name.singularize.camelize + "Task", :foreign_key => "executor_id"
7
- end
8
- end
9
- end
10
- end
11
- end
@@ -1,16 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- module Model
4
- module Attributes
5
- @@executors = Hash.new
6
-
7
- def executor
8
- @@executors[id]
9
- end
10
- def executor= executor
11
- @@executors[id] = executor
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,24 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- module Model
4
- module Base
5
- def acts_as_executor
6
- send :include, ActsAsExecutor::Executor::Model::Actions
7
- send :include, ActsAsExecutor::Executor::Model::Associations
8
- send :include, ActsAsExecutor::Executor::Model::Attributes
9
- send :include, ActsAsExecutor::Executor::Model::Helpers
10
- send :include, ActsAsExecutor::Executor::Model::Validations
11
-
12
- if ActsAsExecutor.rails_startup?
13
- all
14
- at_exit do
15
- all.each do |e|
16
- e.shutdown
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,25 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- module Model
4
- module Helpers
5
- def startup_now?
6
- if self.executor == nil && ActsAsExecutor.rails_startup?
7
- return true
8
- end
9
- return false
10
- end
11
-
12
- def shutdown_now?
13
- if self.executor != nill && ActsAsExecutor.rails_startup?
14
- return true
15
- end
16
- return false
17
- end
18
-
19
- def schedulable?
20
- ActsAsExecutor::Executor::Kinds::ALL_SCHEDULED.include? kind
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,13 +0,0 @@
1
- module ActsAsExecutor
2
- module Executor
3
- module Model
4
- module Validations
5
- def self.included base
6
- base.validates :name, :presence => true, :uniqueness => true
7
- base.validates :kind, :inclusion => { :in => ActsAsExecutor::Executor::Kinds::ALL }
8
- base.validates :size, :numericality => { :only_integer => true, :greater_than_or_equal_to => 1 }, :if => "ActsAsExecutor::Executor::Kinds::REQUIRING_SIZE.include? kind"
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,34 +0,0 @@
1
- module ActsAsExecutor
2
- module Task
3
- module Model
4
- module Actions
5
- def self.included base
6
- base.serialize :arguments, Hash
7
-
8
- base.after_find :execute, :if => :execute_now?
9
- base.after_save :execute, :if => :execute_now?
10
- end
11
-
12
- def execute
13
- begin
14
- instance = clazz.constantize.new
15
- rescue NameError
16
- ActsAsExecutor.log.error "Task creating task could not create class"
17
- end
18
-
19
- if arguments
20
- arguments.each_pair do |k, v|
21
- attribute = "#{k}="
22
- instance.send attribute, v if instance.respond_to? attribute
23
- end
24
- end
25
-
26
- self.future = executor.execute instance, schedule, start, every, units
27
- if !executor.schedulable?
28
- self.future.task = self
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,11 +0,0 @@
1
- module ActsAsExecutor
2
- module Task
3
- module Model
4
- module Associations
5
- def self.included base
6
- base.belongs_to :executor, :class_name => base.table_name.sub(/_tasks/, "").camelize
7
- end
8
- end
9
- end
10
- end
11
- end
@@ -1,16 +0,0 @@
1
- module ActsAsExecutor
2
- module Task
3
- module Model
4
- module Attributes
5
- @@futures = Hash.new
6
-
7
- def future
8
- @@futures[id]
9
- end
10
- def future= future
11
- @@futures[id] = future
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,15 +0,0 @@
1
- module ActsAsExecutor
2
- module Task
3
- module Model
4
- module Base
5
- def acts_as_executor_task
6
- send :include, ActsAsExecutor::Task::Model::Actions
7
- send :include, ActsAsExecutor::Task::Model::Associations
8
- send :include, ActsAsExecutor::Task::Model::Attributes
9
- send :include, ActsAsExecutor::Task::Model::Helpers
10
- send :include, ActsAsExecutor::Task::Model::Validations
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,14 +0,0 @@
1
- module ActsAsExecutor
2
- module Task
3
- module Model
4
- module Helpers
5
- def execute_now?
6
- if self.future == nil
7
- return true
8
- end
9
- return false
10
- end
11
- end
12
- end
13
- end
14
- end
@@ -1,16 +0,0 @@
1
- module ActsAsExecutor
2
- module Task
3
- module Model
4
- module Validations
5
- def self.included base
6
- base.validates :executor_id, :presence => true
7
- base.validates :clazz, :presence => true, :class_exists => true
8
- base.validates :schedule, :inclusion => { :in => ActsAsExecutor::Task::Schedules::ALL }, :if => "executor and executor.schedulable?"
9
- base.validates :start, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0 }, :if => "executor and executor.schedulable?"
10
- base.validates :every, :numericality => { :only_integer => true, :greater_than_or_equal_to => 1 }, :if => "executor and executor.schedulable? and schedule != ActsAsExecutor::Task::Schedules::ONE_SHOT"
11
- base.validates :units, :inclusion => { :in => ActsAsExecutor::Common::Units::ALL }, :if => "executor and executor.schedulable?"
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,4 +0,0 @@
1
- ActsAsExecutor.configure do |config|
2
- # Default = Rails.logger
3
- # config.logger = Log4r::Logger["ActsAsExecutor"]
4
- end