freddy-jruby 0.6.0 → 0.7.2

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: bcd002e379a1f9326e97c95617e8027065403fcc
4
- data.tar.gz: 2982e7fae24ee6ba8e763be8426d86806406e2da
3
+ metadata.gz: 4d8614a6a2bc844445d26bf035b0ecdbd5c2e12d
4
+ data.tar.gz: c64f8114a61bd258bef376c4927110b338041d44
5
5
  SHA512:
6
- metadata.gz: d4f642d80cbb81bd9150c1cac643d4a919b18ada01cc40ad42e3c26cbc394d1f3491ac11a529243da39aeec7c1e4cc5c3d66699178ed4dc29cf6fdf4b36788be
7
- data.tar.gz: d02a32438c611aea42a2d242b7d59d1abfa73fb42a7ac1f17ebb3542059eccffb341b6bc078a822900f9112ee30d6e9615a41d52322fdf88478b7e91681bf113
6
+ metadata.gz: 648e9031be023cab9fdce260b27925331444c8ca35d4dd8321d06df494f3f0f5730f0df68b54e1f9fcf667691ef311c669260da35b99bab2f9d408aa885bba67
7
+ data.tar.gz: a1d06a5f8361ea94c18b698a035bf643bc9858b4541de331bad0a670b2f17051c458bb1383d877c8afbcabe2a78c9f0502c9d279a7dc7b080c7113268c816d68
data/Gemfile CHANGED
@@ -3,5 +3,6 @@ source 'https://rubygems.org'
3
3
  gem 'rspec'
4
4
  gem 'pry'
5
5
  gem 'codeclimate-test-reporter'
6
+ gem 'hamster', '~> 3.0'
6
7
 
7
8
  gemspec
data/README.md CHANGED
@@ -138,10 +138,7 @@ responder_handler.shutdown
138
138
 
139
139
  ## Notes about concurrency
140
140
 
141
- The underlying bunny implementation uses 1 responder thread by default. This means that if there is a time-consuming process or a sleep call in a responder then other responders will not receive messages concurrently.
142
- To resolve this problem *freddy* uses a thread pool for running concurrent responders.
143
- The thread pool is shared between *tap_into* and *respond_to* callbacks and the default size is 4.
144
- The thread pool size can be configured by passing the configuration option *max_concurrency*.
141
+ *freddy* uses a thread pool to run concurrent responders. The thread pool is unique for each *tap_into* and *respond_to* responder. Thread pool size can be configured by passing the configuration option *max_concurrency*. Its default value is 4. e.g. If your application has 2 *respond_to* responders and 1 *tap_into* responder with *max_concurrency* set to 3 then your application may process up to 9 messages in parallel.
145
142
 
146
143
 
147
144
  Note that while it is possible to use *deliver_with_response* inside a *respond_to* block,
data/freddy.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  else
9
9
  spec.name = "freddy"
10
10
  end
11
- spec.version = '0.6.0'
12
- spec.authors = ["Urmas Talimaa"]
13
- spec.email = ["urmas.talimaa@gmail.com"]
11
+ spec.version = '0.7.2'
12
+ spec.authors = ["Salemove TechMovers"]
13
+ spec.email = ["techmovers@salemove.com"]
14
14
  spec.description = %q{Messaging API}
15
15
  spec.summary = %q{API for inter-application messaging supporting acknowledgements and request-response}
16
16
  spec.license = "Private"
@@ -27,10 +27,9 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'march_hare', '~> 2.12.0'
28
28
  spec.add_dependency 'symbolizer'
29
29
  else
30
- spec.add_dependency "bunny", "~> 2.5.0"
30
+ spec.add_dependency "bunny", "~> 2.6"
31
31
  spec.add_dependency "oj", "~> 2.13"
32
32
  end
33
33
 
34
- spec.add_dependency "hamster", "~> 1.0.1.pre.rc3"
35
- spec.add_dependency "thread", "~> 0.2"
34
+ spec.add_dependency "thread", "~> 0.1"
36
35
  end
