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.
@@ -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
@@ -1,4 +1,4 @@
1
1
  # Nothing interesting here: see {Gongren::Server} or {Gongren::Worker}.
2
2
  module Gongren
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.1"
4
4
  end
@@ -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
- Qusion.start(@options)
27
- self.class.control_topic # Instantiates the control topic, for later use
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 self.exchange_name
43
+ def exchange_name
35
44
  "gongren.work"
36
45
  end
37
46
 
38
- def self.exchange_options
47
+ def exchange_options
39
48
  {:durable => true}
40
49
  end
41
50
 
42
- def self.topic
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 self.control_exchange_options
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
@@ -39,12 +39,12 @@ module Gongren
39
39
  @logger = options[:logger] || Logger.new(options[:log] || STDERR)
40
40
  end
41
41
 
42
- def run
43
- raise ArgumentError, "#run must be called with a block" unless block_given?
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
- EM.run do
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
- def self.run(options={}, &block)
89
- new(options).run(&block)
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.0
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-16 00:00:00 -05:00
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