disbatch 0.0.4
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 +27 -0
- data/README +0 -0
- data/bin/disbatchd +74 -0
- data/disbatch_specification.txt +205 -0
- data/doc/Disbatch/NoNodeError.html +128 -0
- data/doc/Disbatch/Node.html +931 -0
- data/doc/Disbatch/Plugin/Hello.html +253 -0
- data/doc/Disbatch/Plugin.html +482 -0
- data/doc/Disbatch/Plugins.html +397 -0
- data/doc/Disbatch/Queue/Task.html +1671 -0
- data/doc/Disbatch/Queue.html +1043 -0
- data/doc/Disbatch.html +602 -0
- data/doc/Mongo.html +236 -0
- data/doc/_index.html +186 -0
- data/doc/class_list.html +47 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +55 -0
- data/doc/css/style.css +322 -0
- data/doc/file.README.html +66 -0
- data/doc/file_list.html +49 -0
- data/doc/frames.html +13 -0
- data/doc/index.html +66 -0
- data/doc/js/app.js +205 -0
- data/doc/js/full_list.js +167 -0
- data/doc/js/jquery.js +16 -0
- data/doc/method_list.html +446 -0
- data/doc/top-level-namespace.html +103 -0
- data/lib/disbatch/errors.rb +6 -0
- data/lib/disbatch/node.rb +105 -0
- data/lib/disbatch/plugin/hello.rb +33 -0
- data/lib/disbatch/plugin.rb +40 -0
- data/lib/disbatch/queue/task.rb +142 -0
- data/lib/disbatch/queue.rb +101 -0
- data/lib/disbatch.rb +61 -0
- metadata +147 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
module Disbatch::Plugin
|
2
|
+
|
3
|
+
|
4
|
+
attr_reader :plugins
|
5
|
+
|
6
|
+
@plugins = {}
|
7
|
+
|
8
|
+
# Register a class as a plugin
|
9
|
+
def register(plugin)
|
10
|
+
name = plugin.to_s
|
11
|
+
|
12
|
+
return false unless plugin.respond_to?(:execute)
|
13
|
+
|
14
|
+
@plugins[name] = plugin
|
15
|
+
puts "Registered #{name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Return a plugin by name
|
19
|
+
def [](name)
|
20
|
+
@plugins[name]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Attempt to load a plugin file
|
24
|
+
def init(file)
|
25
|
+
begin
|
26
|
+
load file
|
27
|
+
puts "Loaded #{file}"
|
28
|
+
rescue
|
29
|
+
puts "Error loading #{file}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Attempt to load all plugin files in a directory
|
34
|
+
def init_all(path)
|
35
|
+
Dir[path].each { |file| init(file) }
|
36
|
+
end
|
37
|
+
|
38
|
+
extend self
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# Represents a Disbatch task
|
2
|
+
class Disbatch::Queue::Task
|
3
|
+
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
attr_reader :queue, :parameters, :id
|
7
|
+
|
8
|
+
private_class_method :new
|
9
|
+
|
10
|
+
# Create a task object
|
11
|
+
#
|
12
|
+
# @param [Disbatch::Queue] queue
|
13
|
+
# @param [Hash] parameters
|
14
|
+
# @param [String] id
|
15
|
+
def initialize(queue, parameters, id)
|
16
|
+
@queue = queue
|
17
|
+
@parameters = parameters
|
18
|
+
@id = id
|
19
|
+
end
|
20
|
+
|
21
|
+
# Take a task
|
22
|
+
#
|
23
|
+
# @param [Disbatch::Queue] queue
|
24
|
+
def self.take(queue)
|
25
|
+
doc = Mongo.try do
|
26
|
+
Disbatch.db[:tasks].find_and_modify({
|
27
|
+
:query => { :queue => queue.id, :status => -2 },
|
28
|
+
:update => { :$set => { :node => Disbatch.node.id, :status => -1, } }
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
unless doc.nil?
|
33
|
+
new(queue, doc['parameters'], doc['_id'])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create a new task
|
38
|
+
#
|
39
|
+
# @param [Disbatch::Queue queue
|
40
|
+
# @param [Hash] parameters
|
41
|
+
def self.create(queue, parameters)
|
42
|
+
id = Mongo.try do
|
43
|
+
Disbatch.db[:tasks].insert({
|
44
|
+
:queue => queue.id,
|
45
|
+
:parameters => parameters,
|
46
|
+
:ctime => Time.now,
|
47
|
+
:mtime => Time.now,
|
48
|
+
:node => -1,
|
49
|
+
:status => -2,
|
50
|
+
:stdout => '',
|
51
|
+
:stderr => '',
|
52
|
+
:log => []
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
unless id.nil?
|
57
|
+
new(queue, parameters, id)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Log a message
|
62
|
+
#
|
63
|
+
# @param [String] message
|
64
|
+
def log(message)
|
65
|
+
Disbatch.db[:tasks].update({:_id => @id}, {'$push' => {'log'=>message} })
|
66
|
+
end
|
67
|
+
|
68
|
+
# Query a task attribute
|
69
|
+
#
|
70
|
+
# @param [String] attribute
|
71
|
+
def query(attribute)
|
72
|
+
doc = Mongo.try { Disbatch.db[:tasks].find_one({:_id => @id}, { :fields => { attribute => 1 } }) }
|
73
|
+
doc.nil? ? nil : doc[attribute]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Update a task attribute
|
77
|
+
#
|
78
|
+
# @param [Symbol] attribute
|
79
|
+
# @param [Object] value
|
80
|
+
def update(attribute, value)
|
81
|
+
Disbatch.db[:tasks].update({:_id => @id}, {:$set => { attribute => value } })
|
82
|
+
end
|
83
|
+
|
84
|
+
# Query task status
|
85
|
+
def status
|
86
|
+
query('status')
|
87
|
+
end
|
88
|
+
|
89
|
+
# Set task status
|
90
|
+
#
|
91
|
+
# @param [Integer] status
|
92
|
+
def status=(status)
|
93
|
+
update(:status,status)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Query stdout
|
97
|
+
def stdout
|
98
|
+
query('stdout')
|
99
|
+
end
|
100
|
+
|
101
|
+
# Set stdout
|
102
|
+
#
|
103
|
+
# @param [String] message
|
104
|
+
def stdout=(message)
|
105
|
+
update(:stdout,message)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Query stderr
|
109
|
+
def stderr
|
110
|
+
query('stderr')
|
111
|
+
end
|
112
|
+
|
113
|
+
# Set stdout
|
114
|
+
#
|
115
|
+
# @param [String] message
|
116
|
+
def stderr=(message)
|
117
|
+
update(:stdout,message)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Fail task
|
121
|
+
def fail
|
122
|
+
self.status=-3
|
123
|
+
end
|
124
|
+
|
125
|
+
# Release task
|
126
|
+
def release
|
127
|
+
self.status=-2
|
128
|
+
end
|
129
|
+
|
130
|
+
# Conclude task
|
131
|
+
def conclude
|
132
|
+
self.status=1
|
133
|
+
end
|
134
|
+
|
135
|
+
# Execute the task
|
136
|
+
def execute!
|
137
|
+
Disbatch::Plugin[queue.plugin].execute(self)
|
138
|
+
end
|
139
|
+
|
140
|
+
alias :params :parameters
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# Represents a Disbatch queue
|
2
|
+
class Disbatch::Queue
|
3
|
+
|
4
|
+
require 'disbatch/queue/task'
|
5
|
+
|
6
|
+
attr_reader :plugin, :id
|
7
|
+
|
8
|
+
private_class_method :new
|
9
|
+
|
10
|
+
# Create a queue object
|
11
|
+
#
|
12
|
+
# @param [String] plugin
|
13
|
+
# @param [String] id
|
14
|
+
def initialize(plugin, id)
|
15
|
+
@id = id
|
16
|
+
@plugin = plugin
|
17
|
+
end
|
18
|
+
|
19
|
+
# Get an existing queue
|
20
|
+
#
|
21
|
+
# @param [String] id
|
22
|
+
def self.get(id)
|
23
|
+
doc = Mongo.try do
|
24
|
+
Disbatch.db[:queues].find_one({:_id => id})
|
25
|
+
end
|
26
|
+
|
27
|
+
unless doc.nil?
|
28
|
+
new(doc['class'], id)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get all existing queues
|
33
|
+
def self.get_all
|
34
|
+
Mongo.try do
|
35
|
+
Disbatch.db[:queues].find.map { |doc| new(doc['class'], doc['_id']) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create a new queue
|
40
|
+
#
|
41
|
+
# @param [String] plugin
|
42
|
+
# @param [Hash] opts
|
43
|
+
# @option opts [String] id
|
44
|
+
# @option opts [Integer] maxthreads
|
45
|
+
# @option opts [String] description
|
46
|
+
# @option opts [Array] nodes_pin
|
47
|
+
# @option opts [Array] nodes_ignore
|
48
|
+
def self.create(plugin, opts={})
|
49
|
+
|
50
|
+
# Throw exception if plugin doesn't exist?
|
51
|
+
|
52
|
+
id = opts[:id] || BSON::ObjectId.new.to_s
|
53
|
+
maxthreads = opts[:maxthreads] || 10
|
54
|
+
description = opts[:description] || ''
|
55
|
+
nodes_pin = opts[:nodes_pin] || []
|
56
|
+
nodes_ignore = opts[:nodes_ignore] || []
|
57
|
+
|
58
|
+
doc = Mongo.try do
|
59
|
+
Disbatch.db[:queues].insert({
|
60
|
+
:_id => id,
|
61
|
+
:class => plugin,
|
62
|
+
:maxthreads => maxthreads,
|
63
|
+
:description => description,
|
64
|
+
:nodes_pin => nodes_pin,
|
65
|
+
:nodes_ignore => nodes_ignore,
|
66
|
+
:ctime => Time.now
|
67
|
+
})
|
68
|
+
end
|
69
|
+
|
70
|
+
unless doc.nil?
|
71
|
+
new(plugin, id)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# Number of pending tasks
|
77
|
+
def length
|
78
|
+
Disbatch.db[:tasks].find({:queue => @id, :status=> -2}).count
|
79
|
+
end
|
80
|
+
|
81
|
+
# Push a new task onto the queue
|
82
|
+
def push(parameters)
|
83
|
+
Disbatch::Queue::Task.create(self, parameters)
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
# Pop a task off the queue
|
88
|
+
def pop
|
89
|
+
Disbatch::Queue::Task.take(self)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Check equality with another queue object
|
93
|
+
#
|
94
|
+
# @param[Disbatch::Queue] queue another queue to compare against
|
95
|
+
def ==(queue)
|
96
|
+
@id == queue.id
|
97
|
+
end
|
98
|
+
|
99
|
+
alias :size :length
|
100
|
+
|
101
|
+
end
|
data/lib/disbatch.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module Disbatch
|
2
|
+
|
3
|
+
# engine version
|
4
|
+
VERSION = 'rdisbatch 0.0.4'
|
5
|
+
# specification version
|
6
|
+
SPEC_VERSION = '1.9'
|
7
|
+
|
8
|
+
attr_accessor :mongo_hosts
|
9
|
+
attr_accessor :mongo_db
|
10
|
+
attr_accessor :mongo_opts
|
11
|
+
|
12
|
+
attr_accessor :node_id
|
13
|
+
|
14
|
+
require 'bson'
|
15
|
+
require 'json'
|
16
|
+
require 'mongo'
|
17
|
+
require 'socket'
|
18
|
+
|
19
|
+
require 'disbatch/node'
|
20
|
+
require 'disbatch/queue'
|
21
|
+
require 'disbatch/plugin'
|
22
|
+
|
23
|
+
@node_id = Socket.gethostname
|
24
|
+
@mongo_host = 'localhost'
|
25
|
+
@mongo_port = 27017
|
26
|
+
@mongo_db = 'disbatch'
|
27
|
+
@mongo_opts = { :pool_size => 50, :safe => 1 }
|
28
|
+
|
29
|
+
# Return and cache the MongoDB connection pool
|
30
|
+
def db
|
31
|
+
@db ||= Mongo::Connection.new(@mongo_host, @mongo_port).db(@mongo_db)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return and cache the local node object
|
35
|
+
def node
|
36
|
+
@node ||= Disbatch::Node.get(@node_id) || Disbatch::Node.create(@node_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
extend self
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
module Mongo
|
44
|
+
|
45
|
+
# Wrap a MongoDB operation for retry
|
46
|
+
#
|
47
|
+
# @param [Integer] max_retries maximum number of times to attempt to connect
|
48
|
+
# @param [Float] interval frequency of retry attempts
|
49
|
+
def self.try(max_retries=4,interval=0.5)
|
50
|
+
retries = 0
|
51
|
+
begin
|
52
|
+
yield
|
53
|
+
rescue Mongo::ConnectionFailure => ex
|
54
|
+
retries +=1
|
55
|
+
raise ex if retries > max_retries
|
56
|
+
sleep(interval)
|
57
|
+
retry
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: disbatch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.4
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matthew Berg
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-12-15 00:00:00 -05:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: bson
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: mongo
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: trollop
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: jruby-openssl
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
type: :runtime
|
70
|
+
version_requirements: *id005
|
71
|
+
description: "\t\tDisbatch is a distributed, multi-language batch processing\n\
|
72
|
+
\t\tplatform.\tThis package provides both a client library and\n\
|
73
|
+
\t\texecution node implementation.\n"
|
74
|
+
email: mberg@synacor.com
|
75
|
+
executables:
|
76
|
+
- disbatchd
|
77
|
+
extensions: []
|
78
|
+
|
79
|
+
extra_rdoc_files:
|
80
|
+
- README
|
81
|
+
- LICENSE
|
82
|
+
- disbatch_specification.txt
|
83
|
+
files:
|
84
|
+
- bin/disbatchd
|
85
|
+
- lib/disbatch.rb
|
86
|
+
- lib/disbatch/queue.rb
|
87
|
+
- lib/disbatch/node.rb
|
88
|
+
- lib/disbatch/errors.rb
|
89
|
+
- lib/disbatch/plugin.rb
|
90
|
+
- lib/disbatch/plugin/hello.rb
|
91
|
+
- lib/disbatch/queue/task.rb
|
92
|
+
- doc/class_list.html
|
93
|
+
- doc/frames.html
|
94
|
+
- doc/_index.html
|
95
|
+
- doc/top-level-namespace.html
|
96
|
+
- doc/Mongo.html
|
97
|
+
- doc/index.html
|
98
|
+
- doc/file.README.html
|
99
|
+
- doc/method_list.html
|
100
|
+
- doc/file_list.html
|
101
|
+
- doc/Disbatch.html
|
102
|
+
- doc/css/full_list.css
|
103
|
+
- doc/css/style.css
|
104
|
+
- doc/css/common.css
|
105
|
+
- doc/Disbatch/Node.html
|
106
|
+
- doc/Disbatch/Queue.html
|
107
|
+
- doc/Disbatch/Plugin.html
|
108
|
+
- doc/Disbatch/NoNodeError.html
|
109
|
+
- doc/Disbatch/Plugins.html
|
110
|
+
- doc/Disbatch/Plugin/Hello.html
|
111
|
+
- doc/Disbatch/Queue/Task.html
|
112
|
+
- doc/js/app.js
|
113
|
+
- doc/js/jquery.js
|
114
|
+
- doc/js/full_list.js
|
115
|
+
- README
|
116
|
+
- LICENSE
|
117
|
+
- disbatch_specification.txt
|
118
|
+
has_rdoc: true
|
119
|
+
homepage: http://disbatch.org/projects/disbatch-ruby
|
120
|
+
licenses: []
|
121
|
+
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: "0"
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: "0"
|
139
|
+
requirements: []
|
140
|
+
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.5.1
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: Distributed batch processing package
|
146
|
+
test_files: []
|
147
|
+
|