data/lib/freddy.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'json'
2
2
  require 'thread/pool'
3
- require 'hamster/mutable_hash'
3
+ require 'securerandom'
4
4
 
5
5
  Dir[File.dirname(__FILE__) + '/freddy/*.rb'].each(&method(:require))
6
6
 
@@ -18,6 +18,7 @@ class Freddy
18
18
  # @option config [Integer] :port (5672)
19
19
  # @option config [String] :user ('guest')
20
20
  # @option config [String] :pass ('guest')
21
+ # @option config [Integer] :max_concurrency (4)
21
22
  #
22
23
  # @return [Freddy]
23
24
  #
@@ -25,17 +26,14 @@ class Freddy
25
26
  # Freddy.build(Logger.new(STDOUT), user: 'thumper', pass: 'howdy')
26
27
  def self.build(logger = Logger.new(STDOUT), max_concurrency: DEFAULT_MAX_CONCURRENCY, **config)
27
28
  connection = Adapters.determine.connect(config)
28
- consume_thread_pool = Thread.pool(max_concurrency)
29
29
 
30
- new(connection, logger, consume_thread_pool)
30
+ new(connection, logger, max_concurrency)
31
31
  end
32
32
 
33
- def initialize(connection, logger, consume_thread_pool)
33
+ def initialize(connection, logger, max_concurrency)
34
34
  @connection = connection
35
35
  @logger = logger
36
-
37
- @tap_into_consumer = Consumers::TapIntoConsumer.new(consume_thread_pool, @logger)
38
- @respond_to_consumer = Consumers::RespondToConsumer.new(consume_thread_pool, @logger)
36
+ @prefetch_buffer_size = max_concurrency
39
37
 
