bi-frost 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61a3243740e3d642efe0184d5c64d4ad11e72bff
4
- data.tar.gz: 3834b3af2f9541dd7222a2ebf3e266f9430db2ea
3
+ metadata.gz: 363ad309cb14525b8eff19191a79063afbd1dafa
4
+ data.tar.gz: ca5ff194604f4bfd3748082c40cfb4b5252f20be
5
5
  SHA512:
6
- metadata.gz: 764a14af9175bf5ffd9f25d8e1d84aa6fd31988db87da0cca2db0bc262715d669b66e591892b6a7e7f017899ad6e870813781ac25dd98860e7c519faee77ecfa
7
- data.tar.gz: 1319f4d4eb92d423485943ecdbdd941f68c78b9360b584213c442f1f8f5ea735e22e1f044e0a8e40e02d37c1f160ada2df9b96e89685ffdb2b22354a8a76b0a7
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(topic_name, sub_name)
12
- topic = Bifrost::Topic.new(topic_name)
12
+ def self.create_topic_with_subscriber(topic, subscriber)
13
+ topic = Bifrost::Topic.new(topic)
13
14
  topic.save
14
- subscriber = Bifrost::Subscriber.new(sub_name)
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
@@ -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(topic_name, subscriber_name, proc)
17
- if topic_name.nil? || subscriber_name.nil? || proc.nil?
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
- @supervisor.actors.each { |w| w.async.run }
34
- # Put the supervisor thread to sleep indefinitely # Better way?
35
+ # Put the supervisor thread to sleep indefinitely
35
36
  loop do
36
- # TODO: Better way?
37
- sleep(5)
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
- # TODO: Log this instead
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
@@ -1,15 +1,15 @@
1
1
  # Major.Minor.Patch version numbering
2
2
  module Bifrost
3
- # The major version of Sif, updated only for major changes that are
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 Sif, updated for new feature releases.
7
+ # The minor version of Bifrost, updated for new feature releases.
8
8
  MINOR_VERSION = 1
9
9
 
10
- # The patch version of Sif, updated only for bug fixes from the last
10
+ # The patch version of Bifrost, updated only for bug fixes from the last
11
11
  # feature release.
12
- PATCH_VERSION = 0
12
+ PATCH_VERSION = 1
13
13
 
14
14
  # The full version as a string.
15
15
  VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}.#{PATCH_VERSION}".freeze
@@ -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 :topic_name, :subscriber_name, :callback
15
+ attr_reader :topic, :subscriber, :callback
14
16
 
15
- def initialize(topic_name, subscriber_name, callback)
16
- raise Bifrost::Exceptions::UnsupportedLambdaError, 'not a proc' unless callback.respond_to?(:call)
17
- @topic_name ||= topic_name
18
- @subscriber_name ||= subscriber_name
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.supervisor_handle(topic_name, subscriber_name)
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.supervisor_handle(topic_name, subscriber_name)
45
- "#{topic_name}-#{subscriber_name}"
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(topic_name, subscriber_name, timeout: ENV['TIMEOUT'] || 10)
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 ) { proc { |m| puts "Principle Received: message #{m}" } }
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
 
@@ -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
- invalid_topic_name = Bifrost::Topic.new('topic name')
87
- expect { invalid_topic_name.save }.to raise_error(URI::InvalidURIError)
86
+ invalid_topic = Bifrost::Topic.new('topic name')
87
+ expect { invalid_topic.save }.to raise_error(URI::InvalidURIError)
88
88
  end
89
89
  end
@@ -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(:topic_name) }
13
- it { is_expected.to respond_to(:subscriber_name) }
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.topic_name}-#{worker.subscriber_name}")
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.0
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-10-31 00:00:00.000000000 Z
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: Topic definitions should occur via the Bifrost. Subscriptions should
154
- take place via the Bifrost. Therefore all messages need to transit through the Bifrost
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 simple pub/sub messaging wrapper component.
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