larva 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0004f08094d687c91fb380df5790dd141cae409d
4
- data.tar.gz: bf30bed9cb37627e9c7ccb6d0df30375a89b4c2a
3
+ metadata.gz: cbf84efda642aa79d413f133e1b7f27db278bec6
4
+ data.tar.gz: 88f947616c14e531fee42dc00fbd419372303bdb
5
5
  SHA512:
6
- metadata.gz: 42b25983e5579a66a6848bb4b509093bcf00a04eb9db8a9fe4d4f16a30488201677b1e82f608a9cef85431be9f7bdfb5b679d1e7c48a3fd85777bd1931e91714
7
- data.tar.gz: 9f172bd1f6a72b9f6ef642747d52b2ce3de0ad55eba6158cc24ab65588ad1c91b983b36683095f1314ea16f6f98da143b3acf77ae5eb65a65b7fa331dd36a01d
6
+ metadata.gz: e1f4c8d39c1da9883535dc5b11f152e70a53c09906b6f4e29530514aa63dccd41c1d66f0ef540182d689a806d291c1a0b5b544be7d66d496281109043acdf795
7
+ data.tar.gz: 78624d5307e979b1bab7bf2d048cb14359d46a6147f2f484d6ec5c23b0146ac5fdf28b585ade020bd83feaca2969cfc575abe6f9ae48e0a82ceada5c6697c6dd
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  Gemfile.lock
2
2
  log/
3
+ pkg/
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - rbx-2.1.1
7
+ script:
8
+ - bundle exec rake test:local
9
+ #addons:
10
+ # code_climate:
11
+ # repo_token: 88dd239bc2e0010742a42a4e0234b4decd19b46d0e9d3408d8b1fe0f96dd8fc1
12
+ matrix:
13
+ allow_failures:
14
+ - rvm: rbx-2.1.1
data/CHANGELOG CHANGED
@@ -1,2 +1,8 @@
1
+ # 0.3.0 / 2014-02-22
2
+ * [FEATURE] Add worker pool.
3
+
4
+ # 0.2.0 / 2014-02-22
5
+ * [FEATURE] Add processor.
6
+
1
7
  # 0.1.0 / 2014-02-22
2
- * [FEATURE] Initial release with listeners
8
+ * [FEATURE] Initial release with listeners.
data/README.md CHANGED
@@ -18,17 +18,76 @@ And then execute:
18
18
 
19
19
  ## Usage
20
20
 
21
+ Larva provides you with listeners, processors and a worker pool to build an application that listens and responds to Propono messages.
22
+
23
+ Here is a sample application. This forms the basis of a rake task for most Meducation daemons.
24
+
25
+ ```ruby
26
+ require 'larva'
27
+
28
+ # Setup Config for Filum and Propono
29
+
30
+ class MyProcessor < Larva::Processor
31
+ def process(message)
32
+ if entity == "comment" && action == "created"
33
+ # Do something...
34
+ else
35
+ false
36
+ end
37
+ end
38
+ end
39
+
40
+ processors = {my_topic: MyProcessor}
41
+ Larva::WorkerPool.start(processors, "queue-suffix")
42
+
43
+ ```
44
+
21
45
  ### Listeners
22
46
 
23
47
  Larva Listeners provide an easy way of listening to a Propono topic and processing the message, complete with lots of logging through Filum.
24
48
 
49
+ ```ruby
50
+ Larva::Listener.listen(:my_topic, processor, "queue_suffix")
51
+ ```
52
+
53
+ This will listen for messages on :my_topic and pass them to `processor.process`. It will log what is happening via Filum.
54
+
55
+ ### Processors
56
+
57
+ Processors are used by listeners to handle the messages that are received. You are expected to subclass `Lavar::Processor` and implement `process`.
58
+
59
+ Processors expect you to have an `entity` and `action` fields in your messages.
60
+
61
+ For example:
62
+
25
63
  ```ruby
26
64
  class MyProcessor
27
- def self.process(message)
65
+ def process(message)
66
+ if entity == "comment" && action == "created"
67
+ # Do something...
68
+ else
69
+ false
70
+ end
28
71
  end
29
72
  end
73
+ Larva::Listener.listen(:my_topic, MyProcessor, "")
74
+ Propono.publish(:my_topic, {entity: "comment", action: "created", id: 8}
75
+ ```
76
+
77
+ With this code `MyProcessor#process` will get called for each message, with extra logging around the call. Within the class you have access to `message`, `action`, `entity` and `id` methods.
78
+
79
+ ### Worker Pool
30
80
 
