bi-frost 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bifrost.rb +9 -4
- data/lib/bifrost/manager.rb +40 -15
- data/lib/bifrost/version.rb +4 -4
- data/lib/bifrost/worker.rb +15 -9
- data/spec/bifrost/manager_spec.rb +1 -1
- data/spec/bifrost/topic_spec.rb +2 -2
- data/spec/bifrost/worker_spec.rb +8 -3
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 363ad309cb14525b8eff19191a79063afbd1dafa
|
4
|
+
data.tar.gz: ca5ff194604f4bfd3748082c40cfb4b5252f20be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e01794fc41e75b97540793609859481ea476d3f0029e30b2451dac5438e7afc73cf4d868678c9e718a109ad83d9b3010cb0d2363cb420fe9f33c20b09ecb230
|
7
|
+
data.tar.gz: bafa72e44054663f88246a33e072b379747e17969c78112cdeb854c193eb4637ebe37d1c53ecfb433f0fec0368ac1bbd132a148f96c5b1b4a004b95c601616bb
|
data/lib/bifrost.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'bifrost/entity'
|
1
2
|
require 'bifrost/message'
|
2
3
|
require 'bifrost/topic'
|
3
4
|
require 'bifrost/subscriber'
|
@@ -8,11 +9,15 @@ require 'bifrost/worker'
|
|
8
9
|
module Bifrost
|
9
10
|
# Simple utlity that creates a topic and a single subscriber for the given
|
10
11
|
# topic. The topic is returned
|
11
|
-
def self.create_topic_with_subscriber(
|
12
|
-
topic = Bifrost::Topic.new(
|
12
|
+
def self.create_topic_with_subscriber(topic, subscriber)
|
13
|
+
topic = Bifrost::Topic.new(topic)
|
13
14
|
topic.save
|
14
|
-
|
15
|
-
topic.add_subscriber(subscriber)
|
15
|
+
topic.add_subscriber(Bifrost::Subscriber.new(subscriber))
|
16
16
|
topic
|
17
17
|
end
|
18
|
+
|
19
|
+
# Creates a manager instance
|
20
|
+
def self.manager
|
21
|
+
Bifrost::Manager.new
|
22
|
+
end
|
18
23
|
end
|
data/lib/bifrost/manager.rb
CHANGED
@@ -6,44 +6,69 @@ module Bifrost
|
|
6
6
|
# This class is used to handle the setup and execution of multiple listeners
|
7
7
|
class Manager
|
8
8
|
include Celluloid
|
9
|
+
include Celluloid::Internals::Logger
|
10
|
+
include Celluloid::Notifications
|
9
11
|
|
10
12
|
# The supervisor needs to be notified when a worker dies, it also needs to
|
11
13
|
# protect itself from harm
|
12
14
|
trap_exit :worker_died
|
13
15
|
|
16
|
+
# Initialisation of the Manager sets up a subscriber, which informs the manager
|
17
|
+
# when the worker is ready to begin work
|
18
|
+
def initialize
|
19
|
+
subscribe('worker_ready', :worker_ready)
|
20
|
+
end
|
21
|
+
|
14
22
|
# A supervised worker can be added to the current collection of supervised workers
|
15
23
|
# this also starts the actor
|
16
|
-
def add(
|
17
|
-
if
|
24
|
+
def add(topic, subscriber, proc)
|
25
|
+
if topic.nil? || subscriber.nil? || proc.nil?
|
18
26
|
raise InvalidWorkerDefinitionError, 'Invalid worker'
|
19
27
|
else
|
20
|
-
@supervisor = Worker.supervise(
|
21
|
-
as: Worker.supervisor_handle(topic_name, subscriber_name),
|
22
|
-
args: [topic_name, subscriber_name, proc]
|
23
|
-
)
|
24
|
-
# Link the worker to the supervisor so if the worker misbehaves the supervisor is alerted
|
25
|
-
# to this poor behaviour, the supervisor decides how to handle recovery
|
26
|
-
link(@supervisor.actors.last)
|
28
|
+
@supervisor = Worker.supervise(as: Worker.handle(topic, subscriber), args: [topic, subscriber, proc])
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
# When we run all the workers as actors in their own threads. This run also blocks to make sure
|
31
33
|
# the spawned threads remain operational indefinitely
|
32
34
|
def run
|
33
|
-
|
34
|
-
# Put the supervisor thread to sleep indefinitely # Better way?
|
35
|
+
# Put the supervisor thread to sleep indefinitely
|
35
36
|
loop do
|
36
|
-
# TODO:
|
37
|
-
sleep(
|
37
|
+
# TODO: Perhaps there is a better way?
|
38
|
+
sleep(60)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# This callback is fired when the worker signals it is ready to commence work after initialisation or
|
43
|
+
# recommence after recovering from a failure.
|
44
|
+
# When a worker completes initialisation it can take a while for the worker to be registered as an Actor
|
45
|
+
# in Celluloid, for this reason we need need to put a minor delay in the initialisation procedure
|
46
|
+
def worker_ready(*args)
|
47
|
+
info("Worker bootstrapping with #{args}...")
|
48
|
+
sleep(ENV['ACTOR_BOOTSTRAP_DELAY'] || 2) # TODO: Perhaps there is a better way?
|
49
|
+
worker = get_worker(args[1], args[2])
|
50
|
+
if worker
|
51
|
+
# Link the worker to the supervisor so if the worker misbehaves the supervisor is alerted
|
52
|
+
# to this poor behaviour, the supervisor decides how to handle recovery
|
53
|
+
link(worker)
|
54
|
+
worker.async.run
|
55
|
+
else
|
56
|
+
error("Worker bootstrap failure with #{args}")
|
38
57
|
end
|
39
58
|
end
|
40
59
|
|
41
60
|
private
|
42
61
|
|
62
|
+
# Retrieve a worker through the supervisory structure, this can take a while as the worker might
|
63
|
+
# be going through a restart procedure by the actor framework
|
64
|
+
def get_worker(topic, subscriber)
|
65
|
+
handle = Worker.handle(topic, subscriber)
|
66
|
+
Celluloid::Actor[handle.to_sym]
|
67
|
+
end
|
68
|
+
|
43
69
|
# This callback function fires when an worker dies
|
44
70
|
def worker_died(worker, reason)
|
45
|
-
#
|
46
|
-
puts "#{worker.inspect} has died: #{reason.class}"
|
71
|
+
error("Worker #{worker.inspect} has died: #{reason.class}")
|
47
72
|
end
|
48
73
|
end
|
49
74
|
end
|
data/lib/bifrost/version.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Major.Minor.Patch version numbering
|
2
2
|
module Bifrost
|
3
|
-
# The major version of
|
3
|
+
# The major version of Bifrost, updated only for major changes that are
|
4
4
|
# likely to require modification to Filmpond apps.
|
5
5
|
MAJOR_VERSION = 0
|
6
6
|
|
7
|
-
# The minor version of
|
7
|
+
# The minor version of Bifrost, updated for new feature releases.
|
8
8
|
MINOR_VERSION = 1
|
9
9
|
|
10
|
-
# The patch version of
|
10
|
+
# The patch version of Bifrost, updated only for bug fixes from the last
|
11
11
|
# feature release.
|
12
|
-
PATCH_VERSION =
|
12
|
+
PATCH_VERSION = 1
|
13
13
|
|
14
14
|
# The full version as a string.
|
15
15
|
VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}.#{PATCH_VERSION}".freeze
|
data/lib/bifrost/worker.rb
CHANGED
@@ -9,20 +9,26 @@ module Bifrost
|
|
9
9
|
# combination one at a time
|
10
10
|
class Worker < Bifrost::Entity
|
11
11
|
include Celluloid
|
12
|
+
include Celluloid::Internals::Logger
|
13
|
+
include Celluloid::Notifications
|
12
14
|
|
13
|
-
attr_reader :
|
15
|
+
attr_reader :topic, :subscriber, :callback
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
17
|
+
# Initialise the worker/actor. This actually starts the worker by implicitly calling the run method
|
18
|
+
def initialize(topic, subscriber, callback)
|
19
|
+
raise Bifrost::Exceptions::UnsupportedLambdaError, 'callback is not a proc' unless callback.respond_to?(:call)
|
20
|
+
@topic ||= topic
|
21
|
+
@subscriber ||= subscriber
|
19
22
|
@callback ||= callback
|
20
23
|
super()
|
24
|
+
info("Worker #{to_sym} starting up...")
|
25
|
+
publish('worker_ready', topic, subscriber)
|
21
26
|
end
|
22
27
|
|
23
28
|
# This method starts the actor, which runs in an infinite loop. This means the worker should
|
24
29
|
# not terminate, but if it does, the supervisor will make sure it restarts
|
25
30
|
def run
|
31
|
+
info("Worker #{to_sym} running...")
|
26
32
|
loop do
|
27
33
|
read_message
|
28
34
|
sleep(ENV['QUEUE_DELAY'] || 10)
|
@@ -32,7 +38,7 @@ module Bifrost
|
|
32
38
|
# Workers have a friendly name which is a combination of the topic and subscriber name
|
33
39
|
# which in the operational environment should be unique
|
34
40
|
def to_s
|
35
|
-
Worker.
|
41
|
+
Worker.handle(topic, subscriber)
|
36
42
|
end
|
37
43
|
|
38
44
|
# Utlity method to get the name of the worker as a symbol
|
@@ -41,15 +47,15 @@ module Bifrost
|
|
41
47
|
end
|
42
48
|
|
43
49
|
# A worker can tell you what it's friendly name will be, this is in order for supervision
|
44
|
-
def self.
|
45
|
-
"#{
|
50
|
+
def self.handle(topic, subscriber)
|
51
|
+
"#{topic.downcase}#{subscriber.downcase}"
|
46
52
|
end
|
47
53
|
|
48
54
|
private
|
49
55
|
|
50
56
|
# Actual processing of the message
|
51
57
|
def read_message
|
52
|
-
message = bus.receive_subscription_message(
|
58
|
+
message = bus.receive_subscription_message(topic, subscriber, timeout: ENV['TIMEOUT'] || 10)
|
53
59
|
if message
|
54
60
|
callback.call(message.properties['message'])
|
55
61
|
bus.delete_subscription_message(message)
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'bifrost'
|
3
3
|
|
4
4
|
describe Bifrost::Manager do
|
5
|
-
let(:cb
|
5
|
+
let(:cb) { proc { |m| puts "Principle Received: message #{m}" } }
|
6
6
|
let(:worker) { Bifrost::Worker.new('topic', 'subscriber', proc) }
|
7
7
|
let(:manager) { Bifrost::Manager.new }
|
8
8
|
|
data/spec/bifrost/topic_spec.rb
CHANGED
@@ -83,7 +83,7 @@ describe Bifrost::Topic do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'should not accept names with spaces in them' do
|
86
|
-
|
87
|
-
expect {
|
86
|
+
invalid_topic = Bifrost::Topic.new('topic name')
|
87
|
+
expect { invalid_topic.save }.to raise_error(URI::InvalidURIError)
|
88
88
|
end
|
89
89
|
end
|
data/spec/bifrost/worker_spec.rb
CHANGED
@@ -9,8 +9,8 @@ describe Bifrost::Worker do
|
|
9
9
|
let(:cb) { proc { |m| puts "Received: message #{m}" } }
|
10
10
|
subject(:worker) { Bifrost::Worker.new('topic', 'subscriber', cb) }
|
11
11
|
|
12
|
-
it { is_expected.to respond_to(:
|
13
|
-
it { is_expected.to respond_to(:
|
12
|
+
it { is_expected.to respond_to(:topic) }
|
13
|
+
it { is_expected.to respond_to(:subscriber) }
|
14
14
|
|
15
15
|
it 'should not except non procs in last argument' do
|
16
16
|
expect { Bifrost::Worker.new('topic', 'subscriber', 'x') }
|
@@ -18,7 +18,12 @@ describe Bifrost::Worker do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should have a friendly string name' do
|
21
|
-
expect(worker.to_s).to eq("#{worker.
|
21
|
+
expect(worker.to_s).to eq("#{worker.topic}#{worker.subscriber}")
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should downcase the friendly name' do
|
25
|
+
another_worker = Bifrost::Worker.new('toPic', 'subScriber', cb)
|
26
|
+
expect(another_worker.to_s).to eq("#{another_worker.topic.downcase}#{another_worker.subscriber.downcase}")
|
22
27
|
end
|
23
28
|
|
24
29
|
it 'should have a friendly symbol name' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bi-frost
|
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
|
- Shirren Premaratne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: azure
|
@@ -42,14 +42,14 @@ dependencies:
|
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -150,8 +150,8 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0.7'
|
153
|
-
description:
|
154
|
-
|
153
|
+
description: Bifrost is a pub/sub wrapper library which uses Azure message bus and
|
154
|
+
actors.
|
155
155
|
email:
|
156
156
|
- shirren@filmpond.com
|
157
157
|
executables: []
|
@@ -178,7 +178,8 @@ files:
|
|
178
178
|
- spec/bifrost/worker_spec.rb
|
179
179
|
- spec/spec_helper.rb
|
180
180
|
homepage: https://github.com/filmpond/bifrost
|
181
|
-
licenses:
|
181
|
+
licenses:
|
182
|
+
- MIT
|
182
183
|
metadata: {}
|
183
184
|
post_install_message:
|
184
185
|
rdoc_options: []
|
@@ -188,7 +189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
189
|
requirements:
|
189
190
|
- - ">="
|
190
191
|
- !ruby/object:Gem::Version
|
191
|
-
version: '0'
|
192
|
+
version: '2.0'
|
192
193
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
194
|
requirements:
|
194
195
|
- - ">="
|
@@ -199,7 +200,8 @@ rubyforge_project:
|
|
199
200
|
rubygems_version: 2.5.1
|
200
201
|
signing_key:
|
201
202
|
specification_version: 4
|
202
|
-
summary: Bifrost is a
|
203
|
+
summary: Bifrost is a pub/sub wrapper library which uses the Azure message bus and
|
204
|
+
actors.
|
203
205
|
test_files:
|
204
206
|
- spec/bifrost/manager_spec.rb
|
205
207
|
- spec/bifrost/message_spec.rb
|