message 0.0.3 → 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.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Message
2
2
 
3
- https://travis-ci.org/xli/message.svg?branch=master
3
+ [![Build Status](https://travis-ci.org/xli/message.svg?branch=master)](https://travis-ci.org/xli/message)
4
+
4
5
 
5
6
  Message provides flexible & reliable background/asynchronous job processing mechanism on top of simple queue interface.
6
7
 
@@ -22,7 +23,7 @@ and you can easily swap in other queues later.
22
23
  ### Queuing jobs
23
24
 
24
25
 
25
- Inspired by delayed_job API, call .async.method(params) on any object and it will be processed in the background.
26
+ Call .async.method(params) on any object and it will be processed in the background.
26
27
 
27
28
  # without message
28
29
  @img.resize(36)
@@ -30,10 +31,22 @@ Inspired by delayed_job API, call .async.method(params) on any object and it wil
30
31
  # with message
31
32
  @img.async.resize(36)
32
33
 
33
- ### Start worker to process jobs
34
+ The above .async call will enqueue the job to a default job queue (Message.worker.default_job)
35
+
36
+ ### Start worker to process default job queue
34
37
 
35
38
  Message.worker.start
36
39
 
40
+ ### Named job queue
41
+
42
+ Queuing jobs into speicific queue named 'image-resize-queue':
43
+
44
+ @img.async('image-resize-queue').resize(36)
45
+
46
+ Start a worker to process queued jobs:
47
+
48
+ Message.worker('image-resize-queue').start
49
+
37
50
  ### Change to synchronize mode
38
51
 
39
52
  Message.worker.sync = true
@@ -48,93 +61,9 @@ For some environment or queue system (e.g. AWS SQS), you will need set an applic
48
61
 
49
62
  Message.worker.default_job = "app-name-#{Rails.env}-message-default"
50
63
 
51
- ## Job interface specification
52
-
53
- Job = a queue + message processor
54
-
55
- ### initialize a job
56
-
57
- job = Message.job('name') { |msg| ... process msg ... }
58
-
59
- ### enq(msg), alias: <<
60
-
61
- Queue up a message for processing:
62
-
63
- job << msg
64
-
65
- ### process(size=1)
66
-
67
- Process a message in queue by processor defined when initializing the job
68
-
69
- job.process
70
-
71
- Process multiple messages
72
-
73
- job.process(5)
74
-
75
- ## Job filters
76
-
77
- You can add job filter to add additional functions to enqueue and process job message
78
-
79
- Message.job.filter(filter_name) do |next_filter, job|
80
- lambda do |*args, &block|
81
- next_filter.call(*args, &block)
82
- end
83
- end
64
+ ### Change backend queue system
84
65
 
85
- Filters will be applied as the order initialized.
86
- Checkout all filters:
87
-
88
- Message.job.filters
89
-
90
- ### enq filter
91
-
92
- Message.job.filter(:enq) do |filter, job|
93
- lambda do |work|
94
- filter.call(work)
95
- end
96
- end
97
-
98
- ### process filter
99
-
100
- Message.job.filter(:process) do |filter, job|
101
- lambda do |size, &processor|
102
- filter.call(size) do |msg|
103
- processor.call(msg)
104
- end
105
- end
106
- end
107
-
108
- ## Queue adapters
109
-
110
- Change queue adapter to change different queue implementation. Default is a in memory queue for testing and development environments.
111
-
112
- ### Change adapter
66
+ By change queue adapter:
113
67
 
114
68
  Message.queue.adapter = :sqs
115
69
 
116
- ### Add a new adapter
117
-
118
- Message.queue.adapters[:sqs] = Message::SqsQueue
119
-
120
- ## Queue interface specification
121
-
122
- To hook up a new queue into Message.
123
-
124
- ### name
125
-
126
- Queue name.
127
-
128
- ### enq(msg), alias: <<
129
-
130
- Enqueue message, non-blocking.
131
-
132
- ### deq(size, &block)
133
-
134
- Dequeue message, non-blocking.
135
- It is up to Queue implementation when to delete the message in queue when deq got called with a block.
136
-
137
- ### size
138
-
139
- (Approximate) queue size.
140
-
@@ -0,0 +1,20 @@
1
+ require 'benchmark'
2
+ module Message
3
+ class Filters
4
+ class Benchmarking
5
+ def call(filter, job, action)
6
+ lambda do |msg|
7
+ return filter.call(msg) unless action == :process
8
+
9
+ ret = nil
10
+ Message.logger.info { "#{job.name}: processing one message"}
11
+ s = Benchmark.realtime do
12
+ ret = filter.call(msg)
13
+ end
14
+ Message.logger.info { "#{job.name}: processed in #{(1000 * s).to_i}ms" }
15
+ ret
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module Message
2
+ class Filters
3
+ class ErrorHandling
4
+ attr_accessor :callback
5
+
6
+ def call(filter, job, action)
7
+ lambda do |msg|
8
+ begin
9
+ filter.call(msg)
10
+ rescue => e
11
+ job_name = job.name rescue 'unknown job(find job name failed)'
12
+ Message.logger.error {"#{action} #{job_name} message failed, #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"}
13
+ if self.callback
14
+ self.callback.call(e, msg, job, action)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module Message
2
+ class Filters
3
+ class RetryOnError
4
+ attr_accessor :tries, :on, :sleep
5
+ def initialize
6
+ @tries = 3
7
+ @on = StandardError
8
+ @sleep = 0.001
9
+ end
10
+
11
+ def call(filter, _, _)
12
+ lambda do |arg|
13
+ @try = 0
14
+ begin
15
+ filter.call(arg)
16
+ rescue self.on => e
17
+ @try += 1
18
+ if @try < self.tries
19
+ Kernel.sleep self.sleep.to_f
20
+ retry
21
+ end
22
+ raise
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,66 +1,37 @@
1
- require 'benchmark'
1
+ require 'message/filters/error_handling'
2
+ require 'message/filters/benchmarking'
3
+ require 'message/filters/retry_on_error'
2
4
 
3
5
  module Message
4
6
  class Filters
5
- attr_reader :config
7
+ include Enumerable
8
+
9
+ attr_accessor :error_handling, :benchmarking, :retry_on_error
6
10
 
7
11
  def initialize
8
- @data = Hash.new{|h,k|h[k]=[]}
9
- @config = {
10
- :error_handling_callback => lambda {|type, job, msg, e| }
11
- }
12
- defaults.each do |t, m|
13
- self[t] << [m, method(m)]
14
- end
12
+ @data = []
13
+ @error_handling = ErrorHandling.new
14
+ @benchmarking = Benchmarking.new
15
+ @retry_on_error = RetryOnError.new
16
+ load(defaults)
15
17
  end
16
18
 
17
- def [](type)
18
- @data[type]
19
+ def <<(filter)
20
+ @data << filter
19
21
  end
20
22
 
21
- def defaults
22
- [
23
- [:process, :error_handling],
24
- [:enq, :error_handling],
25
- [:process, :benchmarking]
26
- ]
27
- end
28
-
29
- def error_handling(filter, job)
30
- lambda do |arg, &processor|
31
- type = processor ? :process : :enq
32
- log_error(type, job, (type == :enq ? arg : nil)) do
33
- if processor
34
- filter.call(arg) do |msg|
35
- log_error(type, job, msg) { processor.call(msg) }
36
- end
37
- else
38
- filter.call(arg)
39
- end
40
- end
23
+ def load(data)
24
+ data.each do |m|
25
+ @data << [m, send(m)]
41
26
  end
42
27
  end
43
28
 
44
- def benchmarking(filter, job)
45
- lambda do |size, &processor|
46
- filter.call(size) do |msg|
47
- ret = nil
48
- Message.logger.info { "#{job.name}: processing one message"}
49
- s = Benchmark.realtime do
50
- ret = processor.call(msg)
51
- end
52
- Message.logger.info { "#{job.name}: processed in #{(1000 * s).to_i}ms" }
53
- ret
54
- end
55
- end
29
+ def defaults
30
+ [:error_handling, :benchmarking, :retry_on_error]
56
31
  end
57
32
 
58
- private
59
- def log_error(type, job, msg, &block)
60
- block.call
61
- rescue => e
62
- Message.logger.error {"#{type} #{job.name} message failed, #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"}
63
- config[:error_handling_callback].call(type, job, msg, e)
33
+ def each(&block)
34
+ @data.each(&block)
64
35
  end
65
36
  end
66
37
  end
data/lib/message/job.rb CHANGED
@@ -7,8 +7,8 @@ module Message
7
7
  @filters ||= Filters.new
8
8
  end
9
9
 
10
- def filter(type, name, &block)
11
- filters[type] << [name, block]
10
+ def filter(name, &block)
11
+ filters << [name, block]
12
12
  end
13
13
 
14
14
  def reset
@@ -30,18 +30,23 @@ module Message
30
30
  end
31
31
 
32
32
  def enq(msg)
33
- chain(:enq, @queue.method(:enq)).call(msg)
33
+ chain(:enq, lambda {|msg| @queue.enq(msg)}).call(msg)
34
34
  end
35
35
  alias :<< :enq
36
36
 
37
37
  def process(size=1)
38
- chain(:process, @queue.method(:deq)).call(size, &@processor)
38
+ deq = lambda do |size|
39
+ @queue.deq(size) do |msg|
40
+ chain(:process, @processor).call(msg)
41
+ end
42
+ end
43
+ chain(:deq, deq).call(size)
39
44
  end
40
45
 
41
46
  private
42
- def chain(type, base)
43
- Job.filters[type].reverse.inject(base) do |m, f|
44
- f[1].call(m, self)
47
+ def chain(action, base)
48
+ Job.filters.to_a.reverse.inject(base) do |m, f|
49
+ f[1].call(m, self, action)
45
50
  end
46
51
  end
47
52
  end
data/lib/message/q.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require 'message/in_memory_queue'
2
2
  module Message
3
+ class AdapterNotFoundError < StandardError
4
+ end
5
+
3
6
  module Q
4
7
  module_function
5
8
  def init(name)
@@ -15,6 +18,10 @@ module Message
15
18
  end
16
19
 
17
20
  def adapter=(name)
21
+ name = name.to_sym
22
+ unless adapters.has_key?(name)
23
+ raise AdapterNotFoundError, "Could not find adapter named #{name.inspect}"
24
+ end
18
25
  @adapter = name
19
26
  end
20
27
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: message
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-09 00:00:00.000000000 Z
12
+ date: 2014-09-13 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'Message provides flexible & reliable background/asynchronous job processing
15
15
  mechanism on top of simple queue interface.
@@ -31,6 +31,9 @@ extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
33
  - README.md
34
+ - lib/message/filters/benchmarking.rb
35
+ - lib/message/filters/error_handling.rb
36
+ - lib/message/filters/retry_on_error.rb
34
37
  - lib/message/filters.rb
35
38
  - lib/message/in_memory_queue.rb
36
39
  - lib/message/job.rb