threasy 0.4.1 → 0.5.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 +4 -4
- data/README.md +10 -9
- data/lib/threasy/config.rb +3 -1
- data/lib/threasy/schedule/entry.rb +3 -2
- data/lib/threasy/version.rb +1 -1
- data/lib/threasy/work.rb +26 -17
- data/spec/threasy/schedule_spec.rb +10 -0
- data/spec/threasy/work_spec.rb +12 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 11e5f8c6348eca49829c58687a62ce48a414b97c
|
|
4
|
+
data.tar.gz: 94b1c10c04d5a9ec92e66d592c8ab694d4ddc625
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1523591989b79b83ea7e94eeb158d365b80ffb6fbb32d2ac4ee5109414b9124fa49862f1d9b0b860c63d704b277f31432f37327b4957ae14a71b9404f0ce2b8e
|
|
7
|
+
data.tar.gz: 36e4ff11898c517f8f5196d011dc1538bd8d405933446d955d36a67a31034d9bdc968ff7ae64b939324dd4005545db7bbc65b96d8099f1274813b920de70e589
|
data/README.md
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
[travis-image]: https://secure.travis-ci.org/carlzulauf/threasy.png?branch=master
|
|
4
4
|
[travis-link]: http://travis-ci.org/carlzulauf/threasy
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Thr**eaded, **easy** to use scheduling and background job solution.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Schedules are managed by a watcher thread and enqueued as background jobs when they are due.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Background work is stored in a thread-safe `Queue` and worked on by a pool of worker threads.
|
|
11
11
|
|
|
12
12
|
### What to expect
|
|
13
13
|
|
|
14
|
-
*
|
|
14
|
+
* Simple API
|
|
15
15
|
* Ability to queue or schedule ruby blocks for asynchronus execution
|
|
16
16
|
* Extremely light-weight
|
|
17
17
|
* No dependencies (outside ruby stdlib)
|
|
@@ -45,7 +45,7 @@ Or install it yourself as:
|
|
|
45
45
|
|
|
46
46
|
## Usage
|
|
47
47
|
|
|
48
|
-
### `enqueue`
|
|
48
|
+
### `Threasy.enqueue`
|
|
49
49
|
|
|
50
50
|
```ruby
|
|
51
51
|
# Use a block
|
|
@@ -57,7 +57,7 @@ Threasy.enqueue MyJob.new(1,2,3)
|
|
|
57
57
|
|
|
58
58
|
Jobs are placed in a work queue. Worker threads are spun up to process jobs as the queue grows.
|
|
59
59
|
|
|
60
|
-
### `schedule`
|
|
60
|
+
### `Threasy.schedule`
|
|
61
61
|
|
|
62
62
|
Puts a job onto the schedule. Once the scheduler sees a job is due for processessing, it is enqueued into the work queue to be processed like any other job.
|
|
63
63
|
|
|
@@ -66,6 +66,7 @@ Available options:
|
|
|
66
66
|
* `:every`: number of seconds between repetition. Can be combined with `:at` or `:in`.
|
|
67
67
|
* `:in`: number of seconds until job is (next) triggered.
|
|
68
68
|
* `:at`: `Time` job is (next) triggered.
|
|
69
|
+
* `:times`: number of times to trigger job before removing it from the schedule.
|
|
69
70
|
|
|
70
71
|
Example:
|
|
71
72
|
|
|
@@ -77,15 +78,15 @@ Threasy.schedule(:in => 5.minutes) { puts "In the background, 5 minutes from now
|
|
|
77
78
|
Threasy.schedule(MyJob.new(1,2,3), every: 5.minutes)
|
|
78
79
|
```
|
|
79
80
|
|
|
80
|
-
### `schedules`
|
|
81
|
+
### `Threasy.schedules`
|
|
81
82
|
|
|
82
83
|
Returns the default instance of [`Threasy::Schedule`][schedule], which manages scheduled jobs.
|
|
83
84
|
|
|
84
|
-
### `work`
|
|
85
|
+
### `Threasy.work`
|
|
85
86
|
|
|
86
87
|
Returns the default instance of [`Threasy::Work`][work], which manages the work queue and worker threads.
|
|
87
88
|
|
|
88
|
-
### `config`
|
|
89
|
+
### `Threasy.config`
|
|
89
90
|
|
|
90
91
|
Returns the default instance of [`Threasy::Config`][config], which manages runtime configuration options.
|
|
91
92
|
|
data/lib/threasy/config.rb
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
module Threasy
|
|
2
2
|
class Config
|
|
3
|
-
attr_accessor :work, :schedule
|
|
3
|
+
attr_accessor :work, :schedule
|
|
4
|
+
attr_accessor :min_workers, :max_workers, :max_sleep, :max_overdue
|
|
4
5
|
attr_writer :logger
|
|
5
6
|
|
|
6
7
|
def initialize
|
|
8
|
+
self.min_workers = 1
|
|
7
9
|
self.max_workers = 4
|
|
8
10
|
self.max_sleep = 60.0
|
|
9
11
|
self.max_overdue = 300.0
|
|
@@ -11,7 +11,7 @@ module Threasy
|
|
|
11
11
|
# and should not be created by hand.
|
|
12
12
|
#
|
|
13
13
|
# See `Threasy::Schedule#add`
|
|
14
|
-
attr_accessor :schedule, :work, :job, :at, :repeat, :times
|
|
14
|
+
attr_accessor :schedule, :work, :job, :args, :at, :repeat, :times
|
|
15
15
|
|
|
16
16
|
def initialize(job, options = {})
|
|
17
17
|
self.schedule = options.fetch(:schedule) { Threasy.schedules }
|
|
@@ -21,6 +21,7 @@ module Threasy
|
|
|
21
21
|
seconds = options.fetch(:in) { repeat || 60 }
|
|
22
22
|
self.at = options.fetch(:at) { Time.now + seconds }
|
|
23
23
|
self.times = options[:times]
|
|
24
|
+
self.args = options.fetch(:args) { [] }
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
def repeat?
|
|
@@ -49,7 +50,7 @@ module Threasy
|
|
|
49
50
|
|
|
50
51
|
def work!
|
|
51
52
|
if once? || overdue < max_overdue
|
|
52
|
-
work.enqueue(job) if times_remaining?
|
|
53
|
+
work.enqueue(job, *args) if times_remaining?
|
|
53
54
|
self.times -= 1 unless times.nil?
|
|
54
55
|
end
|
|
55
56
|
|
data/lib/threasy/version.rb
CHANGED
data/lib/threasy/work.rb
CHANGED
|
@@ -19,6 +19,7 @@ module Threasy
|
|
|
19
19
|
@queue = TimeoutQueue.new
|
|
20
20
|
@pool = Set.new
|
|
21
21
|
@semaphore = Mutex.new
|
|
22
|
+
min_workers.times { add_worker }
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
# Enqueue a job into the work queue
|
|
@@ -36,8 +37,9 @@ module Threasy
|
|
|
36
37
|
# # Enqueue string that evals to a job object
|
|
37
38
|
# Threasy.enqueue("BackgroundJob.new")
|
|
38
39
|
#
|
|
39
|
-
def enqueue(
|
|
40
|
-
|
|
40
|
+
def enqueue(*args, &block)
|
|
41
|
+
args.unshift(block) if block_given?
|
|
42
|
+
queue.push(args).tap { check_workers }
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
alias_method :enqueue_block, :enqueue
|
|
@@ -50,6 +52,10 @@ module Threasy
|
|
|
50
52
|
queue.pop
|
|
51
53
|
end
|
|
52
54
|
|
|
55
|
+
def min_workers
|
|
56
|
+
Threasy.config.min_workers
|
|
57
|
+
end
|
|
58
|
+
|
|
53
59
|
def max_workers
|
|
54
60
|
Threasy.config.max_workers
|
|
55
61
|
end
|
|
@@ -57,17 +63,16 @@ module Threasy
|
|
|
57
63
|
def check_workers
|
|
58
64
|
sync do
|
|
59
65
|
pool_size = pool.size
|
|
60
|
-
|
|
61
|
-
log "Checking workers. Pool: #{pool_size}, Max: #{max_workers}, Queue: #{queue_size}"
|
|
66
|
+
log "Checking workers. Pool: #{pool_size} (min: #{min_workers}, max: #{max_workers})"
|
|
62
67
|
if pool_size < max_workers
|
|
63
|
-
add_worker
|
|
68
|
+
add_worker if pool_size == 0 || queue.size > max_workers
|
|
64
69
|
end
|
|
65
70
|
end
|
|
66
71
|
end
|
|
67
72
|
|
|
68
|
-
def add_worker
|
|
73
|
+
def add_worker
|
|
69
74
|
log "Adding new worker to pool"
|
|
70
|
-
worker = Worker.new(self, size)
|
|
75
|
+
worker = Worker.new(self, pool.size)
|
|
71
76
|
pool.add worker
|
|
72
77
|
worker.work
|
|
73
78
|
end
|
|
@@ -87,18 +92,22 @@ module Threasy
|
|
|
87
92
|
end
|
|
88
93
|
|
|
89
94
|
def work
|
|
90
|
-
Thread.start do
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
@thread = Thread.start do
|
|
96
|
+
loop do
|
|
97
|
+
if args = @work.grab
|
|
98
|
+
job = args.shift
|
|
99
|
+
log.debug "Worker ##{@id} has grabbed a job"
|
|
100
|
+
begin
|
|
101
|
+
job = eval(job) if job.kind_of?(String)
|
|
102
|
+
job.respond_to?(:perform) ? job.perform(*args) : job.call(*args)
|
|
103
|
+
rescue Exception => e
|
|
104
|
+
log.error %|Worker ##{@id} error: #{e.message}\n#{e.backtrace.join("\n")}|
|
|
105
|
+
end
|
|
106
|
+
elsif @work.pool.size > @work.min_workers
|
|
107
|
+
@work.sync { @work.pool.delete self }
|
|
108
|
+
break
|
|
98
109
|
end
|
|
99
110
|
end
|
|
100
|
-
log.debug "Worker ##{@id} removing self from pool"
|
|
101
|
-
@work.sync{ @work.pool.delete self }
|
|
102
111
|
end
|
|
103
112
|
end
|
|
104
113
|
|
|
@@ -36,6 +36,16 @@ describe "Threasy::Schedule" do
|
|
|
36
36
|
expect(subject).not_to receive(:add_entry)
|
|
37
37
|
subject.add(job, at: Time.now - 100)
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
it "should pass optional arguments onto job when its worked" do
|
|
41
|
+
async do |done|
|
|
42
|
+
args = [:foo, :bar]
|
|
43
|
+
subject.add(in: 0.01, args: args) do |*a|
|
|
44
|
+
expect(a).to eq(args)
|
|
45
|
+
done.()
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
39
49
|
end
|
|
40
50
|
|
|
41
51
|
describe "#remove" do
|
data/spec/threasy/work_spec.rb
CHANGED
|
@@ -3,7 +3,7 @@ class TestJob
|
|
|
3
3
|
@resolver = resolver
|
|
4
4
|
end
|
|
5
5
|
|
|
6
|
-
def perform
|
|
6
|
+
def perform(*args)
|
|
7
7
|
@resolver.()
|
|
8
8
|
end
|
|
9
9
|
end
|
|
@@ -36,5 +36,16 @@ describe "Threasy::Work" do
|
|
|
36
36
|
subject.enqueue { done.() }
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
it "should pass optional arguments onto job" do
|
|
41
|
+
async do |done|
|
|
42
|
+
args = [:foo, :bar]
|
|
43
|
+
job = proc do |*a|
|
|
44
|
+
expect(a).to eq(args)
|
|
45
|
+
done.()
|
|
46
|
+
end
|
|
47
|
+
subject.enqueue job, *args
|
|
48
|
+
end
|
|
49
|
+
end
|
|
39
50
|
end
|
|
40
51
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: threasy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Carl Zulauf
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-09-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|