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.
@@ -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
+