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