la_gear 1.0.0.pre.alpha.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2d34135664854b75f8889357557d68ad4b482515
4
+ data.tar.gz: 802e22ef6a102736e54b244fa5eb38d74028fd96
5
+ SHA512:
6
+ metadata.gz: a229175adb0a558e1acf8d5f9864a2e0e73a39ce51f8764dfffb8293ff561a5d23b9bd011b015a03b84a279eb3abf4de9f4b6f7d8251843f002b0d92978e4e53
7
+ data.tar.gz: 429397c8f840c1a0f1e84f32c4fdaa7483a301d558f663415ab7069b7e27dcc6f5c4b406873bc2b8409c923eec3e661208c332c2240b4b369b08ff728df6427e
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rubocop.yml ADDED
@@ -0,0 +1,12 @@
1
+ AllCops:
2
+ Include:
3
+ Exclude:
4
+
5
+ LineLength:
6
+ Max: 99
7
+
8
+ Documentation:
9
+ Enabled: false
10
+
11
+ GlobalVars:
12
+ AllowedVariables: [$publisher]
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in la_gear.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Gabriel Chaney
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # L.A. Gear
2
+
3
+ This gem has two primary purposes:
4
+ * Allowing you to define one worker class that has your [`sneakers`](https://github.com/jondot/sneakers) worker queue configuration and the [`sidekiq`](https://github.com/mperham/sidekiq) `perform` method that actually processes the message.
5
+ * DRYing up your `sneakers` configuration by using a conventions.
6
+
7
+ Here are some other features:
8
+ * Messages are deserialized as JSON by default and the properties are passed to Sidekiq's `perform_async` method
9
+ * Out-of-the-box configuration of `sneakers` for multiple RabbitMQ subscribers
10
+ * An alternative to the `Sneakers::Publisher#publish` method that allows you to pass in more options when publishing to a RabbitMQ exchange
11
+ * Helper methods for configuring `sneakers`
12
+ * Support for configuring `sneakers` with [BigWig](http://bigwig.io/)
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'la_gear'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install la_gear
27
+
28
+ ## Usage
29
+
30
+ Instead of `include Sneakers::Worker` in your workers, use `include LaGear::Worker`. Then all of your queues and routing key bindings will automatically use an `Sneakers::Config[:app_name]` plus the class name of your worker as your queue name and the class name of your worker as the routing key. For example,
31
+ ```
32
+ Sneakers.configure app_name: 'pogs_are_awesome'
33
+
34
+ class BoKnows
35
+ include LaGear::Worker
36
+
37
+ def perform(baseball, football)
38
+ # ... message processing code ...
39
+ end
40
+ end
41
+ ```
42
+ would by default result in the following 2 queue names: `pogs_are_awesome.bo_knows` and `pogs_are_awesome.bo_knows.retry`. The default routing key would be: `bo_knows`. This allows for multiple consumer queue bindings for a direct exchange (see the Multiple Bindings section of https://www.rabbitmq.com/tutorials/tutorial-four-ruby.html). The `.retry` is for if you are using [dead letter exchanges](https://www.rabbitmq.com/dlx.html) and [message expirations](https://www.rabbitmq.com/ttl.html) to perform retries (which you should). Just call the `Sneakers::Worker#from_queue` method to override the convention-based defaults.
43
+
44
+ Also, notice in the example above that we don't define a `work` method for `Sneakers::Worker`. That's because `LaGear::Worker` defines it for you. All the method does deserialize your RabbitMQ message (defaults to JSON) and pass each of the properties as a parameters to Sidekiq's `perform_async` method to process the message. Put your message processing code in a `perform` method instead. That's the method that Sidekiq invokes when it actual processes the message that `LaGear::Worker#work` sent to it.
45
+
46
+ ### The Bus
47
+
48
+ There is also a `LaGear::Bus` class which is an alternative to the `Sneakers::Publisher`. It adds an `opts` parameter to the `publish` method, allowing you to pass the options you would pass to the `bunny` exchange publish [method](http://reference.rubybunny.info/Bunny/Exchange.html#publish-instance_method) (see http://reference.rubybunny.info/Bunny/Exchange.html#publish-instance_method for the list of options).
49
+
50
+ `LaGear::Bus` also has support for BigWig's [bi-endpoint]((https://devcenter.heroku.com/articles/rabbitmq-bigwig#provisioning-the-add-on)) configuration where they use one RabbitMQ endpoint for receiving and one for transmitting. Configure Sneaker with an `amqp` and `amqp_publish` to get this working. Or you can just use the `LaGear::SneakersConfigurer.configure_bi_amqp_endpoints` convience method. Here's an example for a Heroku app:
51
+ ```
52
+ if ENV['RABBITMQ_BIGWIG_RX_URL'] && ENV['RABBITMQ_BIGWIG_TX_URL']
53
+ LaGear::SneakersConfigurer.configure_bi_amqp_endpoints(
54
+ ENV['RABBITMQ_BIGWIG_RX_URL'],
55
+ ENV['RABBITMQ_BIGWIG_TX_URL']
56
+ )
57
+ end
58
+ # else Sneakers/Bunny just uses the default RabbitMQ endpoint (amqp://localhost:15672)
59
+ ```
60
+
61
+ The reason I call it a "bus" is because I want to end up adding bus-style semantic methods to it besides publish similar to the methods in NServiceBus's [`IBus`](https://github.com/Particular/NServiceBus/blob/develop/src/NServiceBus.Core/IBus.cs) (see also [`ISendOnlyBus`](https://github.com/Particular/NServiceBus/blob/develop/src/NServiceBus.Core/ISendOnlyBus.cs)).
62
+
63
+ ## Known Issues
64
+
65
+ * For workers in a Rails 3.2 app I have, I had to explicilty include `Sneakers::Worker` and `Sidekiq::Worker` before `LaGear::Worker` because of an issue with it complaing that the `include` method was private in the Rails environment (see [here](https://github.com/gabrieljoelc/la_gear/blob/master/lib/la_gear/worker.rb#L6) for the current workaround). Here's what your workers should look like if this is happening to you:
66
+ ```
67
+ class BoKnows
68
+ include Sneakers::Worker unless LaGear::Worker.sidekiq_proc?
69
+ include Sidekiq::Worker
70
+ include LaGear::Worker
71
+
72
+ def perform(baseball, football)
73
+ # ... your worker code ...
74
+ end
75
+ end
76
+ ```
77
+
78
+ ## Contributing
79
+
80
+ 1. Fork it ( https://github.com/[my-github-username]/la_gear/fork )
81
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
82
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
83
+ 4. Push to the branch (`git push origin my-new-feature`)
84
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/la_gear.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'la_gear/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'la_gear'
8
+ spec.version = LaGear::VERSION
9
+ spec.authors = ['Gabriel Chaney']
10
+ spec.email = ['gabriel.chaney@gmail.com']
11
+ spec.summary = %q{A thin abstraction on-top-of [sneakers](https://github.com/jondot/sneakers) to DRY your workers. Pump it up!}
12
+ #spec.description = %q{This gem allows you to DRY up your [sneakers](https://github.com/jondot/sneakers) workers by using a conventions-based configuration. It also includes a `LaGear::Bus` class that allows you to pass in more options when publishing to an exchange.}
13
+ spec.homepage = 'https://github.com/giftcardzen/la_gear'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/).reject{|f| f == 'Gemfile.lock'}
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+ spec.add_dependency 'json', '~> 1.8'
21
+ spec.add_dependency 'bunny', '~> 1.6.3'
22
+ spec.add_dependency 'sneakers', '~> 1.0'
23
+ spec.add_dependency 'activesupport', '~> 4.2'
24
+ spec.add_dependency 'sidekiq', '~> 3.3'
25
+ spec.add_dependency 'connection_pool', '~> 2.1'
26
+
27
+ spec.add_development_dependency 'rake', '~> 10.4'
28
+ end
@@ -0,0 +1,23 @@
1
+ module LaGear
2
+ module ActiveRecord
3
+ module PublishTriggerable
4
+ def publish_after_commit(routing_key, opts)
5
+ publish_method = "publish_#{routing_key}"
6
+ define_method publish_method do
7
+ message = block_given? ? yield(self) : {}
8
+ Bus.publish(routing_key.to_s, message)
9
+ end
10
+ after_commit publish_method, opts
11
+ end
12
+
13
+ def send_after_commit(routing_key, opts)
14
+ publish_method = "publish_#{routing_key}"
15
+ define_method publish_method do
16
+ message = block_given? ? yield(self) : {}
17
+ Bus.publish_local(routing_key.to_s, message)
18
+ end
19
+ after_commit publish_method, opts
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1 @@
1
+ require 'la_gear/active_record/publish_triggerable'
@@ -0,0 +1,50 @@
1
+ module LaGear
2
+ module Bus
3
+ def init_pool(size = ::Sidekiq.options[:concurrency],
4
+ timeout = 3)
5
+ $publisher = ConnectionPool.new(
6
+ size: size,
7
+ timeout: timeout
8
+ ) { ::LaGear::Publisher.new }
9
+
10
+ $publisher.with do |bus|
11
+ puts "Has the bus arrived? #{bus.send(:serialize, ❨╯°□°❩╯︵┻━┻: 'Calm down, bro')}"
12
+ end
13
+ end
14
+ module_function :init_pool
15
+
16
+ def publish(routing_key, msg, bunny_opts = {}, sidekiq_opts = {})
17
+ DelayablePublisher.sidekiq_delay(sidekiq_opts).publish(routing_key, msg, bunny_opts)
18
+ end
19
+ module_function :publish
20
+
21
+ def publish_in(interval, routing_key, msg, bunny_opts = {}, sidekiq_opts = {})
22
+ DelayablePublisher.sidekiq_delay_for(interval, sidekiq_opts).publish(routing_key, msg, bunny_opts)
23
+ end
24
+ module_function :publish_in
25
+
26
+ def publish_at(timestamp, routing_key, msg, bunny_opts = {}, sidekiq_opts = {})
27
+ DelayablePublisher.sidekiq_delay_until(timestamp, sidekiq_opts).publish(routing_key, msg, bunny_opts)
28
+ end
29
+ module_function :publish_at
30
+
31
+ def publish_local(routing_key, msg)
32
+ routing_key.classify.constantize.perform_async(*msg.values)
33
+ end
34
+ module_function :publish_local
35
+
36
+ private
37
+
38
+ class DelayablePublisher
39
+ def self.publish(routing_key, msg, opts = {})
40
+ if $publisher
41
+ $publisher.with do |publisher|
42
+ publisher.publish(routing_key, msg, opts)
43
+ end
44
+ else # this is what integration tests might use
45
+ LaGear::Publisher.new.publish(routing_key, msg, opts)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ module LaGear
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,39 @@
1
+ module LaGear
2
+ class Publisher < ::Sneakers::Publisher
3
+ attr_accessor :exchange
4
+
5
+ def publish(routing_key, msg, opts = {})
6
+ @mutex.synchronize do
7
+ ensure_connection! unless connected?
8
+ end
9
+ opts.merge! routing_key: routing_key
10
+ serialized_msg = serialize(msg)
11
+ @exchange.publish(serialized_msg, opts)
12
+ end
13
+
14
+ protected
15
+
16
+ def serialize(msg)
17
+ JSON.generate(msg)
18
+ end
19
+
20
+ private
21
+
22
+ def ensure_connection!
23
+ opts = { heartbeat: @opts[:heartbeat] }
24
+ opts.merge!(vhost: @opts[:vhost]) if @opts[:vhost]
25
+ @bunny = Bunny.new(@opts[:amqp_publish] || @opts[:amqp], opts)
26
+ @bunny.start
27
+ @channel = @bunny.create_channel
28
+ @exchange = @channel.exchange(
29
+ @opts[:exchange],
30
+ type: @opts[:exchange_type],
31
+ durable: @opts[:durable]
32
+ )
33
+ end
34
+
35
+ def connected?
36
+ @bunny && @bunny.connected?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ module LaGear
2
+ class SneakersConfigurer
3
+ class << self
4
+ def configure_bi_amqp_endpoints(rx_uri_str, tx_uri_str)
5
+ parser = UriParser.new(rx_uri_str)
6
+ Sneakers.configure(
7
+ amqp: parser.amqp,
8
+ vhost: parser.vhost
9
+ )
10
+ parser = UriParser.new(tx_uri_str)
11
+ Sneakers.configure(
12
+ amqp_publish: parser.amqp,
13
+ vhost_publish: parser.vhost
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ module LaGear
2
+ class UriParser
3
+ def initialize(uri_str)
4
+ @uri = URI(uri_str)
5
+ end
6
+
7
+ def amqp
8
+ "#{@uri.scheme}://#{@uri.userinfo}@#{@uri.host}:#{@uri.port}"
9
+ end
10
+
11
+ def vhost
12
+ @uri.path.gsub!(/^\//, '')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module LaGear
2
+ VERSION = '1.0.0-alpha.1'
3
+ end
@@ -0,0 +1,69 @@
1
+ module LaGear
2
+ module Worker
3
+ def self.included(base)
4
+ # for some reason, Rails is complaining about include being private so this
5
+ # include isn't working. Add include Sneakers::Worker to Rails workers for now...
6
+
7
+ if sidekiq_proc?
8
+ base.extend(DefaultClassMethods)
9
+ else
10
+ base.include(Sneakers::Worker) if base.respond_to?(:include)
11
+ base.extend(SneakersClassMethods)
12
+ Sneakers.logger.debug "#{}"
13
+ base.from_queue base.default_queue_name, base.default_queue_opts
14
+ end
15
+ base.include(::Sidekiq::Worker) if base.respond_to?(:include)
16
+ end
17
+
18
+ class << self
19
+ def sidekiq_proc?
20
+ $0.ends_with?('sidekiq')
21
+ end
22
+ end
23
+
24
+ module SneakersClassMethods
25
+ def default_queue_name
26
+ "#{Sneakers::Config.fetch(:app_name, 'sneakers_app').underscore}.#{routing_key}"
27
+ end
28
+
29
+ def default_queue_opts
30
+ {
31
+ routing_key: [routing_key, retry_routing_key],
32
+ arguments: default_queue_args,
33
+ handler_opts: {
34
+ routing_key: retry_routing_key
35
+ }
36
+ }
37
+ end
38
+
39
+ def routing_key
40
+ # TODO: the splitting is a semantic smell...
41
+ name.split('::').last.underscore
42
+ end
43
+
44
+ def retry_routing_key
45
+ "#{default_queue_name}.retry"
46
+ end
47
+
48
+ def default_queue_args
49
+ { 'x-dead-letter-exchange' => "#{Sneakers::Config.fetch(:exchange, 'sneakers').underscore}.retry" }
50
+ end
51
+ end
52
+
53
+ module DefaultClassMethods
54
+ def from_queue(_dummy_name, _dummy_opts); end
55
+
56
+ SneakersClassMethods.instance_methods(false).each { |m| define_method(m) { {} } }
57
+ end
58
+
59
+ def work(msg)
60
+ msg = deserialize(msg)
61
+ self.class.perform_async(*msg.values)
62
+ ack!
63
+ end
64
+
65
+ def deserialize(msg)
66
+ JSON.parse(msg)
67
+ end
68
+ end
69
+ end
data/lib/la_gear.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'la_gear/version'
2
+
3
+ require 'json'
4
+ require 'active_support/inflector'
5
+ require 'bunny'
6
+
7
+ require 'sneakers'
8
+ require 'sneakers/worker'
9
+ require 'la_gear/worker'
10
+ require 'la_gear/publisher'
11
+ require 'la_gear/bus'
12
+ require 'la_gear/uri_parser'
13
+ require 'la_gear/sneakers_configurer'
14
+
15
+ module LaGear
16
+ module Rails
17
+ if defined? ::Rails::Engine
18
+ require 'la_gear/engine'
19
+ end
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: la_gear
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre.alpha.1
5
+ platform: ruby
6
+ authors:
7
+ - Gabriel Chaney
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bunny
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.6.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.6.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: sneakers
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sidekiq
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.3'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: connection_pool
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.4'
111
+ description:
112
+ email:
113
+ - gabriel.chaney@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rubocop.yml"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - la_gear.gemspec
125
+ - lib/la_gear.rb
126
+ - lib/la_gear/active_record.rb
127
+ - lib/la_gear/active_record/publish_triggerable.rb
128
+ - lib/la_gear/bus.rb
129
+ - lib/la_gear/engine.rb
130
+ - lib/la_gear/publisher.rb
131
+ - lib/la_gear/sneakers_configurer.rb
132
+ - lib/la_gear/uri_parser.rb
133
+ - lib/la_gear/version.rb
134
+ - lib/la_gear/worker.rb
135
+ homepage: https://github.com/giftcardzen/la_gear
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.3.1
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.2.3
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: A thin abstraction on-top-of [sneakers](https://github.com/jondot/sneakers)
159
+ to DRY your workers. Pump it up!
160
+ test_files: []
161
+ has_rdoc: