acts_as_executor 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|