workers 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b66f1edc747b5df57e671c9efe7abbd4f36a863
4
- data.tar.gz: 16b9fcb187bfda5a629160de3b0c742c66f5f1b4
3
+ metadata.gz: 07932a16f900199549ba88c4eb68a9aee5bf79f3
4
+ data.tar.gz: 697e7518ffaab1a98fa034aa309b2076392b47d9
5
5
  SHA512:
6
- metadata.gz: 1c4db47993b135c9dfbb6d8feb703ee82946bd67f98a953ef00673e5b83d432426764ab84e2604650b46628c55e11172b76940960024b26a1a6b9cf5a924cb06
7
- data.tar.gz: 4d1a0306500a6e26741d0516ae0906b7ad9c9f5fc2e6ab76561174ab73c8dada2a88d683a4d3c2108d90b62b79c0a96e72f7f95716023c1238cea1cf36fd75bd
6
+ metadata.gz: 3b7ef7a498830b6d6eff47fe5068abd2180b317ddc80cd3f6d4073dd0c7defcb6d74db05664f08e757a314674c3ee750d34c2327189408d92c5ba429b7796109
7
+ data.tar.gz: 5559d5cd379dd854e4f1df50ecf8e3fdb8538af9a215f972dc65dd4434eb6caeeae803115687acd8a66c08fddb377e4efd018f45642e885f00459f53f700dc45
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.5
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in workers.gemspec
3
+ gem 'coveralls', :require => false
4
+
4
5
  gemspec
data/README.md CHANGED
@@ -1,10 +1,22 @@
1
- # Workers
1
+ # Workers [![Build Status](https://travis-ci.org/chadrem/workers.svg)](https://travis-ci.org/chadrem/workers) [![Coverage Status](https://coveralls.io/repos/chadrem/workers/badge.svg?branch=master&service=github)](https://coveralls.io/github/chadrem/workers?branch=master)
2
2
 
3
3
  Workers is a Ruby gem for performing work in background threads.
4
4
  Design goals include high performance, low latency, simple API, customizability, and multi-layered architecture.
5
5
  It provides a number of simple to use classes that solve a wide range of concurrency problems.
