active_publisher 0.1.5-java → 0.2.0.pre-java
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 +4 -4
- data/.gitignore +1 -0
- data/README.md +68 -1
- data/active_publisher.gemspec +2 -0
- data/lib/active_publisher/async/in_memory_adapter/async_queue.rb +61 -0
- data/lib/active_publisher/async/in_memory_adapter/consumer_thread.rb +89 -0
- data/lib/active_publisher/async/in_memory_adapter.rb +31 -125
- data/lib/active_publisher/connection.rb +2 -0
- data/lib/active_publisher/message.rb +3 -0
- data/lib/active_publisher/version.rb +1 -1
- data/lib/active_publisher.rb +23 -0
- metadata +22 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63df17dc2a58125dcc18b1cb9c7d20f0517da0ac
|
4
|
+
data.tar.gz: 9bd8dcd05da48bde7c14ff49a3dc10928ab609a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8dbdc550e66d0d4182ed96333a03e37ab89466371bc3bc4634ff6d78e1f02e8daeafb5ed3b13f0bc3cb91d793af46ee6954ba2519e148122d8b2dde569a025c
|
7
|
+
data.tar.gz: d6a7965709096d9f9828afe0655982aaa5ddafa87b3256e44d6c815df4b6467af64bd0236d5f3c49edb9dd366f28dbb2e3011c1373ebd86a8ea9928bf8418bb6
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -20,9 +20,76 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
$ gem install active_publisher
|
22
22
|
|
23
|
+
## Configuration
|
24
|
+
|
25
|
+
ActivePublisher will use a `config/active_publisher.yml` or `config/action_subscriber.yml` automatically.
|
26
|
+
|
27
|
+
Create a `config/active_publisher.yml` similar to a database.yml, with your configuration nested in your environments keys.
|
28
|
+
|
29
|
+
```yaml
|
30
|
+
default: &default
|
31
|
+
host: localhost
|
32
|
+
username: guest
|
33
|
+
password: guest
|
34
|
+
|
35
|
+
development:
|
36
|
+
<<: *default
|
37
|
+
|
38
|
+
test:
|
39
|
+
<<: *default
|
40
|
+
|
41
|
+
production:
|
42
|
+
<<: *default
|
43
|
+
host: <%= ENV['RABBIT_MQ_HOST'] %>
|
44
|
+
username: <%= ENV['RABBIT_MQ_USERNAME'] %>
|
45
|
+
password: <%= ENV['RABBIT_MQ_PASSWORD'] %>
|
46
|
+
```
|
47
|
+
|
48
|
+
Defaults for the configuration are:
|
49
|
+
```ruby
|
50
|
+
{
|
51
|
+
:heartbeat => 5,
|
52
|
+
:host => "localhost",
|
53
|
+
:hosts => [],
|
54
|
+
:port => 5672,
|
55
|
+
:publisher_confirms => false,
|
56
|
+
:seconds_to_wait_for_graceful_shutdown => 30,
|
57
|
+
:timeout => 1,
|
58
|
+
:username => "guest",
|
59
|
+
:password => "guest",
|
60
|
+
:virtual_host => "/"
|
61
|
+
}
|
62
|
+
```
|
63
|
+
|
23
64
|
## Usage
|
24
65
|
|
25
|
-
|
66
|
+
Basic publishing is simple.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
# @param [String] route The routing key to use for this message.
|
70
|
+
# @param [String] payload The message you are sending. Should already be encoded as a string.
|
71
|
+
# @param [String] exchange The exchange you want to publish to.
|
72
|
+
# @param [Hash] options hash to set message parameters (e.g. headers)
|
73
|
+
|
74
|
+
::ActivePublisher.publish("user.created", user.to_json, "events", {})
|
75
|
+
```
|
76
|
+
|
77
|
+
|
78
|
+
Async publishing is as simple as configuring the async publishing adapter and running `publish_sync` the same was as publish.
|
79
|
+
You can use the `::ActivePublisher::Async::InMemoryAdapter` that ships with `ActivePublisher`.
|
80
|
+
|
81
|
+
|
82
|
+
`initializers/active_publisher.rb`
|
83
|
+
```ruby
|
84
|
+
require "active_publisher"
|
85
|
+
::ActivePublisher::Async.publisher_adapter = ::ActivePublisher::Async::InMemoryAdapter.new
|
86
|
+
|
87
|
+
```
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
::ActivePublisher.publish_async("user.created", user.to_json, "events", {})
|
91
|
+
```
|
92
|
+
|
26
93
|
|
27
94
|
## Development
|
28
95
|
|
data/active_publisher.gemspec
CHANGED
@@ -26,6 +26,8 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_dependency 'bunny', '~> 2.1'
|
27
27
|
end
|
28
28
|
|
29
|
+
spec.add_dependency 'multi_op_queue', '>= 0.1.2'
|
30
|
+
|
29
31
|
spec.add_development_dependency "bundler"
|
30
32
|
spec.add_development_dependency "pry"
|
31
33
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module ActivePublisher
|
2
|
+
module Async
|
3
|
+
module InMemoryAdapter
|
4
|
+
class AsyncQueue
|
5
|
+
include ::ActivePublisher::Logging
|
6
|
+
|
7
|
+
attr_accessor :drop_messages_when_queue_full,
|
8
|
+
:max_queue_size,
|
9
|
+
:supervisor_interval
|
10
|
+
|
11
|
+
attr_reader :consumer, :queue, :supervisor
|
12
|
+
|
13
|
+
def initialize(drop_messages_when_queue_full, max_queue_size, supervisor_interval)
|
14
|
+
@drop_messages_when_queue_full = drop_messages_when_queue_full
|
15
|
+
@max_queue_size = max_queue_size
|
16
|
+
@supervisor_interval = supervisor_interval
|
17
|
+
@queue = ::MultiOpQueue::Queue.new
|
18
|
+
create_and_supervise_consumer!
|
19
|
+
end
|
20
|
+
|
21
|
+
def push(message)
|
22
|
+
# default of 1_000_000 messages
|
23
|
+
if queue.size > max_queue_size
|
24
|
+
# Drop messages if the queue is full and we were configured to do so
|
25
|
+
return if drop_messages_when_queue_full
|
26
|
+
|
27
|
+
# By default we will raise an error to push the responsibility onto the caller
|
28
|
+
fail ::ActivePublisher::Async::InMemoryAdapter::UnableToPersistMessageError, "Queue is full, messages will be dropped."
|
29
|
+
end
|
30
|
+
|
31
|
+
queue.push(message)
|
32
|
+
end
|
33
|
+
|
34
|
+
def size
|
35
|
+
queue.size
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def create_and_supervise_consumer!
|
41
|
+
@consumer = ::ActivePublisher::Async::InMemoryAdapter::ConsumerThread.new(queue)
|
42
|
+
@supervisor = ::Thread.new do
|
43
|
+
loop do
|
44
|
+
unless consumer.alive?
|
45
|
+
# We might need to requeue the last messages popped
|
46
|
+
current_consumer_messages = consumer.current_messages
|
47
|
+
queue.concat(current_consumer_messages) unless current_consumer_messages.empty?
|
48
|
+
consumer.kill
|
49
|
+
@consumer = ::ActivePublisher::Async::InMemoryAdapter::ConsumerThread.new(queue)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Pause before checking the consumer again.
|
53
|
+
sleep supervisor_interval
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ActivePublisher
|
2
|
+
module Async
|
3
|
+
module InMemoryAdapter
|
4
|
+
class ConsumerThread
|
5
|
+
attr_reader :current_messages, :thread, :queue
|
6
|
+
|
7
|
+
if ::RUBY_PLATFORM == "java"
|
8
|
+
NETWORK_ERRORS = [::MarchHare::Exception, ::Java::ComRabbitmqClient::AlreadyClosedException, ::Java::JavaIo::IOException].freeze
|
9
|
+
else
|
10
|
+
NETWORK_ERRORS = [::Bunny::Exception, ::Timeout::Error, ::IOError].freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(listen_queue)
|
14
|
+
@current_messages = []
|
15
|
+
@queue = listen_queue
|
16
|
+
start_thread
|
17
|
+
end
|
18
|
+
|
19
|
+
def alive?
|
20
|
+
@thread && @thread.alive?
|
21
|
+
end
|
22
|
+
|
23
|
+
def kill
|
24
|
+
@thread.kill if @thread
|
25
|
+
@thread = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def await_network_reconnect
|
31
|
+
if defined?(ActivePublisher::RabbitConnection)
|
32
|
+
sleep ::ActivePublisher::RabbitConnection::NETWORK_RECOVERY_INTERVAL
|
33
|
+
else
|
34
|
+
sleep 0.1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def start_thread
|
39
|
+
return if alive?
|
40
|
+
@thread = ::Thread.new do
|
41
|
+
loop do
|
42
|
+
# Write "current_messages" so we can requeue should something happen to the consumer.
|
43
|
+
@current_messages.concat(queue.pop_up_to(20))
|
44
|
+
|
45
|
+
begin
|
46
|
+
# Only open a single connection for each group of messages to an exchange
|
47
|
+
messages_to_retry = []
|
48
|
+
@current_messages.group_by(&:exchange_name).each do |exchange_name, messages|
|
49
|
+
begin
|
50
|
+
::ActivePublisher.publish_all(exchange_name, messages)
|
51
|
+
ensure
|
52
|
+
messages_to_retry.concat(messages)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Reset
|
57
|
+
@current_messages = []
|
58
|
+
rescue *NETWORK_ERRORS
|
59
|
+
# Sleep because connection is down
|
60
|
+
await_network_reconnect
|
61
|
+
@current_messages.concat(messages_to_retry)
|
62
|
+
|
63
|
+
# Requeue and try again.
|
64
|
+
queue.concat(@current_messages) unless @current_messages.empty?
|
65
|
+
rescue => unknown_error
|
66
|
+
@current_messages.concat(messages_to_retry)
|
67
|
+
@current_messages.each do |message|
|
68
|
+
# Degrade to single message publish ... or at least attempt to
|
69
|
+
begin
|
70
|
+
::ActivePublisher.publish(message.route, message.payload, message.exchange_name, message.options)
|
71
|
+
rescue => error
|
72
|
+
::ActivePublisher.configuration.error_handler.call(unknown_error, {:route => message.route, :payload => message.payload, :exchange_name => message.exchange_name, :options => message.options})
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Do not requeue the message because something else horrible happened.
|
77
|
+
@current_messages = []
|
78
|
+
|
79
|
+
# TODO: Find a way to bubble this out of the thread for logging purposes.
|
80
|
+
# Reraise the error out of the publisher loop. The Supervisor will restart the consumer.
|
81
|
+
raise unknown_error
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -1,148 +1,54 @@
|
|
1
|
+
require "active_publisher/message"
|
2
|
+
require "active_publisher/async/in_memory_adapter/async_queue"
|
3
|
+
require "active_publisher/async/in_memory_adapter/consumer_thread"
|
4
|
+
require "multi_op_queue"
|
5
|
+
|
1
6
|
module ActivePublisher
|
2
7
|
module Async
|
3
|
-
|
4
|
-
include ::ActivePublisher::Logging
|
5
|
-
|
6
|
-
attr_reader :async_queue
|
7
|
-
|
8
|
-
def initialize(drop_messages_when_queue_full = false, max_queue_size = 1_000_000, supervisor_interval = 0.2)
|
9
|
-
logger.info "Starting in-memory publisher adapter"
|
10
|
-
|
11
|
-
@async_queue = ::ActivePublisher::Async::InMemoryAdapter::AsyncQueue.new(
|
12
|
-
drop_messages_when_queue_full,
|
13
|
-
max_queue_size,
|
14
|
-
supervisor_interval
|
15
|
-
)
|
16
|
-
end
|
8
|
+
module InMemoryAdapter
|
17
9
|
|
18
|
-
def
|
19
|
-
|
20
|
-
async_queue.push(message)
|
21
|
-
nil
|
10
|
+
def self.new(*args)
|
11
|
+
::ActivePublisher::Async::InMemoryAdapter::Adapter.new(*args)
|
22
12
|
end
|
23
13
|
|
24
|
-
|
25
|
-
max_wait_time = ::ActivePublisher.configuration.seconds_to_wait_for_graceful_shutdown
|
26
|
-
started_shutting_down_at = ::Time.now
|
14
|
+
class UnableToPersistMessageError < ::StandardError; end
|
27
15
|
|
28
|
-
|
29
|
-
while async_queue.size > 0
|
30
|
-
if (::Time.now - started_shutting_down_at) > max_wait_time
|
31
|
-
logger.info "Forcing async publisher adapter shutdown because graceful shutdown period of #{max_wait_time} seconds was exceeded. Current queue size: #{async_queue.size}."
|
32
|
-
break
|
33
|
-
end
|
34
|
-
|
35
|
-
sleep 0.1
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class AsyncQueue
|
16
|
+
class Adapter
|
40
17
|
include ::ActivePublisher::Logging
|
41
18
|
|
42
|
-
|
43
|
-
:max_queue_size,
|
44
|
-
:supervisor_interval
|
45
|
-
|
46
|
-
attr_reader :consumer, :queue, :supervisor
|
47
|
-
|
48
|
-
if ::RUBY_PLATFORM == "java"
|
49
|
-
NETWORK_ERRORS = [::MarchHare::Exception, ::Java::ComRabbitmqClient::AlreadyClosedException, ::Java::JavaIo::IOException].freeze
|
50
|
-
else
|
51
|
-
NETWORK_ERRORS = [::Bunny::Exception, ::Timeout::Error, ::IOError].freeze
|
52
|
-
end
|
53
|
-
|
54
|
-
def initialize(drop_messages_when_queue_full, max_queue_size, supervisor_interval)
|
55
|
-
@drop_messages_when_queue_full = drop_messages_when_queue_full
|
56
|
-
@max_queue_size = max_queue_size
|
57
|
-
@supervisor_interval = supervisor_interval
|
58
|
-
@queue = ::Queue.new
|
59
|
-
create_and_supervise_consumer!
|
60
|
-
end
|
61
|
-
|
62
|
-
def push(message)
|
63
|
-
# default of 1_000_000 messages
|
64
|
-
if queue.size > max_queue_size
|
65
|
-
# Drop messages if the queue is full and we were configured to do so
|
66
|
-
return if drop_messages_when_queue_full
|
19
|
+
attr_reader :async_queue
|
67
20
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
21
|
+
def initialize(drop_messages_when_queue_full = false, max_queue_size = 1_000_000, supervisor_interval = 0.2)
|
22
|
+
logger.info "Starting in-memory publisher adapter"
|
71
23
|
|
72
|
-
|
24
|
+
@async_queue = ::ActivePublisher::Async::InMemoryAdapter::AsyncQueue.new(
|
25
|
+
drop_messages_when_queue_full,
|
26
|
+
max_queue_size,
|
27
|
+
supervisor_interval
|
28
|
+
)
|
73
29
|
end
|
74
30
|
|
75
|
-
def
|
76
|
-
|
31
|
+
def publish(route, payload, exchange_name, options = {})
|
32
|
+
message = ::ActivePublisher::Message.new(route, payload, exchange_name, options)
|
33
|
+
async_queue.push(message)
|
34
|
+
nil
|
77
35
|
end
|
78
36
|
|
79
|
-
|
37
|
+
def shutdown!
|
38
|
+
max_wait_time = ::ActivePublisher.configuration.seconds_to_wait_for_graceful_shutdown
|
39
|
+
started_shutting_down_at = ::Time.now
|
80
40
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
@consumer = create_consumer
|
87
|
-
@supervisor = ::Thread.new do
|
88
|
-
loop do
|
89
|
-
unless consumer.alive?
|
90
|
-
# We might need to requeue the last message.
|
91
|
-
queue.push(@current_message) unless @current_message.nil?
|
92
|
-
consumer.kill
|
93
|
-
@consumer = create_consumer
|
94
|
-
end
|
95
|
-
|
96
|
-
# Pause before checking the consumer again.
|
97
|
-
sleep supervisor_interval
|
41
|
+
logger.info "Draining async publisher in-memory adapter queue before shutdown. current queue size: #{async_queue.size}."
|
42
|
+
while async_queue.size > 0
|
43
|
+
if (::Time.now - started_shutting_down_at) > max_wait_time
|
44
|
+
logger.info "Forcing async publisher adapter shutdown because graceful shutdown period of #{max_wait_time} seconds was exceeded. Current queue size: #{async_queue.size}."
|
45
|
+
break
|
98
46
|
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def create_consumer
|
103
|
-
::Thread.new do
|
104
|
-
loop do
|
105
|
-
# Write "current_message" so we can requeue should something happen to the consumer.
|
106
|
-
@current_message = message = queue.pop
|
107
|
-
|
108
|
-
begin
|
109
|
-
::ActivePublisher.publish(message.route, message.payload, message.exchange_name, message.options)
|
110
|
-
|
111
|
-
# Reset
|
112
|
-
@current_message = nil
|
113
|
-
rescue *NETWORK_ERRORS
|
114
|
-
# Sleep because connection is down
|
115
|
-
await_network_reconnect
|
116
47
|
|
117
|
-
|
118
|
-
queue.push(message)
|
119
|
-
rescue => unknown_error
|
120
|
-
# Do not requeue the message because something else horrible happened.
|
121
|
-
@current_message = nil
|
122
|
-
|
123
|
-
::ActivePublisher.configuration.error_handler.call(unknown_error, {:route => message.route, :payload => message.payload, :exchange_name => message.exchange_name, :options => message.options})
|
124
|
-
|
125
|
-
# TODO: Find a way to bubble this out of the thread for logging purposes.
|
126
|
-
# Reraise the error out of the publisher loop. The Supervisor will restart the consumer.
|
127
|
-
raise unknown_error
|
128
|
-
end
|
129
|
-
end
|
48
|
+
sleep 0.1
|
130
49
|
end
|
131
50
|
end
|
132
|
-
end
|
133
|
-
|
134
|
-
class Message
|
135
|
-
attr_reader :route, :payload, :exchange_name, :options
|
136
|
-
|
137
|
-
def initialize(route, payload, exchange_name, options)
|
138
|
-
@route = route
|
139
|
-
@payload = payload
|
140
|
-
@exchange_name = exchange_name
|
141
|
-
@options = options
|
142
|
-
end
|
143
|
-
end
|
144
51
|
|
145
|
-
class UnableToPersistMessageError < ::StandardError
|
146
52
|
end
|
147
53
|
end
|
148
54
|
end
|
data/lib/active_publisher.rb
CHANGED
@@ -8,11 +8,15 @@ require "thread"
|
|
8
8
|
require "active_publisher/logging"
|
9
9
|
require "active_publisher/async"
|
10
10
|
require "active_publisher/async/in_memory_adapter"
|
11
|
+
require "active_publisher/message"
|
11
12
|
require "active_publisher/version"
|
12
13
|
require "active_publisher/configuration"
|
13
14
|
require "active_publisher/connection"
|
14
15
|
|
15
16
|
module ActivePublisher
|
17
|
+
class UnknownMessageClassError < StandardError; end
|
18
|
+
class ExchangeMismatchError < StandardError; end
|
19
|
+
|
16
20
|
def self.configuration
|
17
21
|
@configuration ||= ::ActivePublisher::Configuration.new
|
18
22
|
end
|
@@ -33,6 +37,25 @@ module ActivePublisher
|
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
40
|
+
def self.publish_all(exchange_name, messages)
|
41
|
+
with_exchange(exchange_name) do |exchange|
|
42
|
+
loop do
|
43
|
+
break if messages.empty?
|
44
|
+
message = messages.shift
|
45
|
+
|
46
|
+
fail ActivePublisher::UnknownMessageClassError, "bulk publish messages must be ActivePublisher::Message" unless message.is_a?(ActivePublisher::Message)
|
47
|
+
fail ActivePublisher::ExchangeMismatchError, "bulk publish messages must match publish_all exchange_name" if message.exchange_name != exchange_name
|
48
|
+
|
49
|
+
begin
|
50
|
+
exchange.publish(message.payload, publishing_options(message.route, message.options || {}))
|
51
|
+
rescue
|
52
|
+
messages << message
|
53
|
+
raise
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
36
59
|
def self.publishing_options(route, in_options = {})
|
37
60
|
options = {
|
38
61
|
:mandatory => false,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_publisher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0.pre
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Brian Stien
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: exe
|
14
14
|
cert_chain: []
|
15
|
-
date: 2016-
|
15
|
+
date: 2016-11-17 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
@@ -28,6 +28,20 @@ dependencies:
|
|
28
28
|
- - "~>"
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '2.7'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.1.2
|
37
|
+
name: multi_op_queue
|
38
|
+
prerelease: false
|
39
|
+
type: :runtime
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 0.1.2
|
31
45
|
- !ruby/object:Gem::Dependency
|
32
46
|
requirement: !ruby/object:Gem::Requirement
|
33
47
|
requirements:
|
@@ -109,9 +123,12 @@ files:
|
|
109
123
|
- lib/active_publisher.rb
|
110
124
|
- lib/active_publisher/async.rb
|
111
125
|
- lib/active_publisher/async/in_memory_adapter.rb
|
126
|
+
- lib/active_publisher/async/in_memory_adapter/async_queue.rb
|
127
|
+
- lib/active_publisher/async/in_memory_adapter/consumer_thread.rb
|
112
128
|
- lib/active_publisher/configuration.rb
|
113
129
|
- lib/active_publisher/connection.rb
|
114
130
|
- lib/active_publisher/logging.rb
|
131
|
+
- lib/active_publisher/message.rb
|
115
132
|
- lib/active_publisher/version.rb
|
116
133
|
homepage: https://github.com/mxenabled/active_publisher
|
117
134
|
licenses:
|
@@ -128,12 +145,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
145
|
version: '0'
|
129
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
147
|
requirements:
|
131
|
-
- - "
|
148
|
+
- - ">"
|
132
149
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
150
|
+
version: 1.3.1
|
134
151
|
requirements: []
|
135
152
|
rubyforge_project:
|
136
|
-
rubygems_version: 2.6.
|
153
|
+
rubygems_version: 2.6.7
|
137
154
|
signing_key:
|
138
155
|
specification_version: 4
|
139
156
|
summary: Aims to make publishing work across MRI and jRuby painless and add some nice features like automatially publishing lifecycle events for ActiveRecord models.
|