40
38
  @send_and_forget_producer = Producers::SendAndForgetProducer.new(
41
39
  connection.create_channel, logger
@@ -73,12 +71,17 @@ class Freddy
73
71
  def respond_to(destination, &callback)
74
72
  @logger.info "Listening for requests on #{destination}"
75
73
 
76
- channel = @connection.create_channel
74
+ channel = @connection.create_channel(prefetch: @prefetch_buffer_size)
77
75
  producer = Producers::ReplyProducer.new(channel, @logger)
78
76
  handler_adapter_factory = MessageHandlerAdapters::Factory.new(producer)
79
77
 
80
- @respond_to_consumer.consume(
81
- destination, channel, handler_adapter_factory, &callback
78
+ Consumers::RespondToConsumer.consume(
79
+ logger: @logger,
80
+ thread_pool: Thread.pool(@prefetch_buffer_size),
81
+ destination: destination,
82
+ channel: channel,
83
+ handler_adapter_factory: handler_adapter_factory,
84
+ &callback
82
85
  )
83
86
  end
84
87
 
@@ -91,6 +94,10 @@ class Freddy
91
94
  # @param [String] pattern
92
95
  # the destination pattern. Use `#` wildcard for matching 0 or more words.
93
96
  # Use `*` to match exactly one word.
97
+ # @param [Hash] options
98
+ # @option options [String] :group
99
+ # only one of the listeners in given group will receive a message. All
100
+ # listeners will receive a message if the group is not specified.
94
101
  #
95
102
  # @yield [message] Yields received message to the block
96
103
  #
@@ -100,9 +107,17 @@ class Freddy
100
107
  # freddy.tap_into 'notifications.*' do |message|
101
108
  # puts "Notification showed #{message.inspect}"
102
109
  # end
103
- def tap_into(pattern, &callback)
110
+ def tap_into(pattern, options = {}, &callback)
104
111
  @logger.debug "Tapping into messages that match #{pattern}"
105
- @tap_into_consumer.consume(pattern, @connection.create_channel, &callback)
112
+
113
+ Consumers::TapIntoConsumer.consume(
114
+ logger: @logger,
115
+ thread_pool: Thread.pool(@prefetch_buffer_size),
116
+ pattern: pattern,
117
+ channel: @connection.create_channel(prefetch: @prefetch_buffer_size),
118
+ options: options,
119
+ &callback
120
+ )
106
121
  end
107
122
 
108
123
  # Sends a message to given destination
@@ -24,6 +24,10 @@ class Freddy
24
24
  def name
25
25
  @queue.name
26
26
  end
27
+
28
+ def message_count
29
+ @queue.message_count
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -13,8 +13,10 @@ class Freddy
13
13
  @bunny = bunny
14
14
  end
15
15
 
16
- def create_channel
17
- Channel.new(@bunny.create_channel)
16
+ def create_channel(prefetch: nil)
17
+ bunny_channel = @bunny.create_channel
18
+ bunny_channel.prefetch(prefetch) if prefetch
19
+ Channel.new(bunny_channel)
18
20
  end
19
21
 
20
22
  def close
@@ -30,7 +32,7 @@ class Freddy
30
32
  @channel = channel
31
33
  end
32
34
 
33
- def_delegators :@channel, :topic, :default_exchange, :consumers
35
+ def_delegators :@channel, :topic, :default_exchange, :consumers, :acknowledge
34
36
 
35
37
  def queue(*args)
36
38
  Queue.new(@channel.queue(*args))
@@ -46,10 +48,13 @@ class Freddy
46
48
  end
47
49
 
48
50
  class Queue < Shared::Queue
49
- def subscribe(&block)
50
- @queue.subscribe do |info, properties, payload|
51
+ def subscribe(manual_ack: false, &block)
52
+ @queue.subscribe(manual_ack: manual_ack) do |info, properties, payload|
51
53
  parsed_payload = Payload.parse(payload)
52
- block.call(Delivery.new(parsed_payload, properties, info.routing_key))
54
+ delivery = Delivery.new(
55
+ parsed_payload, properties, info.routing_key, info.delivery_tag
56
+ )
57
+ block.call(delivery)
53
58
  end
54
59
  end
55
60
  end
@@ -12,8 +12,10 @@ class Freddy
12
12
  @hare = hare
13
13
  end
14
14
 
15
- def create_channel
16
- Channel.new(@hare.create_channel)
15
+ def create_channel(prefetch: nil)
16
+ hare_channel = @hare.create_channel
17
+ hare_channel.basic_qos(prefetch) if prefetch
18
+ Channel.new(hare_channel)
17
19
  end
18
20
 
19
21
  def close
@@ -29,7 +31,7 @@ class Freddy
29
31
  @channel = channel
30
32
  end
31
33
 
32
- def_delegators :@channel, :topic, :default_exchange, :consumers
34
+ def_delegators :@channel, :topic, :default_exchange, :consumers, :acknowledge
33
35
 
34
36
  def queue(*args)
35
37
  Queue.new(@channel.queue(*args))
@@ -45,10 +47,13 @@ class Freddy
45
47
  end
46
48
 
47
49
  class Queue < Shared::Queue
48
- def subscribe(&block)
49
- @queue.subscribe do |meta, payload|
50
+ def subscribe(manual_ack: false, &block)
51
+ @queue.subscribe(manual_ack: manual_ack) do |meta, payload|
50
52
  parsed_payload = Payload.parse(payload)
51
- block.call(Delivery.new(parsed_payload, meta, meta.routing_key))
53
+ delivery = Delivery.new(
54
+ parsed_payload, meta, meta.routing_key, meta.delivery_tag
55
+ )
56
+ block.call(delivery)
52
57
  end
53
58
  end
54
59
  end
@@ -1,16 +1,23 @@
1
1
  class Freddy
2
2
  module Consumers
3
3
  class RespondToConsumer
4
- def initialize(consume_thread_pool, logger)
5
- @consume_thread_pool = consume_thread_pool
4
+ def self.consume(*attrs, &block)
5
+ new(*attrs).consume(&block)
6
+ end
7
+
8
+ def initialize(logger:, thread_pool:, destination:, channel:, handler_adapter_factory:)
6
9
  @logger = logger
10
+ @consume_thread_pool = thread_pool
11
+ @destination = destination
12
+ @channel = channel
13
+ @handler_adapter_factory = handler_adapter_factory
7
14
  end
8
15
 
9
- def consume(destination, channel, handler_adapter_factory, &block)
10
- consumer = consume_from_destination(destination, channel) do |delivery|
11
- Consumers.log_receive_event(@logger, destination, delivery)
16
+ def consume(&block)
17
+ consumer = consume_from_destination do |delivery|
18
+ Consumers.log_receive_event(@logger, @destination, delivery)
12
19
 
13
- adapter = handler_adapter_factory.for(delivery)
20
+ adapter = @handler_adapter_factory.for(delivery)
14
21
 
15
22
  msg_handler = MessageHandler.new(adapter, delivery)
16
23
  block.call(delivery.payload, msg_handler)
@@ -21,15 +28,19 @@ class Freddy
21
28
 
22
29
  private
23
30
 
24
- def consume_from_destination(destination, channel, &block)
25
- channel.queue(destination).subscribe do |delivery|
31
+ def consume_from_destination(&block)
32
+ @channel.queue(@destination).subscribe(manual_ack: true) do |delivery|
26
33
  process_message(delivery, &block)
27
34
  end
28
35
  end
29
36
 
30
37
  def process_message(delivery, &block)
31
38
  @consume_thread_pool.process do
32
- block.call(delivery)
39
+ begin
40
+ block.call(delivery)
41
+ ensure
42
+ @channel.acknowledge(delivery.tag, false)
43
+ end
33
44
  end
34
45
  end
35
46
  end
@@ -3,24 +3,20 @@ class Freddy
3
3
  class ResponseConsumer
4
4
  def initialize(logger)
5
5
  @logger = logger
6
- @dedicated_thread_pool = Thread.pool(1)
7
6
  end
8
7
 
9
- def consume(queue, &block)
8
+ def consume(channel, queue, &block)
10
9
  @logger.debug "Consuming messages on #{queue.name}"
11
- consumer = queue.subscribe do |delivery|
12
- process_message(queue, delivery, &block)
10
+ queue.subscribe do |delivery|
11
+ process_message(channel, queue, delivery, &block)
13
12
  end
14
- ResponderHandler.new(consumer, @dedicated_thread_pool)
15
13
  end
16
14
 
17
15
  private
18
16
 
19
- def process_message(queue, delivery, &block)
20
- @dedicated_thread_pool.process do
21
- Consumers.log_receive_event(@logger, queue.name, delivery)
22
- block.call(delivery)
23
- end
17
+ def process_message(channel, queue, delivery, &block)
18
+ Consumers.log_receive_event(@logger, queue.name, delivery)
19
+ block.call(delivery)
24
20
  end
25
21
  end
26
22
  end
@@ -1,15 +1,22 @@
1
1
  class Freddy
2
2
  module Consumers
3
3
  class TapIntoConsumer
4
- def initialize(consume_thread_pool, logger)
4
+ def self.consume(*attrs, &block)
5
+ new(*attrs).consume(&block)
6
+ end
7
+
8
+ def initialize(logger:, thread_pool:, pattern:, channel:, options:)
5
9
  @logger = logger
6
- @consume_thread_pool = consume_thread_pool
10
+ @consume_thread_pool = thread_pool
11
+ @pattern = pattern
12
+ @channel = channel
13
+ @options = options
7
14
  end
8
15
 
9
- def consume(pattern, channel, &block)
10
- queue = create_queue(pattern, channel)
16
+ def consume(&block)
17
+ queue = create_queue
11
18
 
12
- consumer = queue.subscribe do |delivery|
19
+ consumer = queue.subscribe(manual_ack: true) do |delivery|
13
20
  process_message(queue, delivery, &block)
14
21
  end
15
22
 
@@ -18,18 +25,29 @@ class Freddy
18
25
 
19
26
  private
20
27
 
21
- def create_queue(pattern, channel)
22
- topic_exchange = channel.topic(Freddy::FREDDY_TOPIC_EXCHANGE_NAME)
28
+ def create_queue
29
+ topic_exchange = @channel.topic(Freddy::FREDDY_TOPIC_EXCHANGE_NAME)
30
+ group = @options.fetch(:group, nil)
23
31
 
24
- channel
25
- .queue('', exclusive: true)
26
- .bind(topic_exchange, routing_key: pattern)
32
+ if group
33
+ @channel
34
+ .queue("groups.#{group}")
35
+ .bind(topic_exchange, routing_key: @pattern)
36
+ else
37
+ @channel
38
+ .queue('', exclusive: true)
39
+ .bind(topic_exchange, routing_key: @pattern)
40
+ end
27
41
  end
28
42
 
29
43
  def process_message(queue, delivery, &block)
30
44
  @consume_thread_pool.process do
31
- Consumers.log_receive_event(@logger, queue.name, delivery)
32
- block.call delivery.payload, delivery.routing_key
45
+ begin
46
+ Consumers.log_receive_event(@logger, queue.name, delivery)
47
+ block.call delivery.payload, delivery.routing_key
48
+ ensure
49
+ @channel.acknowledge(delivery.tag, false)
50
+ end
33
51
  end
34
52
  end
35
53
  end
@@ -1,11 +1,12 @@
1
1
  class Freddy
2
2
  class Delivery
3
- attr_reader :routing_key, :payload
3
+ attr_reader :routing_key, :payload, :tag
4
4
 
5
- def initialize(payload, metadata, routing_key)
5
+ def initialize(payload, metadata, routing_key, tag)
6
6
  @payload = payload
7
7
  @metadata = metadata
8
8
  @routing_key = routing_key
9
+ @tag = tag
9
10
  end
10
11
 
11
12
  def correlation_id
@@ -19,7 +19,7 @@ class Freddy
19
19
  @response_queue = @channel.queue("", exclusive: true)
20
20
 
21
21
  @response_consumer = Consumers::ResponseConsumer.new(@logger)
22
- @response_consumer.consume(@response_queue, &method(:handle_response))
22
+ @response_consumer.consume(@channel, @response_queue, &method(:handle_response))
23
23
  end
24
24
 
25
25
  def produce(destination, payload, timeout_in_seconds:, delete_on_timeout:, **properties)
@@ -1,23 +1,31 @@
1
1
  class Freddy
2
2
  class RequestManager
3
3
  def initialize(logger)
4
- @requests = Hamster.mutable_hash
4
+ @requests = ConcurrentHash.new
5
5
  @logger = logger
6
6
  end
7
7
 
8
8
  def no_route(correlation_id)
9
9
  if request = @requests[correlation_id]
10
- @requests.delete correlation_id
10
+ delete(correlation_id)
11
11
  request[:callback].call({error: 'Specified queue does not exist'}, nil)
12
12
  end
13
13
  end
14
14
 
15
15
  def store(correlation_id, opts)
16
- @requests.store(correlation_id, opts)
16
+ @requests[correlation_id] = opts
17
17
  end
18
18
 
19
19
  def delete(correlation_id)
20
20
  @requests.delete(correlation_id)
21
21
  end
22
+
23
+ class ConcurrentHash < Hash
24
+ # CRuby hash does not need any locks. Only adding when using JRuby.
25
+ if RUBY_PLATFORM == 'java'
26
+ require 'jruby/synchronized'
27
+ include JRuby::Synchronized
28
+ end
29
+ end
22
30
  end
23
31
  end
@@ -1,4 +1,3 @@
1
- require 'thread'
2
1
  require 'timeout'
3
2
 
4
3
  class Freddy
@@ -1,24 +1,84 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Freddy::Consumers::RespondToConsumer do
4
- let(:consumer) { described_class.new(thread_pool, logger) }
4
+ let(:consumer) do
5
+ described_class.new(
6
+ logger: logger,
7
+ thread_pool: thread_pool,
8
+ destination: destination,
9
+ channel: channel,
10
+ handler_adapter_factory: msg_handler_adapter_factory
11
+ )
12
+ end
5
13
 
6
- let(:connection) { Freddy::Adapters.determine.connect(config) }
7
- let(:thread_pool) { Thread.pool(1) }
14
+ let(:connection) { Freddy::Adapters.determine.connect(config) }
8
15
  let(:destination) { random_destination }
9
- let(:payload) { {pay: 'load'} }
10
- let(:msg_handler) { double }
16
+ let(:payload) { {pay: 'load'} }
17
+ let(:msg_handler_adapter_factory) { double(for: msg_handler_adapter) }
18
+ let(:msg_handler_adapter) { Freddy::MessageHandlerAdapters::NoOpHandler.new }
19
+ let(:prefetch_buffer_size) { 2 }
20
+ let(:thread_pool) { Thread.pool(prefetch_buffer_size) }
11
21
 
12
22
  after do
13
23
  connection.close
14
24
  end
15
25
 
16
- it "doesn't call passed block without any messages" do
17
- consumer.consume destination, connection.create_channel, msg_handler do
18
- @message_received = true
26
+ context 'when no messages' do
27
+ let(:channel) { connection.create_channel }
28
+
29
+ it "doesn't call passed block" do
30
+ consumer.consume do
31
+ @message_received = true
32
+ end
33
+ default_sleep
34
+
35
+ expect(@message_received).to be_falsy
36
+ end
37
+ end
38
+
39
+ context 'when thread pool is full' do
40
+ let(:prefetch_buffer_size) { 1 }
41
+ let(:msg_count) { prefetch_buffer_size + 1 }
42
+ let(:channel) { connection.create_channel(prefetch: prefetch_buffer_size) }
43
+ let(:mutex) { Mutex.new }
44
+ let(:consume_lock) { ConditionVariable.new }
45
+ let(:queue) { channel.queue(destination) }
46
+
47
+ after do
48
+ # Release the final queued message before finishing the test to avoid
49
+ # bunny warnings.
50
+ process_message
19
51
  end
20
- default_sleep
21
52
 
22
- expect(@message_received).to be_falsy
53
+ it 'does not consume more messages' do
54
+ consumer.consume do
55
+ wait_until_released
56
+ end
57
+
58
+ msg_count.times { deliver_message }
59
+
60
+ sleep default_sleep
61
+ expect(queue.message_count).to eq(msg_count - prefetch_buffer_size)
62
+
63
+ process_message
64
+ expect(queue.message_count).to eq(0)
65
+ end
66
+
67
+ def process_message
68
+ release_consume_lock
69
+ sleep default_sleep
70
+ end
71
+
72
+ def deliver_message
73
+ channel.default_exchange.publish('{}', routing_key: destination)
74
+ end
75
+
76
+ def wait_until_released
77
+ mutex.synchronize { consume_lock.wait(mutex) }
78
+ end
79
+
80
+ def release_consume_lock
81
+ mutex.synchronize { consume_lock.broadcast }
82
+ end
23
83
  end
24
84
  end
@@ -13,12 +13,12 @@ describe Freddy::ResponderHandler do
13
13
  count = 0
14
14
 
15
15
  consumer_handler = freddy.respond_to destination do
16
- sleep 0.1
16
+ sleep 0.3
17
17
  count += 1
18
18
  end
19
19
  deliver
20
20
 
21
- sleep 0.05
21
+ sleep 0.15
22
22
  consumer_handler.shutdown
23
23
 
24
24
  expect(count).to eq(1)
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'hamster/experimental/mutable_set'
2
3
 
3
4
  describe 'Concurrency' do
4
5
  let(:freddy1) { Freddy.build(logger, config) }
@@ -88,7 +89,7 @@ describe 'Concurrency' do
88
89
  context 'concurrent executions of deliver_with_response' do
89
90
  let(:nr_of_threads) { 50 }
90
91
  let(:payload) { {pay: 'load'} }
91
- let(:msg_counter) { Hamster.mutable_set }
92
+ let(:msg_counter) { Hamster::MutableSet[] }
92
93
  let(:queue_name) { random_destination }
93
94
 
94
95
  before do
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'hamster/experimental/mutable_set'
3
+
4
+ describe 'Tapping into with group identifier' do
5
+ let(:deliverer) { Freddy.build(logger, config) }
6
+ let(:responder1) { Freddy.build(logger, config) }
7
+ let(:responder2) { Freddy.build(logger, config) }
8
+
9
+ let(:destination) { random_destination }
10
+
11
+ after { [deliverer, responder1, responder2].each(&:close) }
12
+
13
+ it 'receives a message once' do
14
+ msg_counter = Hamster::MutableSet[]
15
+
16
+ group_id = arbitrary_id
17
+ responder1.tap_into(destination, group: group_id) {|msg| msg_counter << 'r1' }
18
+ responder2.tap_into(destination, group: group_id) {|msg| msg_counter << 'r2' }
19
+ deliverer.deliver(destination, {})
20
+
21
+ default_sleep
22
+ expect(msg_counter.count).to eq(1)
23
+ end
24
+ end
data/spec/spec_helper.rb CHANGED
@@ -12,7 +12,6 @@ SimpleCov.start do
12
12
  end
13
13
 
14
14
  require 'pry'
15
- require 'securerandom'
16
15
  require 'freddy'
17
16
  require 'logger'
18
17
  require 'hamster/experimental/mutable_set'
@@ -29,6 +28,10 @@ def random_destination
29
28
  SecureRandom.hex
30
29
  end
31
30
 
31
+ def arbitrary_id
32
+ SecureRandom.hex
33
+ end
34
+
32
35
  def default_sleep
33
36
  sleep 0.05
34
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freddy-jruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
- - Urmas Talimaa
7
+ - Salemove TechMovers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-01 00:00:00.000000000 Z
11
+ date: 2017-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -71,21 +71,7 @@ dependencies:
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 1.0.1.pre.rc3
75
- name: hamster
76
- prerelease: false
77
- type: :runtime
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 1.0.1.pre.rc3
83
- - !ruby/object:Gem::Dependency
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.2'
74
+ version: '0.1'
89
75
  name: thread
90
76
  prerelease: false
91
77
  type: :runtime
@@ -93,10 +79,10 @@ dependencies:
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '0.2'
82
+ version: '0.1'
97
83
  description: Messaging API
98
84
  email:
99
- - urmas.talimaa@gmail.com
85
+ - techmovers@salemove.com
100
86
  executables: []
101
87
  extensions: []
102
88
  extra_rdoc_files: []
@@ -143,6 +129,7 @@ files:
143
129
  - spec/integration/concurrency_spec.rb
144
130
  - spec/integration/logging_spec.rb
145
131
  - spec/integration/reply_spec.rb
132
+ - spec/integration/tap_into_with_group_spec.rb
146
133
  - spec/spec_helper.rb
147
134
  homepage:
148
135
  licenses:
@@ -164,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
151
  version: '0'
165
152
  requirements: []
166
153
  rubyforge_project:
167
- rubygems_version: 2.4.8
154
+ rubygems_version: 2.6.8
168
155
  signing_key:
169
156
  specification_version: 4
170
157
  summary: API for inter-application messaging supporting acknowledgements and request-response
@@ -178,4 +165,5 @@ test_files:
178
165
  - spec/integration/concurrency_spec.rb
179
166
  - spec/integration/logging_spec.rb
180
167
  - spec/integration/reply_spec.rb
168
+ - spec/integration/tap_into_with_group_spec.rb
181
169
  - spec/spec_helper.rb