31
- Larva::Listener.listen(:my_topic, MyProcessor, "queue_suffix")
81
+ The worker pool creates a listener for each topic, and proxies messages to the associated processors. If any processors die, the application will die.
82
+
83
+ Creating a worker pool is trivial:
84
+
85
+ ```ruby
86
+ processors = {
87
+ my_topic_1: MyProcessor1
88
+ my_topic_2: MyProcessor2
89
+ }
90
+ Larva::WorkerPool.start(processors, "queue-suffix")
32
91
  ```
33
92
 
34
93
  ### Is it any good?
data/lib/larva.rb CHANGED
@@ -4,6 +4,8 @@ require 'propono'
4
4
  require 'filum'
5
5
 
6
6
  require 'larva/listener'
7
+ require 'larva/processor'
8
+ require 'larva/worker_pool'
7
9
 
8
10
  module Larva
9
11
  end
@@ -0,0 +1,24 @@
1
+ module Larva
2
+ class Processor
3
+ def self.process(message)
4
+ new(message).process_with_logging
5
+ end
6
+
7
+ attr_accessor :message, :action, :entity, :id
8
+ def initialize(message)
9
+ @message = message
10
+ @action = message[:action]
11
+ @entity = message[:entity]
12
+ @id = message[:id]
13
+ end
14
+
15
+ def process_with_logging
16
+ Propono.config.logger.info "Processing message: #{message}"
17
+ if self.process
18
+ Propono.config.logger.info "Message Processed: #{message}"
19
+ else
20
+ Propono.config.logger.info "Unrecognized event type, entity: #{entity} action: #{action}."
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/larva/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Larva
2
- VERSION = '0.1.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -0,0 +1,42 @@
1
+ module Larva
2
+ class WorkerPool
3
+ def self.start(processors, queue_suffix)
4
+ new(processors, queue_suffix).start
5
+ end
6
+
7
+ attr_reader :processors, :queue_suffix, :workers
8
+ def initialize(processors, queue_suffix)
9
+ @processors = processors
10
+ @queue_suffix = queue_suffix
11
+ end
12
+
13
+ def start
14
+ start_workers
15
+ keep_workers_alive if workers.count > 0
16
+ end
17
+
18
+ private
19
+ def start_workers
20
+ logger.info "Starting threads."
21
+ @workers = processors.map do |topic, processor|
22
+ Thread.new { start_worker(topic, processor) }
23
+ end
24
+ logger.info "Threads Started."
25
+ end
26
+
27
+ def start_worker(topic, processor)
28
+ Larva::Listener.listen(topic, processor, queue_suffix)
29
+ rescue => e
30
+ logger.error "Unexpected listener termination: #{e} #{e.backtrace}"
31
+ end
32
+
33
+ def keep_workers_alive
34
+ sleep(1) while workers.all? { |t| t.alive? }
35
+ logger.error "Some threads have died"
36
+ end
37
+
38
+ def logger
39
+ Propono.config.logger
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,54 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Larva
4
+ class ProcessorTest < Minitest::Test
5
+ def test_initialize_should_extract_action_and_entity
6
+ entity = "media_file"
7
+ action = "processed"
8
+ message = {entity: entity, action: action, media_file_id: "8"}
9
+ processor = Processor.new(message)
10
+ assert_equal entity, processor.entity
11
+ assert_equal action, processor.action
12
+ end
13
+
14
+ class GoodProcessor < Processor
15
+ def process
16
+ true
17
+ end
18
+ end
19
+
20
+ class BadProcessor < Processor
21
+ def process
22
+ false
23
+ end
24
+ end
25
+
26
+ def test_process_logs_message
27
+ message = {entity: "media_file", action: "processed", media_file_id: "8"}
28
+ output = "Processing message: #{message}"
29
+ Propono.config.logger.stubs(:info)
30
+ Propono.config.logger.expects(:info).with(output)
31
+ GoodProcessor.process(message)
32
+ end
33
+
34
+ def test_process_logs_success
35
+ message = {entity: "media_file", action: "processed", media_file_id: "8"}
36
+ output = "Message Processed: #{message}"
37
+ Propono.config.logger.stubs(:info)
38
+ Propono.config.logger.expects(:info).with(output)
39
+ GoodProcessor.process(message)
40
+ end
41
+
42
+ def test_process_logs_message
43
+ entity = "media_file"
44
+ action = "processed"
45
+ message = {entity: entity, action: action, media_file_id: "8"}
46
+ output = "Unrecognized event type, entity: #{entity} action: #{action}."
47
+
48
+ Propono.config.logger.stubs(:info)
49
+ Propono.config.logger.expects(:info).with(output)
50
+ BadProcessor.process(message)
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Larva
4
+ class WorkerPoolTest < Minitest::Test
5
+ def test_should_complete_for_no_processors
6
+ WorkerPool.start({}, "")
7
+ end
8
+
9
+ def test_process_logs_start_message
10
+ Propono.config.logger.stubs(:info)
11
+ Propono.config.logger.expects(:info).with("Starting threads.")
12
+ WorkerPool.start({}, "")
13
+ end
14
+
15
+ def test_process_logs_end_message
16
+ Propono.config.logger.stubs(:info)
17
+ Propono.config.logger.expects(:info).with("Threads Started.")
18
+ WorkerPool.start({}, "")
19
+ end
20
+
21
+ def test_start_worker_logs_exception
22
+ Larva::Listener.expects(:listen).raises(RuntimeError)
23
+ Propono.config.logger.expects(:error).with do |error|
24
+ error.start_with?("Unexpected listener termination:")
25
+ end
26
+ Propono.config.logger.expects(:error).with('Some threads have died')
27
+ WorkerPool.start({nil => nil}, "")
28
+ end
29
+
30
+ def test_listen_is_called_correctly
31
+ topic_name = "Foo"
32
+ processor = mock
33
+ queue_suffix = "Bar"
34
+ Larva::Listener.expects(:listen).with(topic_name, processor, queue_suffix)
35
+ WorkerPool.start({topic_name => processor}, queue_suffix)
36
+ end
37
+ end
38
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: larva
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - iHiD
@@ -102,6 +102,7 @@ extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
104
  - .gitignore
105
+ - .travis.yml
105
106
  - CHANGELOG
106
107
  - CONTRIBUTING.md
107
108
  - Gemfile
@@ -111,10 +112,14 @@ files:
111
112
  - larva.gemspec
112
113
  - lib/larva.rb
113
114
  - lib/larva/listener.rb
115
+ - lib/larva/processor.rb
114
116
  - lib/larva/version.rb
117
+ - lib/larva/worker_pool.rb
115
118
  - test/larva_test.rb
116
119
  - test/listener_test.rb
120
+ - test/processor_test.rb
117
121
  - test/test_helper.rb
122
+ - test/worker_pool_test.rb
118
123
  homepage: https://github.com/meducation/larva
119
124
  licenses:
120
125
  - AGPL3
@@ -142,5 +147,7 @@ summary: Some Meducation specific helper files for ur pub/sub network
142
147
  test_files:
143
148
  - test/larva_test.rb
144
149
  - test/listener_test.rb
150
+ - test/processor_test.rb
145
151
  - test/test_helper.rb
152
+ - test/worker_pool_test.rb
146
153
  has_rdoc: