workers 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: []