acts_as_executor 1.0.0.beta1
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/LICENSE +19 -0
- data/README.rdoc +50 -0
- data/lib/acts_as_executor.rb +35 -0
- data/lib/acts_as_executor/common/units.rb +15 -0
- data/lib/acts_as_executor/executor/factory.rb +18 -0
- data/lib/acts_as_executor/executor/kinds.rb +12 -0
- data/lib/acts_as_executor/executor/model/actions.rb +73 -0
- data/lib/acts_as_executor/executor/model/associations.rb +11 -0
- data/lib/acts_as_executor/executor/model/attributes.rb +16 -0
- data/lib/acts_as_executor/executor/model/base.rb +24 -0
- data/lib/acts_as_executor/executor/model/helpers.rb +11 -0
- data/lib/acts_as_executor/executor/model/validations.rb +13 -0
- data/lib/acts_as_executor/task/model/actions.rb +11 -0
- data/lib/acts_as_executor/task/model/associations.rb +11 -0
- data/lib/acts_as_executor/task/model/base.rb +13 -0
- data/lib/acts_as_executor/task/model/validations.rb +16 -0
- data/lib/acts_as_executor/task/schedules.rb +11 -0
- data/lib/acts_as_executor/validators/class_exists_validator.rb +9 -0
- data/lib/acts_as_executor/version.rb +3 -0
- data/lib/generators/executor_generator.rb +18 -0
- data/lib/generators/templates/migration/create_executors.rb +26 -0
- data/lib/generators/templates/models/executor.rb +3 -0
- data/lib/generators/templates/models/executor_task.rb +3 -0
- metadata +79 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2011 by Phil Ostler
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
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, scheduled executor and task configurations
|
6
|
+
|
7
|
+
==Getting Started
|
8
|
+
Rails 3 Gemfile
|
9
|
+
gem "acts_as_executor"
|
10
|
+
Install via
|
11
|
+
gem install acts_as_executor
|
12
|
+
# or
|
13
|
+
bundle install
|
14
|
+
|
15
|
+
====Generate & Migrate
|
16
|
+
rails generate executor <ModelName>
|
17
|
+
|
18
|
+
e.g.
|
19
|
+
rails generate executor Executor
|
20
|
+
create app/models/executor.rb
|
21
|
+
create app/models/executor_task.rb
|
22
|
+
create db/migrate/20110523205511_create_executors.rb
|
23
|
+
rake db:migrate
|
24
|
+
|
25
|
+
====Seed
|
26
|
+
e = Executor.create(:name => "background_processing",
|
27
|
+
:kind => ActsAsExecutor::Executor::Kinds::SCHEDULED,
|
28
|
+
:size => 4)
|
29
|
+
e.tasks.create(:clazz => "HelloWorldTask",
|
30
|
+
:arguments => { :message => "This is my argument message" },
|
31
|
+
:schedule => ActsAsExecutor::Task::Schedules::FIXED_DELAY,
|
32
|
+
:start => 1,
|
33
|
+
:every => 5,
|
34
|
+
:units => ActsAsExecutor::Common::Units::SECONDS)
|
35
|
+
|
36
|
+
====Example Task
|
37
|
+
class HelloWorldTask
|
38
|
+
include Java::java.lang.Runnable
|
39
|
+
|
40
|
+
attr_accessor :message
|
41
|
+
|
42
|
+
def run
|
43
|
+
p "Hello World. " + message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
==What's New in Release 1.0.0.beta1
|
48
|
+
* Automatic startup only on Rails start. e.g. rake tasks don't trigger executor startup
|
49
|
+
* Arguments can now be passed to tasks
|
50
|
+
* Logging to <tt>Rails.logger</tt>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "acts_as_executor/common/units"
|
2
|
+
|
3
|
+
require "acts_as_executor/executor/factory"
|
4
|
+
require "acts_as_executor/executor/kinds"
|
5
|
+
|
6
|
+
require "acts_as_executor/executor/model/actions"
|
7
|
+
require "acts_as_executor/executor/model/associations"
|
8
|
+
require "acts_as_executor/executor/model/attributes"
|
9
|
+
require "acts_as_executor/executor/model/base"
|
10
|
+
require "acts_as_executor/executor/model/helpers"
|
11
|
+
require "acts_as_executor/executor/model/validations"
|
12
|
+
|
13
|
+
require "acts_as_executor/task/schedules"
|
14
|
+
|
15
|
+
require "acts_as_executor/task/model/actions"
|
16
|
+
require "acts_as_executor/task/model/associations"
|
17
|
+
require "acts_as_executor/task/model/base"
|
18
|
+
require "acts_as_executor/task/model/validations"
|
19
|
+
|
20
|
+
require "acts_as_executor/validators/class_exists_validator"
|
21
|
+
|
22
|
+
ActiveRecord::Base.send :extend, ActsAsExecutor::Executor::Model::Base
|
23
|
+
ActiveRecord::Base.send :extend, ActsAsExecutor::Task::Model::Base
|
24
|
+
|
25
|
+
module ActsAsExecutor
|
26
|
+
def self.log
|
27
|
+
logger
|
28
|
+
end
|
29
|
+
def self.logger
|
30
|
+
@@logger ||= Rails.logger
|
31
|
+
end
|
32
|
+
def self.rails_startup?
|
33
|
+
File.basename($0) == "rails"
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActsAsExecutor
|
2
|
+
module Common
|
3
|
+
class Units
|
4
|
+
NANOSECONDS = "nanoseconds"
|
5
|
+
MICROSECONDS = "microseconds"
|
6
|
+
MILLISECONDS = "milliseconds"
|
7
|
+
SECONDS = "seconds"
|
8
|
+
MINUTES = "minutes"
|
9
|
+
HOURS = "hours"
|
10
|
+
DAYS = "days"
|
11
|
+
|
12
|
+
ALL = [ NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS ]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ActsAsExecutor
|
2
|
+
module Executor
|
3
|
+
class Factory
|
4
|
+
def self.create kind, size = nil
|
5
|
+
case kind
|
6
|
+
when ActsAsExecutor::Executor::Kinds::SCHEDULED
|
7
|
+
raise TypeError, "size cannot be nil" unless size
|
8
|
+
raise ArgumentError, "size must be larger than 0" unless size.to_i > 0
|
9
|
+
return Java::java.util.concurrent.Executors.new_scheduled_thread_pool size.to_i
|
10
|
+
when ActsAsExecutor::Executor::Kinds::SINGLE_SCHEDULED
|
11
|
+
return Java::java.util.concurrent.Executors.new_single_thread_scheduled_executor
|
12
|
+
else
|
13
|
+
return nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ActsAsExecutor
|
2
|
+
module Executor
|
3
|
+
class Kinds
|
4
|
+
SCHEDULED = "scheduled"
|
5
|
+
SINGLE_SCHEDULED = "single_scheduled"
|
6
|
+
|
7
|
+
ALL = [ SCHEDULED, SINGLE_SCHEDULED ]
|
8
|
+
ALL_SCHEDULED = [ SCHEDULED, SINGLE_SCHEDULED ]
|
9
|
+
REQUIRING_SIZE = [ SCHEDULED ]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module ActsAsExecutor
|
2
|
+
module Executor
|
3
|
+
module Model
|
4
|
+
module Actions
|
5
|
+
def self.included base
|
6
|
+
base.after_find :startup, :if => "ActsAsExecutor.rails_startup?"
|
7
|
+
base.after_destroy :shutdown
|
8
|
+
end
|
9
|
+
|
10
|
+
def startup
|
11
|
+
unless self.executor
|
12
|
+
ActsAsExecutor.log.debug "Executor \"" + name + "\" starting up..."
|
13
|
+
self.executor = ActsAsExecutor::Executor::Factory.create kind, size
|
14
|
+
ActsAsExecutor.log.info "Executor \"" + name + "\" has completed startup"
|
15
|
+
|
16
|
+
ActsAsExecutor.log.debug "Executor \"" + name + "\" attaching tasks..."
|
17
|
+
tasks.each do |t|
|
18
|
+
submit t
|
19
|
+
end
|
20
|
+
ActsAsExecutor.log.info "Executor \"" + name + "\" has completed attaching tasks"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def shutdown
|
25
|
+
if self.executor
|
26
|
+
ActsAsExecutor.log.debug "Executor \"" + name + "\" shutting down..."
|
27
|
+
begin
|
28
|
+
self.executor.shutdown
|
29
|
+
rescue Java::java.lang.RuntimePermission
|
30
|
+
ActsAsExecutor.log.error "Executor \"" + name + "\" has experienced a RuntimePermission error"
|
31
|
+
rescue Java::java.lang.SecurityException
|
32
|
+
ActsAsExecutor.log.error "Executor \"" + name + "\" has experienced a SecurityException error"
|
33
|
+
end
|
34
|
+
ActsAsExecutor.log.info "Executor \"" + name + "\" has completed shutdown"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def submit task
|
39
|
+
begin
|
40
|
+
clazz = task.clazz.constantize.new
|
41
|
+
rescue NameError
|
42
|
+
ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task \"" + task.clazz + "\" could not create class"
|
43
|
+
end
|
44
|
+
|
45
|
+
if task.arguments
|
46
|
+
task.arguments.each_pair do |k, v|
|
47
|
+
attribute = "#{k}="
|
48
|
+
clazz.send attribute, v if clazz.respond_to? attribute
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
units = Java::java.util.concurrent.TimeUnit.value_of(task.units.upcase)
|
54
|
+
case task.schedule
|
55
|
+
when ActsAsExecutor::Task::Schedules::ONE_SHOT
|
56
|
+
self.executor.schedule clazz, task.start, units
|
57
|
+
when ActsAsExecutor::Task::Schedules::FIXED_DELAY
|
58
|
+
self.executor.schedule_with_fixed_delay clazz, task.start, task.every, units
|
59
|
+
when ActsAsExecutor::Task::Schedules::FIXED_RATE
|
60
|
+
self.executor.schedule_at_fixed_rate clazz, task.start, task.every, units
|
61
|
+
end
|
62
|
+
rescue Java::java.lang.NullPointerException
|
63
|
+
ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task \"" + task.clazz + "\" threw a NullPointerException"
|
64
|
+
rescue Java::java.lang.IllegalArgumentException
|
65
|
+
ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task \"" + task.clazz + "\" threw a IllegalArgumentException"
|
66
|
+
rescue Java::java.util.concurrent.RejectedExecutionException
|
67
|
+
ActsAsExecutor.log.error "Executor \"" + name + "\" attaching task \"" + task.clazz + "\" threw a RejectedExecutionException"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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
|
@@ -0,0 +1,13 @@
|
|
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
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActsAsExecutor
|
2
|
+
module Task
|
3
|
+
module Model
|
4
|
+
module Base
|
5
|
+
def acts_as_executor_task
|
6
|
+
send :include, ActsAsExecutor::Task::Model::Associations
|
7
|
+
send :include, ActsAsExecutor::Task::Model::Actions
|
8
|
+
send :include, ActsAsExecutor::Task::Model::Validations
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
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
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class ExecutorGenerator < Rails::Generators::NamedBase
|
2
|
+
include Rails::Generators::Migration
|
3
|
+
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
|
6
|
+
def models
|
7
|
+
template File.join("models", "executor.rb"), File.join("app", "models", file_name + ".rb")
|
8
|
+
template File.join("models", "executor_task.rb"), File.join("app", "models", file_name + "_task.rb")
|
9
|
+
end
|
10
|
+
|
11
|
+
def migration
|
12
|
+
migration_template File.join("migration", "create_executors.rb"), File.join("db", "migrate", "create_" + table_name + ".rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.next_migration_number dirname
|
16
|
+
Time.now.utc.strftime "%Y%m%d%H%M%S"
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Create<%= class_name.pluralize %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :kind
|
6
|
+
t.integer :size
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :<%= singular_table_name %>_tasks do |t|
|
11
|
+
t.integer :executor_id
|
12
|
+
t.string :clazz
|
13
|
+
t.string :arguments
|
14
|
+
t.string :schedule
|
15
|
+
t.integer :start
|
16
|
+
t.integer :every
|
17
|
+
t.string :units
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.down
|
23
|
+
drop_table :<%= table_name %>
|
24
|
+
drop_table :<%= singular_table_name %>_tasks
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_executor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 6
|
5
|
+
version: 1.0.0.beta1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Phil Ostler
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-24 00:00:00 +01:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Seamless integration of Java's Executor framework with JRuby on Rails
|
18
|
+
email:
|
19
|
+
- philostler@gmail.com
|
20
|
+
executables: []
|
21
|
+
|
22
|
+
extensions: []
|
23
|
+
|
24
|
+
extra_rdoc_files: []
|
25
|
+
|
26
|
+
files:
|
27
|
+
- lib/acts_as_executor.rb
|
28
|
+
- lib/acts_as_executor/version.rb
|
29
|
+
- lib/acts_as_executor/common/units.rb
|
30
|
+
- lib/acts_as_executor/executor/factory.rb
|
31
|
+
- lib/acts_as_executor/executor/kinds.rb
|
32
|
+
- lib/acts_as_executor/executor/model/actions.rb
|
33
|
+
- lib/acts_as_executor/executor/model/associations.rb
|
34
|
+
- lib/acts_as_executor/executor/model/attributes.rb
|
35
|
+
- lib/acts_as_executor/executor/model/base.rb
|
36
|
+
- lib/acts_as_executor/executor/model/helpers.rb
|
37
|
+
- lib/acts_as_executor/executor/model/validations.rb
|
38
|
+
- lib/acts_as_executor/task/schedules.rb
|
39
|
+
- lib/acts_as_executor/task/model/actions.rb
|
40
|
+
- lib/acts_as_executor/task/model/associations.rb
|
41
|
+
- lib/acts_as_executor/task/model/base.rb
|
42
|
+
- lib/acts_as_executor/task/model/validations.rb
|
43
|
+
- lib/acts_as_executor/validators/class_exists_validator.rb
|
44
|
+
- lib/generators/executor_generator.rb
|
45
|
+
- lib/generators/templates/migration/create_executors.rb
|
46
|
+
- lib/generators/templates/models/executor.rb
|
47
|
+
- lib/generators/templates/models/executor_task.rb
|
48
|
+
- README.rdoc
|
49
|
+
- LICENSE
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: https://github.com/philostler/acts_as_executor
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 1.3.1
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.5.1
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Java Executor framework integration for Rails
|
78
|
+
test_files: []
|
79
|
+
|