mopsy 1.0.0.pre

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: 1cd5b158ca917d57da1e100457d9a6c3d6390b36
4
+ data.tar.gz: faeecc7432c161535b1e8f4c34d45a2b0aec3355
5
+ SHA512:
6
+ metadata.gz: 2a53a2d8f5efa9b46f1130dc8ca246272e5a884c2b6f3c0ea24e119ea3c39dfd3ba1a6fce2e5d440d045567f60c521849613065b8c324e2606ed67fe1da63a1c
7
+ data.tar.gz: e62ff072e05bbb3c0ec858b18c8395f15af87826203a4339db6b8d998d9508196daa34bab603a15ef56c7df206f08e769b7d9e3bfe1ac474673d7447801fffcb
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # Ignore RVM Gemset conf
12
+ .ruby-gemset
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1 @@
1
+ 2.4.1
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.15.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in mopsy.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Gareth Jones
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,40 @@
1
+ # Mopsy
2
+
3
+ Mopsy is yet another Ruby/RabbitMQ framework. I started building it because I wanted one framework that was capable of both background job style message processing _and_ RPC message handling. I also wanted it to be less opinionated about things than Hutch, for example. Or do I just mean opinionated in my opinion? I'm not sure...
4
+
5
+ ...Anyway. Best not to try an use it just yet. It's still in dev. Ta very much.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'mopsy'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install mopsy
22
+
23
+ ## Usage
24
+
25
+ Well, don't just yet.
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]/mopsy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
40
+
@@ -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,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'mopsy'
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(__FILE__)
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mopsy'
4
+
5
+ Mopsy.configure
6
+ Mopsy::CLI.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,14 @@
1
+ class DumbJobExample
2
+ include Mopsy::Handlers::JobHandler
3
+
4
+ subscribe 'example.work.queue'
5
+
6
+ def perform(delivery_info, metadata, msg)
7
+ logger.info "DumbJobExample received:"
8
+ logger.info delivery_info
9
+ logger.info metadata
10
+ logger.info msg
11
+
12
+ (1..20).each { |i| logger.info "DumbJobExample: doing fake work #{i}"; sleep(0.5) }
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class DumbRpcExample
2
+ include Mopsy::Handlers::ActionHandler
3
+
4
+ subscribe 'example.rpc.queue'
5
+
6
+ def perform(delivery_info, metadata, msg)
7
+ logger.info "DumbRpcExample received:"
8
+ logger.info delivery_info
9
+ logger.info metadata
10
+ logger.info msg
11
+
12
+ (1..20).each { |i| logger.info "DumbRpcExample: doing fake work #{i}"; sleep(0.5) }
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ require 'mopsy/version'
2
+ require 'mopsy/conf'
3
+ require 'mopsy/cli'
4
+ require 'mopsy/concerns/logging'
5
+ require 'mopsy/handlers/loader'
6
+ require 'mopsy/handlers/handler'
7
+ require 'mopsy/handlers/action_handler'
8
+ require 'mopsy/handlers/job_handler'
9
+ require 'mopsy/handlers/run_group'
10
+ require 'mopsy/rabbit/queue'
11
+ require 'mopsy/runner'
12
+
13
+ module Mopsy
14
+ extend self
15
+
16
+ def configure
17
+ @conf = Mopsy::Conf.new
18
+ @logger = Logger.new(STDOUT)
19
+ @logger.level = Logger::DEBUG
20
+
21
+ Handlers::ActionHandler.configure_logger(@logger)
22
+ Handlers::JobHandler.configure_logger(@logger)
23
+ end
24
+
25
+ def conf
26
+ @conf
27
+ end
28
+
29
+ def logger=(logger)
30
+ @logger = logger
31
+ end
32
+
33
+ def logger
34
+ @logger
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ require 'thor'
2
+
3
+ module Mopsy
4
+ class CLI < Thor
5
+
6
+ desc 'work ExampleHandlerOne,ExampleHandlerTwo', 'Run Mopsy with specified task handler classes'
7
+ method_option :require, alises: '-r', desc: 'Comma separated file paths of your handler classes or a glob in double quotes'
8
+
9
+ def work(handlers = '')
10
+
11
+ # Attempt to load files required by the user. Silently discards missing files (due to Dir#glob call).
12
+ if options[:require]
13
+ expand_handler_paths(options[:require]).each do |r|
14
+ require_handler(r)
15
+ end
16
+ end
17
+
18
+ # Then try to find the handler classes, pack it in and go home if not.
19
+ handlers, missing = Handlers::Loader.find_handlers(handlers)
20
+
21
+ unless missing.empty?
22
+ say "Unable to find handler classes: #{missing.join(', ')}"
23
+ exit(1)
24
+ end
25
+
26
+ runner = Mopsy::Runner.new(handlers)
27
+ runner.run
28
+ end
29
+
30
+ # Force Thor to return non-zero exit code on error.
31
+ def self.exit_on_failure?
32
+ true
33
+ end
34
+
35
+ private
36
+
37
+ def expand_handler_paths(paths)
38
+ paths.split(',')
39
+ .map { |p| Dir.glob(p) }
40
+ .flatten
41
+ end
42
+
43
+ def require_handler(f)
44
+ load File.expand_path(f)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ module Mopsy
2
+ module Concerns
3
+ module Logging
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.send :define_method, :logger do
7
+ base.logger
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def logger
13
+ @logger
14
+ end
15
+
16
+ def logger=(logger)
17
+ @logger = logger
18
+ end
19
+
20
+ def configure_logger(log=nil)
21
+ if log
22
+ @logger = log
23
+ else
24
+ @logger = Logger.new(STDOUT)
25
+ @logger.level = Logger::DEBUG
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,52 @@
1
+ require 'forwardable'
2
+
3
+ module Mopsy
4
+ class Conf
5
+ extend Forwardable
6
+ def_delegators :@hash, :delete, :fetch, :has_key?, :merge, :to_hash, :[], :[]=, :==
7
+
8
+ EXCHANGE_OPTION_DEFAULTS = {
9
+ type: :direct,
10
+ durable: true,
11
+ auto_delete: false,
12
+ arguments: {}
13
+ }.freeze
14
+
15
+ QUEUE_OPTION_DEFAULTS = {
16
+ durable: true,
17
+ auto_delete: false,
18
+ exclusive: false,
19
+ arguments: {}
20
+ }.freeze
21
+
22
+ DEFAULTS = {
23
+ # runner
24
+ runner_config_file: nil,
25
+ metrics: nil,
26
+ start_worker_delay: 0.2,
27
+ workers: 4,
28
+ log: STDOUT,
29
+ pid_path: 'mopsy.pid',
30
+ amqp_heartbeat: 30,
31
+
32
+ # workers
33
+ timeout_job_after: 5,
34
+ prefetch: 10,
35
+ threads: 10,
36
+ share_threads: false,
37
+ ack: true,
38
+ heartbeat: 30,
39
+ hooks: {},
40
+ exchange: 'mopsy',
41
+ exchange_options: EXCHANGE_OPTION_DEFAULTS,
42
+ queue_options: QUEUE_OPTION_DEFAULTS
43
+ }.freeze
44
+
45
+
46
+ def initialize
47
+ @hash = DEFAULTS.dup
48
+ @hash[:amqp] = ENV.fetch('RABBITMQ_URL', 'amqp://guest:guest@localhost:5672')
49
+ @hash[:vhost] = AMQ::Settings.parse_amqp_url(@hash[:amqp]).fetch(:vhost, '/')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,20 @@
1
+ module Mopsy
2
+ module Handlers
3
+ module ActionHandler
4
+ include Mopsy::Concerns::Logging
5
+ include Mopsy::Handlers::Handler
6
+
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ attr_reader :queue_name
13
+
14
+ def subscribe(q)
15
+ @queue_name = q.to_s
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,59 @@
1
+ module Mopsy
2
+ module Handlers
3
+ module Handler
4
+ attr_reader :pool
5
+
6
+ def initialize(queue = nil, pool = nil, opts = {})
7
+ # There's really no point in carrying on if no one bothered to supply a queue of some sort.
8
+ unless self.class.queue_name || queue
9
+ raise ArgumentError, "#{self.class.name} must subscribe to a queue, call 'subscribe'"
10
+ end
11
+
12
+ opts = Mopsy.conf.merge(opts)
13
+ @pool = pool || Concurrent::FixedThreadPool.new(1)
14
+ @queue = maybe_create_queue(queue, opts)
15
+ end
16
+
17
+ #
18
+ # Handler method that is actually registered with Bunny to be called when a message is received by the
19
+ # Mopsy::Rabbit::Queue.
20
+ #
21
+ def do_perform(delivery_info, metadata, msg)
22
+ # Send this call off to a thread from the thread pool.
23
+ @pool.post do
24
+ logger.debug { "Handling message from #{self.class.queue_name}" }
25
+
26
+ if self.respond_to?(:perform)
27
+ self.perform(delivery_info, metadata, msg)
28
+ else
29
+ logger.error "No action supplied"
30
+ end
31
+ end
32
+ end
33
+
34
+ #
35
+ # The `run` method is called by Mopsy::Handlers::RunGroup#run which is, in turn, called by ServerEngine.
36
+ #
37
+ def run
38
+ logger.debug { "Subscribing #{self.class.name} to queue #{@queue.name}" }
39
+ @queue.subscribe(self)
40
+ end
41
+
42
+ #
43
+ # Called by ServerEngine when it traps SIGINT/SIGTERM to enable a graceful exit.
44
+ #
45
+ def stop
46
+ logger.info { "Stopping #{self.class.name}" }
47
+ @pool.shutdown
48
+ @pool.wait_for_termination
49
+ logger.info { "Stopped #{self.class.name}" }
50
+ end
51
+
52
+ def maybe_create_queue(q, opts)
53
+ return q if !q.nil? && q.respond_to?(:subscribe)
54
+ Mopsy::Rabbit::Queue.new(self.class.queue_name, opts)
55
+ end
56
+ private :maybe_create_queue
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ module Mopsy
2
+ module Handlers
3
+ module JobHandler
4
+ include Mopsy::Concerns::Logging
5
+ include Mopsy::Handlers::Handler
6
+
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ attr_reader :queue_name
13
+
14
+ def subscribe(q)
15
+ @queue_name = q.to_s
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ module Mopsy
2
+ module Handlers
3
+ class Loader
4
+ class << self
5
+ def class_from_string(str)
6
+ str.split('::').inject(Object) do |mod, class_name|
7
+ mod.const_get(class_name)
8
+ end
9
+ end
10
+
11
+ def find_handlers(handler_string = '')
12
+ missing_handlers = []
13
+
14
+ handlers = handler_string.split(',').map do |klass|
15
+ begin
16
+ found = class_from_string(klass)
17
+ rescue NameError
18
+ missing_handlers << klass
19
+ end
20
+ found
21
+ end
22
+
23
+ [handlers.compact, missing_handlers.compact]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ module Mopsy
2
+ module Handlers
3
+ module RunGroup
4
+ attr_reader :handlers
5
+
6
+ def initialize
7
+ @stop = ServerEngine::BlockingFlag.new
8
+ @worker_pool = Concurrent::FixedThreadPool.new(2)
9
+ end
10
+
11
+ def load_handlers
12
+ @handlers ||= begin
13
+ config[:worker_classes].map do |w|
14
+ w.new(nil, @worker_pool, {})
15
+ end
16
+ rescue => e
17
+ Mopsy.logger.error "Unable to load handlers: #{e.message}"
18
+ exit(1) # TODO: How on earth do we actually exit ServerEngine completely here?
19
+ end
20
+ end
21
+
22
+ def run
23
+ load_handlers
24
+
25
+ @handlers.each do |h|
26
+ Mopsy.logger.debug { "Starting handler: #{h}" }
27
+ h.run
28
+ end
29
+
30
+ until @stop.wait_for_set
31
+ Mopsy.logger.debug("Heartbeat: running threads [#{Thread.list.count}]")
32
+ end
33
+ end
34
+
35
+ def stop
36
+ Mopsy.logger.info("Shutting down workers")
37
+
38
+ @handlers.each do |h|
39
+ h.stop
40
+ end
41
+
42
+ @stop.set!
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,50 @@
1
+ require 'bunny'
2
+
3
+ module Mopsy
4
+ module Rabbit
5
+ class Queue
6
+ attr_reader :channel, :exchange, :name, :opts
7
+
8
+ def initialize(name, opts)
9
+ @name = name
10
+ @opts = opts
11
+ end
12
+
13
+ def subscribe(handler)
14
+ @bunny ||=
15
+ Bunny.new(opts[:amqp],
16
+ {
17
+ vhost: opts[:vhost],
18
+ heartbeat: opts[:heartbeat],
19
+ properties: opts.fetch(:properties, {}),
20
+ logger: Mopsy.logger
21
+ })
22
+ .tap { |b| b.start }
23
+
24
+ @channel = @bunny.create_channel
25
+ @channel.prefetch(opts[:prefetch])
26
+
27
+ exchange_name = opts[:exchange]
28
+ routing_key = @opts[:routing_key] || @name
29
+ routing_keys = [*routing_key]
30
+ @exchange = @channel.exchange(exchange_name, opts[:exchange_options])
31
+ @queue = @channel.queue(name, opts[:queue_options])
32
+
33
+ if exchange_name.length > 0
34
+ routing_keys.each do |key|
35
+ @queue.bind(@exchange, routing_key: key)
36
+ end
37
+ end
38
+
39
+ # Subscribe the handler to the actual Rabbit queue.
40
+ @consumer = @queue.subscribe(block: false, manual_ack: opts[:ack]) do |delivery_info, metadata, msg|
41
+ handler.do_perform(delivery_info, metadata, msg)
42
+ end
43
+ end
44
+
45
+ def unsubscribe
46
+ raise NotImplementedError
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ require 'concurrent/executors'
2
+ require 'serverengine'
3
+
4
+ module Mopsy
5
+ class Runner
6
+ def initialize(handlers, opts={})
7
+ @runner_conf = RunnerConf.new(handlers)
8
+ end
9
+
10
+ def run
11
+ @se = ServerEngine.create(nil, Handlers::RunGroup) { @runner_conf.reload! }
12
+ @se.run
13
+ end
14
+
15
+ def stop
16
+ # Graceful server engine stop
17
+ @se.stop(true)
18
+ end
19
+ end
20
+
21
+ class RunnerConf
22
+
23
+ def initialize(handlers)
24
+ @handlers = handlers
25
+ end
26
+
27
+ def reload!
28
+ Mopsy.logger.warn("Loading runner conf")
29
+
30
+ conf = {}
31
+ conf.merge!({
32
+ logger: Mopsy.logger,
33
+ worker_type: 'process',
34
+ worker_classes: @handlers,
35
+ log_stdout: false,
36
+ log_stderr: false
37
+ })
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Mopsy
2
+ VERSION = "1.0.0.pre"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "mopsy/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'mopsy'
8
+ spec.version = Mopsy::VERSION
9
+ spec.authors = ['Gareth Jones']
10
+ spec.email = ['garethmichaeljones@gmail.com']
11
+
12
+ spec.summary = %q( Yet another job/RPC framework for Ruby and RabbitMQ )
13
+ spec.description = %q( Yet another job/RPC framework for Ruby and RabbitMQ )
14
+ spec.homepage = 'https://github.com/garethmj/mopsy.git'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($/).reject { |f| f == 'Gemfile.lock' }
18
+ spec.executables = spec.files.grep(/^bin/).map { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'bunny', '~> 2.7'
23
+ spec.add_dependency 'concurrent-ruby', '~> 1.0'
24
+ spec.add_dependency 'serverengine', '~> 2.0', '>= 2.0.5'
25
+ spec.add_dependency 'thor'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 1.15'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.0'
30
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'mopsy/handlers/loader'
4
+
5
+ RSpec.describe Mopsy::Handlers::Loader do
6
+ describe '#find_handlers' do
7
+
8
+ before do
9
+ class Foo; end
10
+ class Bar; end
11
+ class Baz
12
+ class Cheese; end
13
+ class Parrot; end
14
+ class Knight
15
+ class Herring; end
16
+ end
17
+ end
18
+ end
19
+
20
+ context 'given a single class name' do
21
+ describe 'without namespace' do
22
+ it 'returns the worker class name' do
23
+ expect(Mopsy::Handlers::Loader.find_handlers('Foo')).to eq([[Foo],[]])
24
+ end
25
+ end
26
+
27
+ describe 'with namespace' do
28
+ it 'returns the worker class name' do
29
+ expect(Mopsy::Handlers::Loader.find_handlers('Baz::Cheese')).to eq([[Baz::Cheese],[]])
30
+ expect(Mopsy::Handlers::Loader.find_handlers('Baz::Knight::Herring')).to eq([[Baz::Knight::Herring],[]])
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'given a list of class names' do
36
+ describe 'without namespaces' do
37
+ it 'returns all worker class names' do
38
+ expect(Mopsy::Handlers::Loader.find_handlers('Foo,Bar')).to eq([[Foo,Bar],[]])
39
+ end
40
+ end
41
+
42
+ describe 'with namespaces' do
43
+ it 'returns all worker class names' do
44
+ workers = Mopsy::Handlers::Loader.find_handlers('Baz::Cheese,Baz::Parrot')
45
+ expect(workers).to eq([[Baz::Cheese,Baz::Parrot],[]])
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'given a non-existent class name' do
51
+ describe 'without namespaces' do
52
+ it 'returns an array of missing handler class names' do
53
+ expect(Mopsy::Handlers::Loader.find_handlers('Ham,Foo')).to eq([[Foo],['Ham']])
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,45 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'mopsy/handlers/run_group'
4
+
5
+ RSpec.describe Mopsy::Handlers::RunGroup do
6
+ before do
7
+ # A do-nothing handler class for use as a mock type thingy.
8
+ class FakeHandler
9
+ include Mopsy::Handlers::Handler
10
+ include Mopsy::Concerns::Logging
11
+
12
+ def perform
13
+ end
14
+ end
15
+
16
+ # Can't create an instance of a module so include it in a wrapper class.
17
+ class MyRunGroup
18
+ include Mopsy::Handlers::RunGroup
19
+ end
20
+
21
+ # Need to make sure logger is configured.
22
+ Mopsy.configure
23
+
24
+ # Fake the injected `config` var from ServerEngine black magic.
25
+ allow_any_instance_of(Mopsy::Handlers::RunGroup).to receive(:config).and_return({ worker_classes: [FakeHandler] })
26
+ end
27
+
28
+ let(:rg) { MyRunGroup.new }
29
+
30
+ describe 'handler configuration' do
31
+ it 'fetches worker classes from ServerEngine injected config' do
32
+ expect(rg.load_handlers.first).to be_an_instance_of(FakeHandler)
33
+ expect(rg.load_handlers.first.pool).to be_an_instance_of(Concurrent::FixedThreadPool)
34
+ end
35
+ end
36
+
37
+ describe '#run' do
38
+ it 'sends #do_perform to registered handlers' do
39
+ allow_any_instance_of(ServerEngine::BlockingFlag).to receive(:wait_for_set).and_return(true)
40
+ rg.load_handlers
41
+ expect(rg.handlers.first).to receive(:do_perform)
42
+ rg.run
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Mopsy do
4
+ it "has a version number" do
5
+ expect(Mopsy::VERSION).not_to be nil
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ require 'bundler/setup'
2
+ require 'mopsy'
3
+
4
+ RSpec.configure do |config|
5
+ # Enable flags like --only-failures and --next-failure
6
+ config.example_status_persistence_file_path = '.rspec_status'
7
+
8
+ # Disable RSpec exposing methods globally on `Module` and `main`
9
+ config.disable_monkey_patching!
10
+
11
+ config.expect_with :rspec do |c|
12
+ c.syntax = :expect
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mopsy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Gareth Jones
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bunny
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: serverengine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.0.5
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '2.0'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 2.0.5
61
+ - !ruby/object:Gem::Dependency
62
+ name: thor
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: bundler
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.15'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.15'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '10.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '10.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rspec
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.0'
117
+ description: " Yet another job/RPC framework for Ruby and RabbitMQ "
118
+ email:
119
+ - garethmichaeljones@gmail.com
120
+ executables:
121
+ - console
122
+ - mopsy
123
+ - setup
124
+ extensions: []
125
+ extra_rdoc_files: []
126
+ files:
127
+ - ".gitignore"
128
+ - ".rspec"
129
+ - ".ruby-version"
130
+ - ".travis.yml"
131
+ - Gemfile
132
+ - LICENSE.txt
133
+ - README.md
134
+ - Rakefile
135
+ - bin/console
136
+ - bin/mopsy
137
+ - bin/setup
138
+ - examples/dumb_job_example.rb
139
+ - examples/dumb_rpc_example.rb
140
+ - lib/mopsy.rb
141
+ - lib/mopsy/cli.rb
142
+ - lib/mopsy/concerns/logging.rb
143
+ - lib/mopsy/conf.rb
144
+ - lib/mopsy/handlers/action_handler.rb
145
+ - lib/mopsy/handlers/handler.rb
146
+ - lib/mopsy/handlers/job_handler.rb
147
+ - lib/mopsy/handlers/loader.rb
148
+ - lib/mopsy/handlers/run_group.rb
149
+ - lib/mopsy/rabbit/queue.rb
150
+ - lib/mopsy/runner.rb
151
+ - lib/mopsy/version.rb
152
+ - mopsy.gemspec
153
+ - spec/handlers/loader_spec.rb
154
+ - spec/handlers/run_group_spec.rb
155
+ - spec/mopsy_spec.rb
156
+ - spec/spec_helper.rb
157
+ homepage: https://github.com/garethmj/mopsy.git
158
+ licenses:
159
+ - MIT
160
+ metadata: {}
161
+ post_install_message:
162
+ rdoc_options: []
163
+ require_paths:
164
+ - lib
165
+ required_ruby_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ required_rubygems_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">"
173
+ - !ruby/object:Gem::Version
174
+ version: 1.3.1
175
+ requirements: []
176
+ rubyforge_project:
177
+ rubygems_version: 2.6.11
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: Yet another job/RPC framework for Ruby and RabbitMQ
181
+ test_files:
182
+ - spec/handlers/loader_spec.rb
183
+ - spec/handlers/run_group_spec.rb
184
+ - spec/mopsy_spec.rb
185
+ - spec/spec_helper.rb