disbatch 0.0.4

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