services 0.0.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 +7 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +5 -0
- data/lib/services.rb +25 -0
- data/lib/services/asyncable.rb +75 -0
- data/lib/services/base.rb +68 -0
- data/lib/services/base/call_logger.rb +22 -0
- data/lib/services/base/exception_wrapper.rb +15 -0
- data/lib/services/base/uniqueness_checker.rb +36 -0
- data/lib/services/logger.rb +21 -0
- data/lib/services/railtie.rb +7 -0
- data/lib/services/version.rb +3 -0
- data/services.gemspec +32 -0
- data/spec/services/base_spec.rb +75 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/support/logs/.gitkeep +0 -0
- data/spec/support/redis-cli +0 -0
- data/spec/support/redis-server +0 -0
- data/spec/support/test_services.rb +5 -0
- metadata +190 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 29c86c30a1166901d26fdf5d0484a368c1486011
|
4
|
+
data.tar.gz: 8617c1b8bd2543fdcf22e1eac5e30ab274b13a5c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 544977f3bdb51a170867318270d11acf79b2039981efbc53d6e19c61935ddf31db3b94634470f418dede84970d0334dcc7c71eb137a61f621c31a6bded717bcf
|
7
|
+
data.tar.gz: a9d4bad15dabe9c9f9c92fe096f4b44318f9b72f4e37fdc531c216e2a103ae02a46ff2844f81d4260e15f4d04228a490973fb28ea868f5344831a95c0809cf21
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
guard 'rspec', cmd: 'bundle exec rspec', failed_mode: :none, all_after_pass: true, all_on_start: true do
|
2
|
+
# Specs
|
3
|
+
watch(%r(^spec/.+_spec\.rb$))
|
4
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
5
|
+
watch(%r(^spec/support/(.+)\.rb$)) { 'spec' }
|
6
|
+
|
7
|
+
# Files
|
8
|
+
watch(%r(^lib/(.+)\.rb$)) { |m| "spec/#{m[1]}_spec.rb" }
|
9
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 kraut computing UG (haftungsbeschränkt)
|
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,38 @@
|
|
1
|
+
# Services
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/services)
|
4
|
+
[](http://travis-ci.org/krautcomputing/services)
|
5
|
+
[](https://gemnasium.com/krautcomputing/services)
|
6
|
+
[](https://codeclimate.com/github/krautcomputing/services)
|
7
|
+
|
8
|
+
Services is a opinionated set of modules that can be used to implement the use cases (or services, contexts, whatchamacallit) of a Ruby application.
|
9
|
+
|
10
|
+
## Requirements
|
11
|
+
|
12
|
+
Ruby >= 2.0
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'services'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install services
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Coming soon...
|
31
|
+
|
32
|
+
## Contributing
|
33
|
+
|
34
|
+
1. Fork it
|
35
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
36
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
37
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
38
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/services.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'gem_config'
|
2
|
+
|
3
|
+
module Services
|
4
|
+
include GemConfig::Base
|
5
|
+
|
6
|
+
BackgroundProcessorNotFound = Class.new(StandardError)
|
7
|
+
|
8
|
+
with_configuration do
|
9
|
+
has :host, classes: String
|
10
|
+
has :log_dir, classes: [String, Pathname]
|
11
|
+
has :redis
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require_relative 'services/version'
|
16
|
+
require_relative 'services/logger'
|
17
|
+
begin
|
18
|
+
require_relative 'services/asyncable'
|
19
|
+
rescue Services::BackgroundProcessorNotFound
|
20
|
+
end
|
21
|
+
require_relative 'services/base/call_logger'
|
22
|
+
require_relative 'services/base/exception_Wrapper'
|
23
|
+
require_relative 'services/base/uniqueness_checker'
|
24
|
+
require_relative 'services/base'
|
25
|
+
require_relative 'services/railtie' if defined?(Rails)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'sidekiq'
|
5
|
+
rescue LoadError
|
6
|
+
raise Services::BackgroundProcessorNotFound
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'sidetiq'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
|
14
|
+
module Services
|
15
|
+
module Asyncable
|
16
|
+
extend ActiveSupport::Concern
|
17
|
+
|
18
|
+
# The name of the parameter that is added to the parameter list when calling a method to be processed in the background.
|
19
|
+
TARGET_PARAM_NAME = :async_target_id
|
20
|
+
|
21
|
+
included do
|
22
|
+
include Sidekiq::Worker
|
23
|
+
include Sidetiq::Schedulable if defined?(Sidetiq)
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
# Bulk enqueue items
|
28
|
+
# args can either be a one-dimensional or two-dimensional array,
|
29
|
+
# each item in args should be the arguments for one job.
|
30
|
+
def bulk_perform_async(args)
|
31
|
+
# Convert args to two-dimensional array if it isn't already.
|
32
|
+
args = args.map { |arg| [arg] } if args.none? { |arg| arg.is_a?(Array) }
|
33
|
+
Sidekiq::Client.push_bulk 'class' => self, 'args' => args
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
%w(perform_async perform_in).each do |method_name|
|
38
|
+
define_method method_name do |*args|
|
39
|
+
self.class.send method_name, *args, TARGET_PARAM_NAME => self.id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method :perform_at, :perform_in
|
43
|
+
|
44
|
+
def perform(*args)
|
45
|
+
return self.call(*args) if self.is_a?(Services::Base)
|
46
|
+
|
47
|
+
target = if args.last.is_a?(Hash) && args.last.keys.first.to_sym == TARGET_PARAM_NAME
|
48
|
+
self.class.find args.pop.values.first
|
49
|
+
else
|
50
|
+
self.class
|
51
|
+
end
|
52
|
+
|
53
|
+
target.send *args
|
54
|
+
end
|
55
|
+
|
56
|
+
def own_worker
|
57
|
+
return @own_worker if defined?(@own_worker)
|
58
|
+
@own_worker = if self.jid.nil?
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
own_worker = Sidekiq::Workers.new.detect do |_, work, _|
|
62
|
+
work['payload']['jid'] == self.jid
|
63
|
+
end
|
64
|
+
raise self.class::Error, "Could not find own worker with jid #{self.jid}: #{Sidekiq::Workers.new.map{ |*args| args }}" if own_worker.nil?
|
65
|
+
own_worker
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def sibling_workers
|
70
|
+
@sibling_workers ||= Sidekiq::Workers.new.select do |_, work, _|
|
71
|
+
work['payload']['class'] == self.class.to_s && (own_worker.nil? || work['payload']['jid'] != own_worker[1]['payload']['jid'])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'nesty'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'action_dispatch'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
module Services
|
7
|
+
class Base
|
8
|
+
class << self
|
9
|
+
def inherited(subclass)
|
10
|
+
subclass.const_set :Error, Class.new(Nesty::NestedStandardError)
|
11
|
+
subclass.send :include, Rails.application.routes.url_helpers if defined?(Rails)
|
12
|
+
subclass.send :include, Asyncable if defined?(Asyncable)
|
13
|
+
subclass.send :prepend, CallLogger, ExceptionWrapper, UniquenessChecker
|
14
|
+
end
|
15
|
+
|
16
|
+
delegate :call, to: :new
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@id = SecureRandom.hex(6)
|
21
|
+
@logger = Logger.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(*args)
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def find_object(ids_or_objects, klass = nil)
|
31
|
+
if klass.nil?
|
32
|
+
klass = self.class.to_s[/Services::([^:]+)/, 1].singularize.constantize rescue nil
|
33
|
+
raise "Could not determine class from #{self.class}" if klass.nil?
|
34
|
+
end
|
35
|
+
case ids_or_objects
|
36
|
+
when klass
|
37
|
+
return ids_or_objects
|
38
|
+
when Array
|
39
|
+
raise 'Array can only contain IDs.' if ids_or_objects.any? { |ids_or_object| !ids_or_object.is_a?(Fixnum) }
|
40
|
+
objects = "Services::#{klass.to_s.pluralize}::Find".constantize.call(ids_or_objects)
|
41
|
+
missing_ids = ids_or_objects - objects.pluck(:id)
|
42
|
+
raise self.class::Error, "#{klass.to_s.pluralize(missing_ids)} #{missing_ids.join(', ')} not found." if missing_ids.present?
|
43
|
+
return objects
|
44
|
+
when Fixnum
|
45
|
+
object = "Services::#{klass.to_s.pluralize}::Find".constantize.call(ids_or_objects).first
|
46
|
+
raise self.class::Error, "#{klass} #{ids_or_objects} not found." if object.nil?
|
47
|
+
return object
|
48
|
+
else
|
49
|
+
raise "Unexpected ids_or_objects class: #{ids_or_objects.class}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def log(message, severity = :info)
|
54
|
+
@logger.log [self.class, @id], message, severity
|
55
|
+
end
|
56
|
+
|
57
|
+
def controller
|
58
|
+
@controller ||= begin
|
59
|
+
raise 'Please configure host.' unless Services.configuration.host?
|
60
|
+
request = ActionDispatch::TestRequest.new
|
61
|
+
request.host = Services.configuration.host
|
62
|
+
ActionController::Base.new.tap do |controller|
|
63
|
+
controller.instance_variable_set('@_request', request)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Services
|
2
|
+
class Base
|
3
|
+
module CallLogger
|
4
|
+
def call(*args)
|
5
|
+
log "START with args: #{args}"
|
6
|
+
start = Time.now
|
7
|
+
begin
|
8
|
+
result = super
|
9
|
+
rescue StandardError => e
|
10
|
+
log "#{e.class}: #{e.message}"
|
11
|
+
e.backtrace.each do |line|
|
12
|
+
log line
|
13
|
+
end
|
14
|
+
raise e
|
15
|
+
ensure
|
16
|
+
log "END after #{(Time.now - start).round(2)} seconds"
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Services
|
2
|
+
class Base
|
3
|
+
module UniquenessChecker
|
4
|
+
def self.prepended(mod)
|
5
|
+
mod.const_set :NotUniqueError, Class.new(mod::Error)
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(*args)
|
9
|
+
key = unique_key(args)
|
10
|
+
if Services.configuration.redis.exists(key)
|
11
|
+
raise self.class::NotUniqueError
|
12
|
+
else
|
13
|
+
Services.configuration.redis.setex key, 60 * 60, Time.now
|
14
|
+
begin
|
15
|
+
super
|
16
|
+
ensure
|
17
|
+
Services.configuration.redis.del key
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def unique_key(args)
|
25
|
+
# TODO: symbolize keys in hashes in args and sort hashes by key
|
26
|
+
args = args.dup
|
27
|
+
key = [
|
28
|
+
'services',
|
29
|
+
'uniqueness',
|
30
|
+
self.class.to_s,
|
31
|
+
Digest::MD5.hexdigest(args.to_s)
|
32
|
+
].join(':')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_support/tagged_logging'
|
2
|
+
|
3
|
+
module Services
|
4
|
+
class Logger
|
5
|
+
def initialize
|
6
|
+
unless Services.configuration.log_dir.nil?
|
7
|
+
log_file = File.join(Services.configuration.log_dir, 'services.log')
|
8
|
+
@logger = ActiveSupport::TaggedLogging.new(::Logger.new(log_file))
|
9
|
+
@logger.clear_tags!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def log(tags, message, severity = :info)
|
14
|
+
unless @logger.nil?
|
15
|
+
@logger.tagged Time.now, severity.upcase, *tags do
|
16
|
+
@logger.send severity, message
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/services.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'services/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |gem|
|
9
|
+
gem.name = 'services'
|
10
|
+
gem.version = Services::VERSION
|
11
|
+
gem.platform = Gem::Platform::RUBY
|
12
|
+
gem.author = 'Manuel Meurer'
|
13
|
+
gem.email = 'manuel@krautcomputing.com'
|
14
|
+
gem.summary = ''
|
15
|
+
gem.description = ''
|
16
|
+
gem.homepage = ''
|
17
|
+
gem.license = 'MIT'
|
18
|
+
|
19
|
+
gem.files = `git ls-files`.split($/)
|
20
|
+
gem.executables = gem.files.grep(%r(^bin/)).map { |f| File.basename(f) }
|
21
|
+
gem.test_files = gem.files.grep(%r(^(test|spec|features)/))
|
22
|
+
gem.require_paths = ['lib']
|
23
|
+
|
24
|
+
gem.add_development_dependency 'rake'
|
25
|
+
gem.add_development_dependency 'guard-rspec', '~> 4.2'
|
26
|
+
gem.add_development_dependency 'rspec', '>= 3.0.0.beta2', '< 4'
|
27
|
+
gem.add_development_dependency 'sidekiq', '~> 3.0'
|
28
|
+
gem.add_development_dependency 'redis', '~> 3.0'
|
29
|
+
gem.add_runtime_dependency 'rails', '>= 3.0.0'
|
30
|
+
gem.add_runtime_dependency 'gem_config', '~> 0.3.1'
|
31
|
+
gem.add_runtime_dependency 'nesty', '~> 1.0.2'
|
32
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Services::Base do
|
4
|
+
context 'wrapping exceptions' do
|
5
|
+
it 'does not wrap service errors or subclasses' do
|
6
|
+
class ServiceWithError < Services::Base
|
7
|
+
def call
|
8
|
+
raise Error.new('I am a service error.', nil)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
expect do
|
12
|
+
ServiceWithError.call
|
13
|
+
end.to raise_error do |error|
|
14
|
+
expect(error).to be_a(ServiceWithError::Error)
|
15
|
+
expect(error.message).to eq('I am a service error.')
|
16
|
+
expect(error.nested).to be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
class ServiceWithCustomError < Services::Base
|
20
|
+
CustomError = Class.new(self::Error)
|
21
|
+
def call
|
22
|
+
raise CustomError.new('I am a custom error.', nil)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
expect do
|
26
|
+
ServiceWithCustomError.call
|
27
|
+
end.to raise_error do |error|
|
28
|
+
expect(error).to be_a(ServiceWithCustomError::CustomError)
|
29
|
+
expect(error.message).to eq('I am a custom error.')
|
30
|
+
expect(error.nested).to be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'wraps all other exceptions' do
|
35
|
+
class ServiceWithStandardError < Services::Base
|
36
|
+
def call
|
37
|
+
raise 'I am a StandardError.'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
expect do
|
41
|
+
ServiceWithStandardError.call
|
42
|
+
end.to raise_error do |error|
|
43
|
+
expect(error).to be_a(ServiceWithStandardError::Error)
|
44
|
+
expect(error.message).to eq('I am a StandardError.')
|
45
|
+
expect(error.nested).to be_a(StandardError)
|
46
|
+
expect(error.nested.message).to eq('I am a StandardError.')
|
47
|
+
end
|
48
|
+
|
49
|
+
class ServiceWithCustomStandardError < Services::Base
|
50
|
+
CustomStandardError = Class.new(StandardError)
|
51
|
+
def call
|
52
|
+
raise CustomStandardError, 'I am a custom StandardError.'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
expect do
|
56
|
+
ServiceWithCustomStandardError.call
|
57
|
+
end.to raise_error do |error|
|
58
|
+
expect(error).to be_a(ServiceWithCustomStandardError::Error)
|
59
|
+
expect(error.message).to eq('I am a custom StandardError.')
|
60
|
+
expect(error.nested).to be_a(ServiceWithCustomStandardError::CustomStandardError)
|
61
|
+
expect(error.nested.message).to eq('I am a custom StandardError.')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'checking for uniqueness' do
|
67
|
+
it 'raises an error when the same job is executed twice' do
|
68
|
+
LongRunningService.perform_async
|
69
|
+
sleep 0.5 # Wait for Sidekiq to start processing the job
|
70
|
+
expect do
|
71
|
+
LongRunningService.call
|
72
|
+
end.to raise_error(LongRunningService::NotUniqueError)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'redis'
|
3
|
+
require 'sidekiq'
|
4
|
+
require_relative '../lib/services'
|
5
|
+
require_relative 'support/test_services'
|
6
|
+
|
7
|
+
support_dir = Pathname.new(File.expand_path('../support', __FILE__))
|
8
|
+
log_dir = support_dir.join('logs')
|
9
|
+
|
10
|
+
redis_port = 6379
|
11
|
+
redis_pidfile = support_dir.join('redis.pid')
|
12
|
+
redis_url = "redis://localhost:#{redis_port}/0"
|
13
|
+
|
14
|
+
sidekiq_pidfile = support_dir.join('sidekiq.pid')
|
15
|
+
sidekiq_timeout = 60
|
16
|
+
|
17
|
+
Services.configure do |config|
|
18
|
+
config.redis = Redis.new
|
19
|
+
config.log_dir = log_dir
|
20
|
+
end
|
21
|
+
|
22
|
+
Sidekiq.configure_client do |config|
|
23
|
+
config.redis = { redis: redis_url, namespace: 'sidekiq', size: 1 }
|
24
|
+
end
|
25
|
+
|
26
|
+
Sidekiq.configure_server do |config|
|
27
|
+
config.redis = { redis: redis_url, namespace: 'sidekiq' }
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec.configure do |config|
|
31
|
+
config.run_all_when_everything_filtered = true
|
32
|
+
config.filter_run :focus
|
33
|
+
config.order = 'random'
|
34
|
+
|
35
|
+
config.before :all do
|
36
|
+
# Start Redis
|
37
|
+
redis_options = {
|
38
|
+
daemonize: 'yes',
|
39
|
+
port: redis_port,
|
40
|
+
dir: support_dir,
|
41
|
+
dbfilename: 'redis.rdb',
|
42
|
+
logfile: log_dir.join('redis.log'),
|
43
|
+
pidfile: redis_pidfile
|
44
|
+
}
|
45
|
+
redis = support_dir.join('redis-server')
|
46
|
+
system "#{redis} #{options_hash_to_string(redis_options)}"
|
47
|
+
|
48
|
+
# Start Sidekiq
|
49
|
+
sidekiq_options = {
|
50
|
+
concurrency: 1,
|
51
|
+
daemon: true,
|
52
|
+
timeout: sidekiq_timeout,
|
53
|
+
verbose: true,
|
54
|
+
require: __FILE__,
|
55
|
+
logfile: log_dir.join('sidekiq.log'),
|
56
|
+
pidfile: sidekiq_pidfile
|
57
|
+
}
|
58
|
+
system "bundle exec sidekiq #{options_hash_to_string(sidekiq_options)}"
|
59
|
+
end
|
60
|
+
|
61
|
+
config.after :all do
|
62
|
+
# Stop Sidekiq
|
63
|
+
system "bundle exec sidekiqctl stop #{sidekiq_pidfile} #{sidekiq_timeout}"
|
64
|
+
while File.exist?(sidekiq_pidfile)
|
65
|
+
puts 'Waiting for Sidekiq to shut down...'
|
66
|
+
sleep 1
|
67
|
+
end
|
68
|
+
|
69
|
+
# Stop Redis
|
70
|
+
redis_cli = support_dir.join('redis-cli')
|
71
|
+
system "#{redis_cli} -p #{redis_port} shutdown"
|
72
|
+
while File.exist?(redis_pidfile)
|
73
|
+
puts 'Waiting for Redis to shut down...'
|
74
|
+
sleep 1
|
75
|
+
end
|
76
|
+
|
77
|
+
# Truncate log files
|
78
|
+
max_len = 1024 * 1024 # 1 MB
|
79
|
+
Dir[File.join(log_dir, '*.log')].each do |file|
|
80
|
+
File.truncate file, max_len if File.size(file) > max_len
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def options_hash_to_string(options)
|
86
|
+
options.map { |k, v| "--#{k} #{v}" }.join(' ')
|
87
|
+
end
|
File without changes
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: services
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Manuel Meurer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: guard-rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0.beta2
|
48
|
+
- - <
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '4'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 3.0.0.beta2
|
58
|
+
- - <
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '4'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: sidekiq
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ~>
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: redis
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ~>
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '3.0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ~>
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '3.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rails
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 3.0.0
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 3.0.0
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: gem_config
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.3.1
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ~>
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 0.3.1
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: nesty
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ~>
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.0.2
|
124
|
+
type: :runtime
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ~>
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 1.0.2
|
131
|
+
description: ''
|
132
|
+
email: manuel@krautcomputing.com
|
133
|
+
executables: []
|
134
|
+
extensions: []
|
135
|
+
extra_rdoc_files: []
|
136
|
+
files:
|
137
|
+
- .gitignore
|
138
|
+
- Gemfile
|
139
|
+
- Guardfile
|
140
|
+
- LICENSE.txt
|
141
|
+
- README.md
|
142
|
+
- Rakefile
|
143
|
+
- lib/services.rb
|
144
|
+
- lib/services/asyncable.rb
|
145
|
+
- lib/services/base.rb
|
146
|
+
- lib/services/base/call_logger.rb
|
147
|
+
- lib/services/base/exception_wrapper.rb
|
148
|
+
- lib/services/base/uniqueness_checker.rb
|
149
|
+
- lib/services/logger.rb
|
150
|
+
- lib/services/railtie.rb
|
151
|
+
- lib/services/version.rb
|
152
|
+
- services.gemspec
|
153
|
+
- spec/services/base_spec.rb
|
154
|
+
- spec/spec_helper.rb
|
155
|
+
- spec/support/logs/.gitkeep
|
156
|
+
- spec/support/redis-cli
|
157
|
+
- spec/support/redis-server
|
158
|
+
- spec/support/test_services.rb
|
159
|
+
homepage: ''
|
160
|
+
licenses:
|
161
|
+
- MIT
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 2.2.2
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: ''
|
183
|
+
test_files:
|
184
|
+
- spec/services/base_spec.rb
|
185
|
+
- spec/spec_helper.rb
|
186
|
+
- spec/support/logs/.gitkeep
|
187
|
+
- spec/support/redis-cli
|
188
|
+
- spec/support/redis-server
|
189
|
+
- spec/support/test_services.rb
|
190
|
+
has_rdoc:
|