gongren 0.1.0 → 0.1.1
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/README.rdoc +2 -0
- data/Rakefile +20 -0
- data/examples/clock/consumer.rb +14 -0
- data/examples/clock/producer.rb +17 -0
- data/examples/faster_clock/consumer.rb +15 -0
- data/examples/faster_clock/producer.rb +17 -0
- data/lib/gongren.rb +1 -1
- data/lib/gongren/server.rb +27 -26
- data/lib/gongren/worker.rb +8 -6
- metadata +6 -2
data/README.rdoc
CHANGED
@@ -4,6 +4,8 @@ Gongren distributes jobs to workers, with support for failed worker daemons and
|
|
4
4
|
|
5
5
|
Gongren is Chinese worker: 工人. See http://www.ehow.com/video_4403851_say-worker-chinese.html for pronunciation.
|
6
6
|
|
7
|
+
Gongren uses prior work by Dan DeLeo: http://github.com/danielsdeleo/qusion/
|
8
|
+
|
7
9
|
== Note on Patches/Pull Requests
|
8
10
|
|
9
11
|
* Fork the project.
|
data/Rakefile
CHANGED
@@ -80,3 +80,23 @@ rescue LoadError
|
|
80
80
|
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
namespace :version do
|
85
|
+
task :rewrite do
|
86
|
+
require "erb"
|
87
|
+
require "ostruct"
|
88
|
+
|
89
|
+
version = Rake.application.jeweler.version_helper.to_s
|
90
|
+
template = ERB.new <<-EOT.gsub(/^\s{6}/, "")
|
91
|
+
# Nothing interesting here: see {Gongren::Server} or {Gongren::Worker}.
|
92
|
+
module Gongren
|
93
|
+
VERSION = "<%= version %>"
|
94
|
+
end
|
95
|
+
EOT
|
96
|
+
File.open(File.join(Dir.pwd, "lib/gongren.rb"), "w") {|out| out.puts template.result(binding)}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
task "version:bump:patch" => "version:rewrite"
|
101
|
+
task "version:bump:minor" => "version:rewrite"
|
102
|
+
task "version:bump:major" => "version:rewrite"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
begin
|
3
|
+
require "gongren/worker"
|
4
|
+
rescue LoadError
|
5
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), "../../lib"))
|
6
|
+
raise if $LOAD_PATH.include?(path)
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(path)
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
Gongren::Worker.start do |message|
|
13
|
+
p message[:time]
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
begin
|
3
|
+
require "gongren/server"
|
4
|
+
rescue LoadError
|
5
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), "../../lib"))
|
6
|
+
raise if $LOAD_PATH.include?(path)
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(path)
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
Gongren::Server.start do |server|
|
13
|
+
# On every tick, submit an event
|
14
|
+
EM.add_periodic_timer(1) do
|
15
|
+
server.submit("tick", :time => Time.now.utc)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
begin
|
3
|
+
require "gongren/worker"
|
4
|
+
rescue LoadError
|
5
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), "../../lib"))
|
6
|
+
raise if $LOAD_PATH.include?(path)
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(path)
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
Gongren::Worker.start do |message|
|
13
|
+
p message[:time]
|
14
|
+
sleep 1.8 # Ensure we can never catch up
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
begin
|
3
|
+
require "gongren/server"
|
4
|
+
rescue LoadError
|
5
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), "../../lib"))
|
6
|
+
raise if $LOAD_PATH.include?(path)
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(path)
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
Gongren::Server.start do |server|
|
13
|
+
# On every tick, submit an event
|
14
|
+
EM.add_periodic_timer(1) do
|
15
|
+
server.submit("tick", :time => Time.now.utc)
|
16
|
+
end
|
17
|
+
end
|
data/lib/gongren.rb
CHANGED
data/lib/gongren/server.rb
CHANGED
@@ -1,58 +1,59 @@
|
|
1
|
+
require "mq"
|
1
2
|
require "logger"
|
2
|
-
require "qusion"
|
3
3
|
|
4
4
|
module Gongren
|
5
|
-
# This version is intimately tied to Rails.
|
6
5
|
class Server
|
7
6
|
def initialize(options={})
|
8
7
|
@options = options.inject(Hash.new) {|memo, (k,v)| memo[k.to_sym] = v; memo} # #symbolize_keys
|
9
8
|
@logger = options[:logger] || Logger.new(options[:log] || STDERR)
|
10
9
|
end
|
11
10
|
|
12
|
-
# Submits a unit of work to the pool of workers.
|
13
|
-
def self.submit(name, unit)
|
14
|
-
data = Marshal.dump(unit)
|
15
|
-
topic.publish(data, :persistent => true, :key => "unit.#{name}")
|
16
|
-
end
|
17
|
-
|
18
11
|
# A quick way to instantiate a server with some options.
|
19
|
-
def self.start(options={})
|
20
|
-
new(options).start
|
12
|
+
def self.start(options={}, &block)
|
13
|
+
new(options).start(&block)
|
21
14
|
end
|
22
15
|
|
23
|
-
# Starts the reactor / event loop.
|
16
|
+
# Starts the reactor / event loop. This method never returns.
|
17
|
+
# Must pass a block to yield to, enabling you to do useful work.
|
18
|
+
# The block must return a 2 element Array:
|
19
|
+
# <tt>["name of work unit", object]</tt>
|
20
|
+
#
|
21
|
+
# You must provide a block to which an instance of Gongren::Server will be yielded.
|
24
22
|
def start
|
25
|
-
logger.info { "Gongren::Server #{Process.pid} starting" }
|
26
|
-
|
27
|
-
|
23
|
+
logger.info { "Gongren::Server #{Process.pid} starting with options: #{options.inspect}" }
|
24
|
+
|
25
|
+
AMQP.start(options) do
|
26
|
+
@units = MQ.topic(exchange_name, exchange_options)
|
27
|
+
@control = MQ.topic(control_exchange_name, control_exchange_options)
|
28
|
+
|
29
|
+
yield self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def submit(name, message)
|
34
|
+
logger.debug { "Submitting #{name.inspect}: #{message.inspect}" }
|
35
|
+
data = Marshal.dump(message)
|
36
|
+
@units.publish(data, :persistent => true, :key => "unit.#{name}")
|
28
37
|
end
|
29
38
|
|
30
39
|
private
|
31
40
|
|
32
41
|
attr_reader :options, :logger
|
33
42
|
|
34
|
-
def
|
43
|
+
def exchange_name
|
35
44
|
"gongren.work"
|
36
45
|
end
|
37
46
|
|
38
|
-
def
|
47
|
+
def exchange_options
|
39
48
|
{:durable => true}
|
40
49
|
end
|
41
50
|
|
42
|
-
def
|
43
|
-
Qusion.channel.topic(exchange_name, exchange_options)
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.control_exchange_name
|
51
|
+
def control_exchange_name
|
47
52
|
"gongren.worker.control"
|
48
53
|
end
|
49
54
|
|
50
|
-
def
|
55
|
+
def control_exchange_options
|
51
56
|
{}
|
52
57
|
end
|
53
|
-
|
54
|
-
def self.control_topic
|
55
|
-
Qusion.channel.topic(control_exchange_name, control_exchange_options)
|
56
|
-
end
|
57
58
|
end
|
58
59
|
end
|
data/lib/gongren/worker.rb
CHANGED
@@ -39,12 +39,12 @@ module Gongren
|
|
39
39
|
@logger = options[:logger] || Logger.new(options[:log] || STDERR)
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
raise ArgumentError, "#
|
42
|
+
def start
|
43
|
+
raise ArgumentError, "#start must be called with a block" unless block_given?
|
44
44
|
|
45
45
|
logger.info { "Gongren::Worker #{worker_id} ready to work" }
|
46
46
|
|
47
|
-
|
47
|
+
AMQP.start do
|
48
48
|
MQ.queue(control_queue_name, control_queue_options).bind(control_exchange_name, control_exchange_options) do |header, data|
|
49
49
|
message = Marshal.load(data)
|
50
50
|
logger.info { message.inspect }
|
@@ -60,7 +60,7 @@ module Gongren
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
MQ.queue(queue_name, queue_options).bind(exchange_name, exchange_options).subscribe do |header, data|
|
63
|
+
MQ.queue(queue_name, queue_options).bind(exchange_name, exchange_options).subscribe(:ack => true) do |header, data|
|
64
64
|
message = Marshal.load(data)
|
65
65
|
class << message; include Unit; end # Dynamically add our #ack method
|
66
66
|
message.gongren_header = header
|
@@ -85,10 +85,12 @@ module Gongren
|
|
85
85
|
|
86
86
|
# A quick way to run a worker. Creates an instance with the options and runs the block
|
87
87
|
# whenever a message is received, passing the exact object that was sent from the server.
|
88
|
-
|
89
|
-
|
88
|
+
# Never returns.
|
89
|
+
def self.start(options={}, &block)
|
90
|
+
new(options).start(&block)
|
90
91
|
end
|
91
92
|
|
93
|
+
|
92
94
|
module Unit
|
93
95
|
attr_writer :gongren_header
|
94
96
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gongren
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Fran\xC3\xA7ois Beausoleil"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-20 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -112,3 +112,7 @@ summary: Gongren distributes jobs to workers, with support for failed worker dae
|
|
112
112
|
test_files:
|
113
113
|
- test/helper.rb
|
114
114
|
- test/test_gongren.rb
|
115
|
+
- examples/clock/consumer.rb
|
116
|
+
- examples/clock/producer.rb
|
117
|
+
- examples/faster_clock/consumer.rb
|
118
|
+
- examples/faster_clock/producer.rb
|