active_publisher 0.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee4c49a24442766e89184aa8428e5adbb0935010
4
+ data.tar.gz: fd049fe585ea4a0fc595d64ea549e34440199dd8
5
+ SHA512:
6
+ metadata.gz: 5f34ecb294d6d101c1ca84f457c718c40f596fd0187ce887449a74abbb3d70cb6a86970cdb16f412210b95e46006afd8e5e4ffd39a3ad834ddf73b851d45919f
7
+ data.tar.gz: 2acc37311bd40d1fcad6758cd02c5e4c785e05d0151f6afbb5f9a3bc3964042e3c92ee41a36ccd8a254bc1c4dbee2da5d19e64785064f085908078d40d94b855
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ - jruby-1.7
7
+ - jruby-9.0.4.0
8
+ - jruby-head
9
+ services:
10
+ - rabbitmq
11
+ sudo: false
12
+ cache: bundler
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: jruby-head
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in active_publisher.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Michael Ries
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,41 @@
1
+ # ActivePublisher
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/active_publisher`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'active_publisher'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install active_publisher
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/active_publisher. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'active_publisher/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "active_publisher"
8
+ spec.version = ActivePublisher::VERSION
9
+ spec.authors = ["Brian Stien","Adam Hutchison","Brandon Dewitt","Devin Christensen","Michael Ries"]
10
+ spec.email = ["brianastien@gmail.com","liveh2o@gmail.com","brandonsdewitt@gmail.com","quixoten@gmail.com","michael@riesd.com"]
11
+ spec.description = %q{A library for publshing messages to RabbitMQ}
12
+ spec.summary = %q{Aims to make publishing work across MRI and jRuby painless and add some nice features like automatially publishing lifecycle events for ActiveRecord models.}
13
+ spec.homepage = "https://github.com/mxenabled/active_publisher"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+
22
+ if ENV['PLATFORM'] == "java" || ::RUBY_PLATFORM == 'java'
23
+ spec.platform = "java"
24
+ spec.add_dependency 'march_hare', '~> 2.7'
25
+ else
26
+ spec.add_dependency 'bunny', '~> 2.1'
27
+ end
28
+
29
+ spec.add_development_dependency "bundler"
30
+ spec.add_development_dependency "pry"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rspec", "~> 3.2"
33
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "active_publisher"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,69 @@
1
+ if ::RUBY_PLATFORM == "java"
2
+ require "march_hare"
3
+ else
4
+ require "bunny"
5
+ end
6
+ require "thread"
7
+
8
+ require "active_publisher/logging"
9
+ require "active_publisher/async"
10
+ require "active_publisher/async/in_memory_adapter"
11
+ require "active_publisher/version"
12
+ require "active_publisher/configuration"
13
+ require "active_publisher/connection"
14
+
15
+ module ActivePublisher
16
+ def self.configuration
17
+ @configuration ||= ::ActivePublisher::Configuration.new
18
+ end
19
+
20
+ def self.configure
21
+ yield(configuration) if block_given?
22
+ end
23
+
24
+ # Publish a message to RabbitMQ
25
+ #
26
+ # @param [String] route The routing key to use for this message.
27
+ # @param [String] payload The message you are sending. Should already be encoded as a string.
28
+ # @param [String] exchange The exchange you want to publish to.
29
+ # @param [Hash] options hash to set message parameters (e.g. headers)
30
+ def self.publish(route, payload, exchange_name, options = {})
31
+ with_exchange(exchange_name) do |exchange|
32
+ exchange.publish(payload, publishing_options(route, options))
33
+ end
34
+ end
35
+
36
+ def self.publishing_options(route, options = {})
37
+ options[:mandatory] = false unless options.key(:mandatory)
38
+ options[:persistent] = false unless options.key(:persistent)
39
+ options[:routing_key] = route
40
+
41
+ if ::RUBY_PLATFORM == "java"
42
+ java_options = {}
43
+ java_options[:mandatory] = options.delete(:mandatory)
44
+ java_options[:routing_key] = options.delete(:routing_key)
45
+ java_options[:properties] = options
46
+ java_options
47
+ else
48
+ options
49
+ end
50
+ end
51
+
52
+ def self.with_exchange(exchange_name)
53
+ connection = ::ActivePublisher::Connection.connection
54
+ channel = connection.create_channel
55
+ begin
56
+ channel.confirm_select if configuration.publisher_confirms
57
+ exchange = channel.topic(exchange_name)
58
+ yield(exchange)
59
+ channel.wait_for_confirms if configuration.publisher_confirms
60
+ ensure
61
+ channel.close rescue nil
62
+ end
63
+ end
64
+ end
65
+
66
+ at_exit do
67
+ ::ActivePublisher::Async.publisher_adapter.shutdown! if ::ActivePublisher::Async.publisher_adapter
68
+ ::ActivePublisher::Connection.disconnect!
69
+ end
@@ -0,0 +1,21 @@
1
+ module ActivePublisher
2
+ # Publish a message asynchronously to RabbitMQ.
3
+ #
4
+ # Asynchronous is designed to do two things:
5
+ # 1. Introduce the idea of a durable retry should the RabbitMQ connection disconnect.
6
+ # 2. Provide a higher-level pattern for fire-and-forget publishing.
7
+ #
8
+ # @param [String] route The routing key to use for this message.
9
+ # @param [String] payload The message you are sending. Should already be encoded as a string.
10
+ # @param [String] exchange The exchange you want to publish to.
11
+ # @param [Hash] options hash to set message parameters (e.g. headers).
12
+ def self.publish_async(route, payload, exchange_name, options = {})
13
+ ::ActivePublisher::Async.publisher_adapter.publish(route, payload, exchange_name, options)
14
+ end
15
+
16
+ module Async
17
+ class << self
18
+ attr_accessor :publisher_adapter
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,149 @@
1
+ module ActivePublisher
2
+ module Async
3
+ class InMemoryAdapter
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
17
+
18
+ def publish(route, payload, exchange_name, options = {})
19
+ message = ::ActivePublisher::Async::InMemoryAdapter::Message.new(route, payload, exchange_name, options)
20
+ async_queue.push(message)
21
+ nil
22
+ end
23
+
24
+ def shutdown!
25
+ max_wait_time = ::ActivePublisher.configuration.seconds_to_wait_for_graceful_shutdown
26
+ started_shutting_down_at = ::Time.now
27
+
28
+ logger.info "Draining async publisher in-memory adapter queue before shutdown. current queue size: #{async_queue.size}."
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
40
+ include ::ActivePublisher::Logging
41
+
42
+ attr_accessor :drop_messages_when_queue_full,
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
67
+
68
+ # By default we will raise an error to push the responsibility onto the caller
69
+ fail ::ActivePublisher::Async::InMemoryAdapter::UnableToPersistMessageError, "Queue is full, messages will be dropped."
70
+ end
71
+
72
+ queue.push(message)
73
+ end
74
+
75
+ def size
76
+ queue.size
77
+ end
78
+
79
+ private
80
+
81
+ def await_network_reconnect
82
+ sleep ::ActivePublisher::RabbitConnection::NETWORK_RECOVERY_INTERVAL
83
+ end
84
+
85
+ def create_and_supervise_consumer!
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
98
+ 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
+
117
+ # Requeue and try again.
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
130
+ end
131
+ 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
+
145
+ class UnableToPersistMessageError < ::StandardError
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,94 @@
1
+ require "yaml"
2
+
3
+ module ActivePublisher
4
+ class Configuration
5
+ attr_accessor :error_handler,
6
+ :heartbeat,
7
+ :host,
8
+ :hosts,
9
+ :password,
10
+ :port,
11
+ :publisher_confirms,
12
+ :seconds_to_wait_for_graceful_shutdown,
13
+ :username,
14
+ :timeout,
15
+ :virtual_host
16
+
17
+ CONFIGURATION_MUTEX = ::Mutex.new
18
+
19
+ DEFAULTS = {
20
+ :error_handler => lambda { |error, env_hash|
21
+ ::ActivePublisher::Logging.logger.error(error.class)
22
+ ::ActivePublisher::Logging.logger.error(error.message)
23
+ ::ActivePublisher::Logging.logger.error(error.backtrace.join("\n")) if error.backtrace.respond_to?(:join)
24
+ },
25
+ :heartbeat => 5,
26
+ :host => "localhost",
27
+ :hosts => [],
28
+ :port => 5672,
29
+ :publisher_confirms => false,
30
+ :seconds_to_wait_for_graceful_shutdown => 30,
31
+ :timeout => 1,
32
+ :username => "guest",
33
+ :password => "guest",
34
+ :virtual_host => "/"
35
+ }
36
+
37
+ ##
38
+ # Class Methods
39
+ #
40
+ def self.configure_from_yaml_and_cli(cli_options = {}, reload = false)
41
+ CONFIGURATION_MUTEX.synchronize do
42
+ @configure_from_yaml_and_cli = nil if reload
43
+ @configure_from_yaml_and_cli ||= begin
44
+ env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["APP_ENV"] || "development"
45
+
46
+ yaml_config = attempt_to_load_yaml_file
47
+ DEFAULTS.each_pair do |key, value|
48
+ setting = cli_options[key] || yaml_config[key.to_s]
49
+ ::ActivePublisher.config.__send__("#{key}=", setting) if setting
50
+ end
51
+
52
+ true
53
+ end
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Private class methods
59
+ #
60
+ def self.attempt_to_load_yaml_file
61
+ yaml_config = {}
62
+ absolute_config_path = ::File.expand_path(::File.join("config", "active_publisher.yml"))
63
+ action_subscriber_config_file = ::File.expand_path(::File.join("config", "action_subscriber.yml"))
64
+ if ::File.exists?(absolute_config_path)
65
+ yaml_config = ::YAML.load_file(absolute_config_path)[env]
66
+ elsif ::File.exists?(action_subscriber_config_file)
67
+ yaml_config = ::YAML.load_file(action_subscriber_config_file)[env]
68
+ end
69
+ yaml_config
70
+ end
71
+ private_class_method :attempt_to_load_yaml_file
72
+
73
+ ##
74
+ # Instance Methods
75
+ #
76
+ def initialize
77
+ DEFAULTS.each_pair do |key, value|
78
+ self.__send__("#{key}=", value)
79
+ end
80
+ end
81
+
82
+ def connection_string=(url)
83
+ settings = ::ActionSubscriber::URI.parse_amqp_url(url)
84
+ settings.each do |key, value|
85
+ send("#{key}=", value)
86
+ end
87
+ end
88
+
89
+ def hosts
90
+ return @hosts if @hosts.size > 0
91
+ [ host ]
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,54 @@
1
+ require 'thread'
2
+
3
+ module ActivePublisher
4
+ module Connection
5
+ CONNECTION_MUTEX = ::Mutex.new
6
+ NETWORK_RECOVERY_INTERVAL = 1.freeze
7
+
8
+ def self.connected?
9
+ connection.try(:connected?)
10
+ end
11
+
12
+ def self.connection
13
+ CONNECTION_MUTEX.synchronize do
14
+ return @connection if @connection
15
+ @connection = create_connection
16
+ end
17
+ end
18
+
19
+ def self.disconnect!
20
+ CONNECTION_MUTEX.synchronize do
21
+ if @connection && @connection.connected?
22
+ @connection.close
23
+ end
24
+
25
+ @connection = nil
26
+ end
27
+ end
28
+
29
+ # Private API
30
+ def self.create_connection
31
+ if ::RUBY_PLATFORM == "java"
32
+ connection = ::MarchHare.connect(connection_options)
33
+ else
34
+ connection = ::Bunny.new(connection_options)
35
+ connection.start
36
+ connection
37
+ end
38
+ end
39
+ private_class_method :create_connection
40
+
41
+ def self.connection_options
42
+ {
43
+ :heartbeat => ::ActivePublisher.configuration.heartbeat,
44
+ :hosts => ::ActivePublisher.configuration.hosts,
45
+ :port => ::ActivePublisher.configuration.port,
46
+ :continuation_timeout => ::ActivePublisher.configuration.timeout * 1_000.0, #convert sec to ms
47
+ :automatically_recover => true,
48
+ :network_recovery_interval => NETWORK_RECOVERY_INTERVAL,
49
+ :recover_from_connection_close => true,
50
+ }
51
+ end
52
+ private_class_method :connection_options
53
+ end
54
+ end
@@ -0,0 +1,27 @@
1
+ # Taken from https://github.com/mperham/sidekiq/blob/7f882787e53d234042ff18099241403300a47585/lib/sidekiq/logging.rb
2
+ require "time"
3
+ require "logger"
4
+
5
+ module ActivePublisher
6
+ module Logging
7
+ def self.initialize_logger(log_target = STDOUT)
8
+ oldlogger = defined?(@logger) ? @logger : nil
9
+ @logger = Logger.new(log_target)
10
+ @logger.level = Logger::INFO
11
+ oldlogger.close if oldlogger && !$TESTING # don't want to close testing's STDOUT logging
12
+ @logger
13
+ end
14
+
15
+ def self.logger
16
+ defined?(@logger) ? @logger : initialize_logger
17
+ end
18
+
19
+ def self.logger=(log)
20
+ @logger = (log ? log : Logger.new("/dev/null"))
21
+ end
22
+
23
+ def logger
24
+ ::ActivePublisher::Logging.logger
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module ActivePublisher
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_publisher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: java
6
+ authors:
7
+ - Brian Stien
8
+ - Adam Hutchison
9
+ - Brandon Dewitt
10
+ - Devin Christensen
11
+ - Michael Ries
12
+ autorequire:
13
+ bindir: exe
14
+ cert_chain: []
15
+ date: 2016-03-16 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.7'
23
+ name: march_hare
24
+ prerelease: false
25
+ type: :runtime
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
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'
37
+ name: bundler
38
+ prerelease: false
39
+ type: :development
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ - !ruby/object:Gem::Dependency
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ name: pry
52
+ prerelease: false
53
+ type: :development
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ - !ruby/object:Gem::Dependency
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '10.0'
65
+ name: rake
66
+ prerelease: false
67
+ type: :development
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: '10.0'
73
+ - !ruby/object:Gem::Dependency
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "~>"
77
+ - !ruby/object:Gem::Version
78
+ version: '3.2'
79
+ name: rspec
80
+ prerelease: false
81
+ type: :development
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '3.2'
87
+ description: A library for publshing messages to RabbitMQ
88
+ email:
89
+ - brianastien@gmail.com
90
+ - liveh2o@gmail.com
91
+ - brandonsdewitt@gmail.com
92
+ - quixoten@gmail.com
93
+ - michael@riesd.com
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files: []
97
+ files:
98
+ - ".gitignore"
99
+ - ".rspec"
100
+ - ".travis.yml"
101
+ - CODE_OF_CONDUCT.md
102
+ - Gemfile
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - active_publisher.gemspec
107
+ - bin/console
108
+ - bin/setup
109
+ - lib/active_publisher.rb
110
+ - lib/active_publisher/async.rb
111
+ - lib/active_publisher/async/in_memory_adapter.rb
112
+ - lib/active_publisher/configuration.rb
113
+ - lib/active_publisher/connection.rb
114
+ - lib/active_publisher/logging.rb
115
+ - lib/active_publisher/version.rb
116
+ homepage: https://github.com/mxenabled/active_publisher
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.5.0
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Aims to make publishing work across MRI and jRuby painless and add some nice features like automatially publishing lifecycle events for ActiveRecord models.
140
+ test_files: []