parallel_workforce 1.0.0
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 +9 -0
- data/.rspec +1 -0
- data/.rubocop.yml +2 -0
- data/.rubocop_parallel_workforce.yml +365 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +169 -0
- data/LICENSE +201 -0
- data/README.md +110 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/parallel_workforce/configuration.rb +29 -0
- data/lib/parallel_workforce/executor.rb +224 -0
- data/lib/parallel_workforce/job/active_job.rb +23 -0
- data/lib/parallel_workforce/job/active_job_rails.rb +25 -0
- data/lib/parallel_workforce/job/sidekiq.rb +26 -0
- data/lib/parallel_workforce/job/sidekiq_rails.rb +25 -0
- data/lib/parallel_workforce/job/util/performer.rb +120 -0
- data/lib/parallel_workforce/redis_connector/redis_pool.rb +11 -0
- data/lib/parallel_workforce/redis_connector/sidekiq_redis_pool.rb +11 -0
- data/lib/parallel_workforce/requires.rb +37 -0
- data/lib/parallel_workforce/revision_builder/files_hash.rb +19 -0
- data/lib/parallel_workforce/serializer/marshal.rb +21 -0
- data/lib/parallel_workforce/version.rb +3 -0
- data/lib/parallel_workforce.rb +46 -0
- data/parallel_workforce.gemspec +48 -0
- metadata +201 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module ParallelWorkforce
|
2
|
+
module Job
|
3
|
+
class SidekiqRails < ParallelWorkforce::Job::Sidekiq
|
4
|
+
class << self
|
5
|
+
def enqueue_actor(actor_class_name:, result_key:, index:, server_revision:, serialized_actor_args:)
|
6
|
+
perform_async(
|
7
|
+
actor_class_name: actor_class_name,
|
8
|
+
result_key: result_key,
|
9
|
+
index: index,
|
10
|
+
server_revision: server_revision,
|
11
|
+
serialized_actor_args: serialized_actor_args,
|
12
|
+
time_zone_name: Time.zone.name,
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def perform(args)
|
18
|
+
args.symbolize_keys!
|
19
|
+
Time.use_zone(args.delete(:time_zone_name)) do
|
20
|
+
ParallelWorkforce::Job::Util::Performer.new(**args).perform
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module ParallelWorkforce
|
2
|
+
module Job
|
3
|
+
module Util
|
4
|
+
class Performer
|
5
|
+
attr_reader(
|
6
|
+
:actor_class_name,
|
7
|
+
:result_key,
|
8
|
+
:index,
|
9
|
+
:server_revision,
|
10
|
+
:serialized_actor_args,
|
11
|
+
)
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def perform(actor_class, actor_args)
|
15
|
+
actor_args = actor_args.each_with_object({}) { |(k, v), result| result[k.to_sym] = v }
|
16
|
+
|
17
|
+
(actor_args.empty? ? actor_class.new : actor_class.new(**actor_args)).perform
|
18
|
+
end
|
19
|
+
|
20
|
+
def parallel_workforce_thread?
|
21
|
+
!!Thread.current[:parallel_workforce_thread]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(actor_class_name:, result_key:, index:, server_revision:, serialized_actor_args:)
|
26
|
+
@actor_class_name = actor_class_name
|
27
|
+
@result_key = result_key
|
28
|
+
@index = index
|
29
|
+
@server_revision = server_revision
|
30
|
+
@serialized_actor_args = serialized_actor_args
|
31
|
+
end
|
32
|
+
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
34
|
+
# rubocop:disable Metrics/AbcSize
|
35
|
+
def perform
|
36
|
+
result = {}
|
37
|
+
|
38
|
+
if server_revision == worker_revision
|
39
|
+
begin
|
40
|
+
result[:serialized_value] = serialize(perform_actor)
|
41
|
+
rescue ParallelWorkforce::Error => e
|
42
|
+
warn("#{self.class}: Actor revision error: #{e}")
|
43
|
+
result[:error_revision] = worker_revision
|
44
|
+
rescue => e
|
45
|
+
warn("#{self.class}: Error in actor perform: #{e}", *e.backtrace)
|
46
|
+
result[:error] = "Error in actor perform. #{e.class} #{e.message}"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
warn("#{self.class}: Revision mismatch from caller")
|
50
|
+
result[:error_revision] = worker_revision
|
51
|
+
end
|
52
|
+
|
53
|
+
result
|
54
|
+
rescue Exception => exception
|
55
|
+
result = handle_exception(exception)
|
56
|
+
ensure
|
57
|
+
ParallelWorkforce.configuration.redis_connector.with do |redis|
|
58
|
+
# always publish a message result to avoid a Timeout in subscriber
|
59
|
+
# NOTE: always using Ruby marshaling to store in Redis, not serializer
|
60
|
+
redis.rpush(result_key, Marshal.dump(result.merge(index: index)))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
# rubocop:enable Metrics/AbcSize
|
64
|
+
# rubocop:enable Metrics/MethodLength
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def perform_actor
|
69
|
+
actor_class = begin
|
70
|
+
Object.const_get(actor_class_name)
|
71
|
+
rescue NameError
|
72
|
+
raise ParallelWorkforce::SerializerError.new("Unable to locate actor class: #{actor_class_name}")
|
73
|
+
end
|
74
|
+
|
75
|
+
in_parallel_workforce_thread do
|
76
|
+
self.class.perform(actor_class, deserialize(serialized_actor_args))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def in_parallel_workforce_thread(&block)
|
81
|
+
original_parallel_workforce_thread = Thread.current[:parallel_workforce_thread]
|
82
|
+
|
83
|
+
Thread.current[:parallel_workforce_thread] = true
|
84
|
+
yield
|
85
|
+
ensure
|
86
|
+
Thread.current[:parallel_workforce_thread] = original_parallel_workforce_thread
|
87
|
+
end
|
88
|
+
|
89
|
+
def serialize(object)
|
90
|
+
ParallelWorkforce.configuration.serializer.serialize(object)
|
91
|
+
end
|
92
|
+
|
93
|
+
def deserialize(string)
|
94
|
+
ParallelWorkforce.configuration.serializer.deserialize(string)
|
95
|
+
end
|
96
|
+
|
97
|
+
def worker_revision
|
98
|
+
ParallelWorkforce.configuration.revision_builder&.revision
|
99
|
+
end
|
100
|
+
|
101
|
+
def warn(*messages)
|
102
|
+
ParallelWorkforce.log(:warn, *messages)
|
103
|
+
end
|
104
|
+
|
105
|
+
def error(*messages)
|
106
|
+
ParallelWorkforce.log(:error, *messages)
|
107
|
+
end
|
108
|
+
|
109
|
+
def handle_exception(exception)
|
110
|
+
# swallow exceptions, no need to retry
|
111
|
+
error("#{self.class}: #{exception}", *exception.backtrace)
|
112
|
+
|
113
|
+
{
|
114
|
+
error: "Unhandled exception. #{exception.class} #{exception.message}",
|
115
|
+
}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "version"
|
2
|
+
require_relative "executor"
|
3
|
+
require_relative "configuration"
|
4
|
+
require_relative "job/util/performer"
|
5
|
+
require_relative "redis_connector/redis_pool"
|
6
|
+
require_relative "revision_builder/files_hash"
|
7
|
+
require_relative "serializer/marshal"
|
8
|
+
|
9
|
+
# rubocop:disable Lint/HandleExceptions
|
10
|
+
begin
|
11
|
+
require 'active_job'
|
12
|
+
rescue LoadError
|
13
|
+
end
|
14
|
+
begin
|
15
|
+
require 'rails'
|
16
|
+
rescue LoadError
|
17
|
+
end
|
18
|
+
begin
|
19
|
+
require 'sidekiq'
|
20
|
+
rescue LoadError
|
21
|
+
end
|
22
|
+
# rubocop:enable Lint/HandleExceptions
|
23
|
+
|
24
|
+
if defined?(::ActiveJob)
|
25
|
+
require_relative 'job/active_job'
|
26
|
+
if defined?(::Rails)
|
27
|
+
require_relative 'job/active_job_rails'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if defined?(::Sidekiq)
|
32
|
+
require_relative 'redis_connector/sidekiq_redis_pool'
|
33
|
+
require_relative 'job/sidekiq'
|
34
|
+
if defined?(::Rails)
|
35
|
+
require_relative 'job/sidekiq_rails'
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ParallelWorkforce
|
2
|
+
module RevisionBuilder
|
3
|
+
class FilesHash
|
4
|
+
attr_reader :revision
|
5
|
+
|
6
|
+
def initialize(files=Dir["#{File.expand_path('.')}/**/*.rb"])
|
7
|
+
@revision = build_revision(files).freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def build_revision(files)
|
13
|
+
Digest::MD5.new.tap do |digest|
|
14
|
+
files.sort.each { |file| digest << File.read(file) }
|
15
|
+
end.hexdigest
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ParallelWorkforce
|
2
|
+
module Serializer
|
3
|
+
class Marshal
|
4
|
+
def serialize(object)
|
5
|
+
::Marshal.dump(object)
|
6
|
+
rescue TypeError => e
|
7
|
+
ParallelWorkforce.log(:error, "#{self.class}: Unable to serialize object: #{e}", e, *e.backtrace)
|
8
|
+
|
9
|
+
raise ParallelWorkforce::SerializerError.new("Unable to serialize object: #{e}")
|
10
|
+
end
|
11
|
+
|
12
|
+
def deserialize(string)
|
13
|
+
::Marshal.load(string)
|
14
|
+
rescue TypeError => e
|
15
|
+
ParallelWorkforce.log(:warn, "#{self.class}: Unable to deserialize string: #{e}", e, *e.backtrace)
|
16
|
+
|
17
|
+
raise ParallelWorkforce::SerializerError.new("Unable to deserialize string: #{e}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'parallel_workforce/requires'
|
2
|
+
|
3
|
+
module ParallelWorkforce
|
4
|
+
Error = Class.new(StandardError)
|
5
|
+
ActorPerformError = Class.new(Error)
|
6
|
+
ActorNotFoundError = Class.new(Error)
|
7
|
+
TimeoutError = Class.new(Error)
|
8
|
+
SerializerError = Class.new(Error)
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# +actor_classes+: a single class or array of classes that have a perform method and can be initialized with no args.
|
12
|
+
# If an array is passed, the array size must batch the action_args_array size.
|
13
|
+
# Return results array with element from each action in the order of the job_args_array
|
14
|
+
# rubocop:disable Metrics/ParameterLists
|
15
|
+
def perform_all(actor_classes:, actor_args_array:,
|
16
|
+
serial_execution_indexes: nil, execute_serially: nil, job_class: nil, &execution_block)
|
17
|
+
ParallelWorkforce::Executor.new(
|
18
|
+
actor_classes: actor_classes,
|
19
|
+
actor_args_array: actor_args_array,
|
20
|
+
execute_serially: execute_serially,
|
21
|
+
serial_execution_indexes: serial_execution_indexes,
|
22
|
+
job_class: job_class,
|
23
|
+
execution_block: execution_block,
|
24
|
+
).perform_all
|
25
|
+
end
|
26
|
+
# rubocop:enable Metrics/ParameterLists
|
27
|
+
|
28
|
+
def configuration
|
29
|
+
@configuration ||= Configuration.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def configure(&block)
|
33
|
+
yield(configuration)
|
34
|
+
end
|
35
|
+
|
36
|
+
def log(level, *messages)
|
37
|
+
return if configuration.logger.nil?
|
38
|
+
|
39
|
+
messages.each do |message|
|
40
|
+
configuration.logger.send(level, message)
|
41
|
+
end
|
42
|
+
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "parallel_workforce/version"
|
4
|
+
|
5
|
+
# rubocop:disable Metrics/BlockLength
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "parallel_workforce"
|
8
|
+
spec.version = ParallelWorkforce::VERSION
|
9
|
+
spec.authors = ["Michael Pearce"]
|
10
|
+
spec.email = ["michael.p@enjoy.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Simplify parallel code execution into workers}
|
13
|
+
spec.description = %q{Simplify parallel code execution into workers.}
|
14
|
+
spec.homepage = "https://github.com/EnjoyTech/parallel_workforce"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
23
|
+
spec.metadata["changelog_uri"] = "https://github.com/EnjoyTech/parallel_workforce/CHANGELOG.md"
|
24
|
+
else
|
25
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
26
|
+
"public gem pushes."
|
27
|
+
end
|
28
|
+
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
+
spec.files = Dir.chdir(File.expand_path('.', __dir__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
|
+
end
|
34
|
+
spec.bindir = "exe"
|
35
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
|
+
spec.require_paths = ["lib"]
|
37
|
+
|
38
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
39
|
+
spec.add_development_dependency "fakeredis", "~> 0.7"
|
40
|
+
spec.add_development_dependency "pry", "~> 0.12"
|
41
|
+
spec.add_development_dependency "rails", "~> 4.2"
|
42
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
43
|
+
spec.add_development_dependency "rspec", "~> 3.8"
|
44
|
+
spec.add_development_dependency "rubocop", "~> 0.65"
|
45
|
+
spec.add_development_dependency "rubocop-rspec", "~> 1.32"
|
46
|
+
spec.add_development_dependency "sidekiq", "~> 4.0"
|
47
|
+
end
|
48
|
+
# rubocop:enable Metrics/BlockLength
|
metadata
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: parallel_workforce
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Pearce
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fakeredis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.12'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.12'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.2'
|
62
|
+
type: :development
|
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: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.8'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.8'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.65'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.65'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop-rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.32'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.32'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sidekiq
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '4.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '4.0'
|
139
|
+
description: Simplify parallel code execution into workers.
|
140
|
+
email:
|
141
|
+
- michael.p@enjoy.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".gitignore"
|
147
|
+
- ".rspec"
|
148
|
+
- ".rubocop.yml"
|
149
|
+
- ".rubocop_parallel_workforce.yml"
|
150
|
+
- ".ruby-version"
|
151
|
+
- CHANGELOG.md
|
152
|
+
- Gemfile
|
153
|
+
- Gemfile.lock
|
154
|
+
- LICENSE
|
155
|
+
- README.md
|
156
|
+
- Rakefile
|
157
|
+
- bin/console
|
158
|
+
- bin/setup
|
159
|
+
- lib/parallel_workforce.rb
|
160
|
+
- lib/parallel_workforce/configuration.rb
|
161
|
+
- lib/parallel_workforce/executor.rb
|
162
|
+
- lib/parallel_workforce/job/active_job.rb
|
163
|
+
- lib/parallel_workforce/job/active_job_rails.rb
|
164
|
+
- lib/parallel_workforce/job/sidekiq.rb
|
165
|
+
- lib/parallel_workforce/job/sidekiq_rails.rb
|
166
|
+
- lib/parallel_workforce/job/util/performer.rb
|
167
|
+
- lib/parallel_workforce/redis_connector/redis_pool.rb
|
168
|
+
- lib/parallel_workforce/redis_connector/sidekiq_redis_pool.rb
|
169
|
+
- lib/parallel_workforce/requires.rb
|
170
|
+
- lib/parallel_workforce/revision_builder/files_hash.rb
|
171
|
+
- lib/parallel_workforce/serializer/marshal.rb
|
172
|
+
- lib/parallel_workforce/version.rb
|
173
|
+
- parallel_workforce.gemspec
|
174
|
+
homepage: https://github.com/EnjoyTech/parallel_workforce
|
175
|
+
licenses: []
|
176
|
+
metadata:
|
177
|
+
allowed_push_host: https://rubygems.org
|
178
|
+
homepage_uri: https://github.com/EnjoyTech/parallel_workforce
|
179
|
+
source_code_uri: https://github.com/EnjoyTech/parallel_workforce
|
180
|
+
changelog_uri: https://github.com/EnjoyTech/parallel_workforce/CHANGELOG.md
|
181
|
+
post_install_message:
|
182
|
+
rdoc_options: []
|
183
|
+
require_paths:
|
184
|
+
- lib
|
185
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
requirements: []
|
196
|
+
rubyforge_project:
|
197
|
+
rubygems_version: 2.5.2.1
|
198
|
+
signing_key:
|
199
|
+
specification_version: 4
|
200
|
+
summary: Simplify parallel code execution into workers
|
201
|
+
test_files: []
|