6
6
  It is used by [Tribe](https://github.com/chadrem/tribe "Tribe") to implement event-driven actors.
7
7
 
8
+ ## Contents
9
+
10
+ - [Installation](#installation)
11
+ - [Parallel Map](#parallel-map)
12
+ - [Tasks](#tasks)
13
+ - [Workers](#workers)
14
+ - [Pool](#pools)
15
+ - [Timers](#timers)
16
+ - [Schedulers](#schedulers)
17
+ - [Concurrency and performance](#concurrency-and-performance)
18
+ - [Contributing](#contributing)
19
+
8
20
  ## Installation
9
21
 
10
22
  Add this line to your application's Gemfile:
@@ -175,7 +187,7 @@ Note that you must handle exceptions yourself since you are working directly wit
175
187
 
176
188
  # Create a single worker.
177
189
  worker = Workers::Worker.new
178
-
190
+
179
191
  # Perform some work in the background.
180
192
  25.times do |i|
181
193
  worker.perform do
@@ -187,7 +199,7 @@ Note that you must handle exceptions yourself since you are working directly wit
187
199
  end
188
200
  end
189
201
  end
190
-
202
+
191
203
  # Tell the worker to shutdown.
192
204
  worker.shutdown
193
205
 
@@ -294,6 +306,17 @@ You can create additional schedulers as necessary:
294
306
  :pool => Workers::Pool.new # The workers pool used to execute timer callbacks.
295
307
  )
296
308
 
309
+ #### Bucket Schedulers
310
+
311
+ The Bucket scheduler class is a specialized scheduler designed to work around lock contention.
312
+ This is accomplished by using many pools (100 by default) each with a small number of workers (1 by default).
313
+ Timers are assigned to a scheduler by their ````hash```` value.
314
+ Most users will never need to use this class, but it is documented here for completeness.
315
+ Both the number of buckets and the number of workers assigned to each bucket are configurable.
316
+
317
+ # Create a bucket scheduler.
318
+ scheduler = Workers::BucketScheduler.new
319
+
297
320
  ## Concurrency and performance
298
321
 
299
322
  Workers is tested with both JRuby and MRI (C Ruby).
data/Rakefile CHANGED
@@ -1,13 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
2
3
 
3
- desc 'Start an IRB console with Workers loaded'
4
- task :console do
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
6
-
7
- require 'workers'
8
- require 'irb'
9
-
10
- ARGV.clear
11
-
12
- IRB.start
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
13
8
  end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "workers"
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
@@ -3,6 +3,7 @@ require 'monitor'
3
3
  require 'set'
4
4
 
5
5
  require 'workers/version'
6
+ require 'workers/exceptions'
6
7
  require 'workers/helpers'
7
8
  require 'workers/worker'
8
9
  require 'workers/pool'
@@ -18,7 +19,7 @@ require 'workers/task_group'
18
19
  module Workers
19
20
  def self.pool
20
21
  lock do
21
- return @pool ||= Workers::Pool.new
22
+ @pool ||= Workers::Pool.new
22
23
  end
23
24
  end
24
25
 
@@ -31,7 +32,7 @@ module Workers
31
32
 
32
33
  def self.scheduler
33
34
  lock do
34
- return @scheduler ||= Workers::Scheduler.new
35
+ @scheduler ||= Workers::Scheduler.new
35
36
  end
36
37
  end
37
38
 
@@ -18,29 +18,25 @@ module Workers
18
18
  def schedule(timer)
19
19
  @schedulers[timer.hash % @options[:bucket_size]].schedule(timer)
20
20
 
21
- return nil
21
+ nil
22
22
  end
23
23
 
24
24
  def unschedule(timer)
25
25
  @schedulers[timer.hash % @options[:bucket_size]].unschedule(timer)
26
26
 
27
- return nil
27
+ nil
28
28
  end
29
29
 
30
30
  def wakeup
31
31
  @schedulers.each { |s| s.wakeup }
32
32
 
33
- return nil
33
+ nil
34
34
  end
35
35
 
36
36
  def dispose
37
37
  @schedulers.each { |s| s.dispose }
38
38
 
39
- return nil
40
- end
41
-
42
- def alive?
43
- return @schedulers.all? { |s| s.alive? }
39
+ nil
44
40
  end
45
41
  end
46
42
  end
@@ -7,7 +7,7 @@ module Workers
7
7
  @command = command
8
8
  @data = data
9
9
 
10
- return nil
10
+ nil
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1,10 @@
1
+ module Workers
2
+ class WorkersError < RuntimeError; end
3
+ class UnknownEventError < WorkersError; end
4
+ class JoinError < WorkersError; end
5
+ class FailedTaskError < WorkersError; end
6
+ class InvalidStateError < WorkersError; end
7
+ class MaxTriesError < WorkersError; end
8
+ class MissingCallbackError < WorkersError; end
9
+ class PoolSizeError < WorkersError; end
10
+ end
@@ -17,7 +17,7 @@ module Workers
17
17
  end
18
18
 
19
19
  def concat_e(msg, e = nil)
20
- return e ? "#{msg}\nEXCEPTION: #{e.message}\n#{e.backtrace.join("\n")}\n--" : msg
20
+ e ? "#{msg}\nEXCEPTION: #{e.message}\n#{e.backtrace.join("\n")}\n--" : msg
21
21
  end
22
22
  end
23
23
  end
@@ -5,31 +5,31 @@ module Workers
5
5
  def initialize(logger)
6
6
  @logger = logger.is_a?(Workers::LogProxy) ? logger.logger : logger
7
7
 
8
- return nil
8
+ nil
9
9
  end
10
10
 
11
11
  def debug(msg)
12
12
  @logger.debug(msg) if @logger
13
13
 
14
- return nil
14
+ nil
15
15
  end
16
16
 
17
17
  def info(msg)
18
18
  @logger.info(msg) if @logger
19
19
 
20
- return nil
20
+ nil
21
21
  end
22
22
 
23
23
  def warn(msg)
24
24
  @logger.warn(msg) if @logger
25
25
 
26
- return nil
26
+ nil
27
27
  end
28
28
 
29
29
  def error(msg)
30
30
  @logger.error(msg) if @logger
31
31
 
32
- return nil
32
+ nil
33
33
  end
34
34
  end
35
35
  end
@@ -5,7 +5,7 @@ module Workers
5
5
 
6
6
  super(delay, options, &block)
7
7
 
8
- return nil
8
+ nil
9
9
  end
10
10
  end
11
11
  end
@@ -11,22 +11,23 @@ module Workers
11
11
  @lock = Monitor.new
12
12
  @workers = Set.new
13
13
  @size = 0
14
+ @exception_callback = options[:on_exception]
14
15
 
15
16
  expand(options[:size] || Workers::Pool::DEFAULT_POOL_SIZE)
16
17
 
17
- return nil
18
+ nil
18
19
  end
19
20
 
20
21
  def enqueue(command, data = nil)
21
22
  @input_queue.push(Event.new(command, data))
22
23
 
23
- return nil
24
+ nil
24
25
  end
25
26
 
26
27
  def perform(&block)
27
28
  enqueue(:perform, block)
28
29
 
29
- return nil
30
+ nil
30
31
  end
31
32
 
32
33
  def shutdown(&block)
@@ -36,7 +37,7 @@ module Workers
36
37
  end
37
38
  end
38
39
 
39
- return nil
40
+ nil
40
41
  end
41
42
 
42
43
  def join(max_wait = nil)
@@ -44,42 +45,40 @@ module Workers
44
45
  @workers.clear
45
46
  @size = 0
46
47
 
47
- return results
48
+ results
48
49
  end
49
50
 
50
- def dispose
51
- @lock.synchronize do
52
- shutdown
53
- join
54
- end
55
-
56
- return nil
51
+ def dispose(max_wait = nil)
52
+ shutdown
53
+ join(max_wait)
57
54
  end
58
55
 
59
56
  def inspect
60
- return "#<#{self.class.to_s}:0x#{(object_id << 1).to_s(16)} size=#{size}>"
57
+ "#<#{self.class.to_s}:0x#{(object_id << 1).to_s(16)} size=#{size}>"
61
58
  end
62
59
 
63
60
  def size
64
61
  @lock.synchronize do
65
- return @size
62
+ @size
66
63
  end
67
64
  end
68
65
 
69
66
  def expand(count)
70
67
  @lock.synchronize do
71
68
  count.times do
72
- @workers << @worker_class.new(:input_queue => @input_queue)
73
- @size += 1
69
+ worker = @worker_class.new(:input_queue => @input_queue, :die_on_exception => false,
70
+ :on_exception => @exception_callback, :logger => @logger)
71
+ @workers << worker
72
+ @size += 1
74
73
  end
75
74
  end
76
75
 
77
- return nil
76
+ nil
78
77
  end
79
78
 
80
79
  def contract(count, &block)
81
80
  @lock.synchronize do
82
- raise 'Count is too large.' if count > @size
81
+ raise Workers::PoolSizeError, 'Count is too large.' if count > @size
83
82
 
84
83
  count.times do
85
84
  callback = Proc.new do |worker|
@@ -92,7 +91,7 @@ module Workers
92
91
  end
93
92
  end
94
93
 
95
- return nil
94
+ nil
96
95
  end
97
96
 
98
97
  def resize(new_size)
@@ -104,7 +103,7 @@ module Workers
104
103
  end
105
104
  end
106
105
 
107
- return nil
106
+ nil
108
107
  end
109
108
 
110
109
  private
@@ -114,7 +113,7 @@ module Workers
114
113
  @workers.delete(worker)
115
114
  end
116
115
 
117
- return nil
116
+ nil
118
117
  end
119
118
  end
120
119
  end
@@ -9,7 +9,7 @@ module Workers
9
9
  @mutex = Mutex.new
10
10
  @thread = Thread.new { start_loop }
11
11
 
12
- return nil
12
+ nil
13
13
  end
14
14
 
15
15
  def schedule(timer)
@@ -19,7 +19,7 @@ module Workers
19
19
 
20
20
  wakeup
21
21
 
22
- return nil
22
+ nil
23
23
  end
24
24
 
25
25
  def unschedule(timer)
@@ -27,13 +27,13 @@ module Workers
27
27
  @schedule.delete(timer)
28
28
  end
29
29
 
30
- return nil
30
+ nil
31
31
  end
32
32
 
33
33
  def wakeup
34
34
  @thread.wakeup
35
35
 
36
- return nil
36
+ nil
37
37
  end
38
38
 
39
39
  def dispose
@@ -43,11 +43,11 @@ module Workers
43
43
  @thread.kill
44
44
  end
45
45
 
46
- return nil
46
+ nil
47
47
  end
48
48
 
49
49
  def alive?
50
- return @thread && @thread.alive?
50
+ @thread && @thread.alive?
51
51
  end
52
52
 
53
53
  private
@@ -64,7 +64,7 @@ module Workers
64
64
  delay ? sleep(delay) : sleep
65
65
  end
66
66
 
67
- return nil
67
+ nil
68
68
  end
69
69
 
70
70
  def process_overdue
@@ -84,7 +84,7 @@ module Workers
84
84
  @schedule << timer if timer.repeat
85
85
  end
86
86
 
87
- return nil
87
+ nil
88
88
  end
89
89
 
90
90
  def next_delay
@@ -12,19 +12,19 @@ module Workers
12
12
  def initialize(options = {})
13
13
  @logger = Workers::LogProxy.new(options[:logger])
14
14
  @input = options[:input] || []
15
- @perform = options[:perform] || raise('Perform callback is required.')
15
+ @perform = options[:perform] || raise(Workers::MissingCallbackError, 'Perform callback is required.')
16
16
  @finished = options[:finished]
17
17
  @max_tries = options[:max_tries] || 1
18
18
  @state = :initialized
19
19
  @tries = 0
20
20
 
21
- raise 'max_tries must be >= 1' unless @max_tries >= 1
21
+ raise Workers::MaxTriesError, 'max_tries must be >= 1' unless @max_tries >= 1
22
22
 
23
- return nil
23
+ nil
24
24
  end
25
25
 
26
26
  def run
27
- raise "Invalid state (#{@state})." unless @state == :initialized
27
+ raise Workers::InvalidStateError, "Invalid state (#{@state})." unless @state == :initialized
28
28
 
29
29
  @state = :running
30
30
 
@@ -43,15 +43,15 @@ module Workers
43
43
 
44
44
  @finished.call(self)
45
45
 
46
- return nil
46
+ nil
47
47
  end
48
48
 
49
49
  def succeeded?
50
- return @state == :succeeded
50
+ @state == :succeeded
51
51
  end
52
52
 
53
53
  def failed?
54
- return @state == :failed
54
+ @state == :failed
55
55
  end
56
56
  end
57
57
  end
@@ -15,7 +15,7 @@ module Workers
15
15
  @finished_count = 0
16
16
  @conditional = ConditionVariable.new
17
17
 
18
- return nil
18
+ nil
19
19
  end
20
20
 
21
21
  def add(options = {}, &block)
@@ -26,7 +26,7 @@ module Workers
26
26
 
27
27
  @tasks << Workers::Task.new(options)
28
28
 
29
- return nil
29
+ nil
30
30
  end
31
31
 
32
32
  def run
@@ -45,15 +45,15 @@ module Workers
45
45
  @conditional.wait(@internal_lock)
46
46
  end
47
47
 
48
- return @tasks.all? { |t| t.succeeded? }
48
+ @tasks.all? { |t| t.succeeded? }
49
49
  end
50
50
 
51
51
  def successes
52
- return @tasks.select { |t| t.succeeded? }
52
+ @tasks.select { |t| t.succeeded? }
53
53
  end
54
54
 
55
55
  def failures
56
- return @tasks.select { |t| t.failed? }
56
+ @tasks.select { |t| t.failed? }
57
57
  end
58
58
 
59
59
  def map(inputs, options = {}, &block)
@@ -70,10 +70,10 @@ module Workers
70
70
  m = failure.exception.message
71
71
  b = failure.exception.backtrace.join("\n")
72
72
 
73
- raise "At least one task failed. ARGS=#{a}, TRACE=#{m}\n#{b}\n----------\n"
73
+ raise Workers::FailedTaskError, "At least one task failed. ARGS=#{a}, TRACE=#{m}\n#{b}\n----------\n"
74
74
  end
75
75
 
76
- return tasks.map { |t| t.result }
76
+ tasks.map { |t| t.result }
77
77
  end
78
78
 
79
79
  # Convenient mutex to be used by a users's task code that needs serializing.
@@ -81,17 +81,17 @@ module Workers
81
81
  def synchronize(&block)
82
82
  @external_lock.synchronize { block.call }
83
83
 
84
- return nil
84
+ nil
85
85
  end
86
86
 
87
87
  private
88
88
 
89
89
  def state!(*args)
90
90
  unless args.include?(@state)
91
- raise "Invalid state (#{@state})."
91
+ raise Workers::InvalidStateError, "Invalid state (#{@state})."
92
92
  end
93
93
 
94
- return nil
94
+ nil
95
95
  end
96
96
 
97
97
  def finished(task)
@@ -100,7 +100,7 @@ module Workers
100
100
  @conditional.signal if @finished_count >= @tasks.count
101
101
  end
102
102
 
103
- return nil
103
+ nil
104
104
  end
105
105
  end
106
106
  end
@@ -16,23 +16,22 @@ module Workers
16
16
  reset
17
17
  @scheduler.schedule(self)
18
18
 
19
- return nil
19
+ nil
20
20
  end
21
21
 
22
22
  def <=>(other)
23
- return sec_remaining <=> other.sec_remaining
23
+ sec_remaining <=> other.sec_remaining
24
24
  end
25
25
 
26
26
  def sec_remaining
27
27
  @mutex.synchronize do
28
28
  diff = @fire_at.to_f - Time.now.utc.to_f
29
-
30
- return (diff > 0) ? diff : 0
29
+ (diff > 0) ? diff : 0
31
30
  end
32
31
  end
33
32
 
34
33
  def overdue?
35
- return sec_remaining <= 0
34
+ sec_remaining <= 0
36
35
  end
37
36
 
38
37
  def fire
@@ -40,13 +39,13 @@ module Workers
40
39
  @callback.call if @callback
41
40
  end
42
41
 
43
- return nil
42
+ nil
44
43
  end
45
44
 
46
45
  def cancel
47
46
  @scheduler.unschedule(self)
48
47
 
49
- return nil
48
+ nil
50
49
  end
51
50
 
52
51
  def reset
@@ -54,7 +53,7 @@ module Workers
54
53
  @fire_at = Time.now.utc + @delay
55
54
  end
56
55
 
57
- return nil
56
+ nil
58
57
  end
59
58
  end
60
59
  end
@@ -1,3 +1,3 @@
1
1
  module Workers
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -2,82 +2,106 @@ module Workers
2
2
  class Worker
3
3
  include Workers::Helpers
4
4
 
5
+ attr_accessor :exception
6
+
5
7
  def initialize(options = {})
6
8
  @logger = Workers::LogProxy.new(options[:logger])
7
9
  @input_queue = options[:input_queue] || Queue.new
8
10
  @thread = Thread.new { start_event_loop }
11
+ @exception_callback = options[:on_exception]
12
+ @die_on_exception = options.include?(:die_on_exception) ? options[:die_on_exception] : true
9
13
 
10
- return nil
14
+ nil
11
15
  end
12
16
 
13
17
  def enqueue(command, data = nil)
14
18
  @input_queue.push(Event.new(command, data))
15
19
 
16
- return nil
20
+ nil
17
21
  end
18
22
 
19
23
  def perform(&block)
20
24
  enqueue(:perform, block)
21
25
 
22
- return nil
26
+ nil
23
27
  end
24
28
 
25
29
  def shutdown(&block)
26
30
  enqueue(:shutdown, block)
27
31
 
28
- return nil
32
+ nil
33
+ end
34
+
35
+ def kill
36
+ @thread.kill
37
+
38
+ nil
29
39
  end
30
40
 
31
41
  def join(max_wait = nil)
32
- raise "Worker can't join itself." if @thread == Thread.current
42
+ raise Workers::JoinError, "Worker can't join itself." if @thread == Thread.current
33
43
 
34
44
  return true if !@thread.join(max_wait).nil?
35
45
 
36
46
  @thread.kill and return false
37
47
  end
38
48
 
49
+ def dispose(max_wait = nil)
50
+ shutdown
51
+ join(max_wait)
52
+ end
53
+
39
54
  def alive?
40
- return @thread && @thread.alive?
55
+ @thread && @thread.alive?
41
56
  end
42
57
 
43
58
  def inspect
44
- return "#<#{self.class.to_s}:0x#{(object_id << 1).to_s(16)} #{alive? ? 'alive' : 'dead'}>"
59
+ "#<#{self.class.to_s}:0x#{(object_id << 1).to_s(16)} #{alive? ? 'alive' : 'dead'}>"
45
60
  end
46
61
 
47
62
  private
48
63
 
49
64
  def start_event_loop
50
- while true
51
- event = @input_queue.pop
52
-
53
- case event.command
54
- when :shutdown
55
- shutdown_handler(event)
56
- return nil
57
- when :perform
58
- perform_handler(event)
59
- else
60
- process_event(event)
61
- end
65
+ while process_event; end
66
+ end
67
+
68
+ def process_event
69
+ event = @input_queue.pop
70
+
71
+ case event.command
72
+ when :shutdown
73
+ shutdown_handler(event)
74
+ return false
75
+ when :perform
76
+ perform_handler(event)
77
+ else
78
+ raise Workers::UnknownEventError, "Unhandled event (#{event.inspect})."
62
79
  end
80
+
81
+ true
63
82
  rescue Exception => e
64
83
  exception_handler(e)
84
+ true
65
85
  end
66
86
 
67
87
  def shutdown_handler(event)
68
88
  event.data.call(self) if event.data
89
+
90
+ nil
69
91
  end
70
92
 
71
93
  def perform_handler(event)
72
- event.data.call if event.data
94
+ event.data.call
95
+
96
+ nil
73
97
  end
74
98
 
75
99
  def exception_handler(e)
76
- puts concat_e('Worker event loop died.', e)
77
- end
100
+ @exception = e
101
+ @exception_callback.call(e) if @exception_callback
102
+ raise(e) if @die_on_exception
78
103
 
79
- def process_event(event)
80
- raise "Unhandled event (#{event.inspect}). Subclass and override if you need custom events."
104
+ nil
81
105
  end
82
106
  end
83
107
  end
@@ -1,19 +1,24 @@
1
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'workers/version'
5
5
 
6
- Gem::Specification.new do |gem|
7
- gem.name = 'workers'
8
- gem.version = Workers::VERSION
9
- gem.authors = ['Chad Remesch']
10
- gem.email = ['chad@remesch.com']
11
- gem.description = %q{Workers is a Ruby gem for performing work in background threads.}
12
- gem.summary = %q{Workers is a Ruby gem for performing work in background threads. Design goals include high performance, low latency, simple API, customizability, and multi-layered architecture. It provides a number of simple to use classes that solve a wide range of concurrency problems.}
13
- gem.homepage = 'https://github.com/chadrem/workers'
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "workers"
8
+ spec.version = Workers::VERSION
9
+ spec.authors = ["Chad Remesch"]
10
+ spec.email = ["chad@remesch.com"]
14
11
 
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ['lib']
12
+ spec.summary = %q{A Ruby gem for performing work in background threads.}
13
+ spec.homepage = "https://github.com/chadrem/workers"
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
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest"
19
24
  end
metadata CHANGED
@@ -1,16 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chad Remesch
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2015-02-23 00:00:00.000000000 Z
12
- dependencies: []
13
- description: Workers is a Ruby gem for performing work in background threads.
11
+ date: 2015-07-20 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.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
14
56
  email:
15
57
  - chad@remesch.com
16
58
  executables: []
@@ -18,13 +60,17 @@ extensions: []
18
60
  extra_rdoc_files: []
19
61
  files:
20
62
  - ".gitignore"
63
+ - ".travis.yml"
21
64
  - Gemfile
22
65
  - LICENSE.txt
23
66
  - README.md
24
67
  - Rakefile
68
+ - bin/console
69
+ - bin/setup
25
70
  - lib/workers.rb
26
71
  - lib/workers/bucket_scheduler.rb
27
72
  - lib/workers/event.rb
73
+ - lib/workers/exceptions.rb
28
74
  - lib/workers/helpers.rb
29
75
  - lib/workers/log_proxy.rb
30
76
  - lib/workers/periodic_timer.rb
@@ -37,7 +83,8 @@ files:
37
83
  - lib/workers/worker.rb
38
84
  - workers.gemspec
39
85
  homepage: https://github.com/chadrem/workers
40
- licenses: []
86
+ licenses:
87
+ - MIT
41
88
  metadata: {}
42
89
  post_install_message:
43
90
  rdoc_options: []
@@ -58,8 +105,5 @@ rubyforge_project:
58
105
  rubygems_version: 2.4.5
59
106
  signing_key:
60
107
  specification_version: 4
61
- summary: Workers is a Ruby gem for performing work in background threads. Design goals
62
- include high performance, low latency, simple API, customizability, and multi-layered
63
- architecture. It provides a number of simple to use classes that solve a wide range
64
- of concurrency problems.
108
+ summary: A Ruby gem for performing work in background threads.
65
109
  test_files: []