async-job 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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/async/job/backend/inline/server.rb +12 -11
- data/lib/async/job/backend/inline.rb +2 -2
- data/lib/async/job/backend/redis/server.rb +16 -11
- data/lib/async/job/backend/redis.rb +2 -2
- data/lib/async/job/buffer.rb +8 -1
- data/lib/async/job/builder.rb +70 -0
- data/lib/async/job/coder/json.rb +27 -0
- data/lib/async/job/coder/marshal.rb +24 -0
- data/lib/async/job/coder/message_pack.rb +35 -0
- data/lib/async/job/coder.rb +31 -0
- data/lib/async/job/generic.rb +3 -3
- data/lib/async/job/version.rb +1 -1
- data/lib/async/job.rb +1 -0
- data/readme.md +5 -1
- data.tar.gz.sig +0 -0
- metadata +8 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e330cf8c0430796e25264e8c892f70423f1fa0ffbc645a19198774f51ef4893
|
4
|
+
data.tar.gz: 3c1ac69a6bde193876717c65dace5e97803b66ab9471d5baeffc33bb1762701a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 956e76aadce5f21fd099ba72d38914f4a4a6981a1d4382eee34a7bc37a0d79cb7bedb6b93000146a752fdc829945a93c72ef873fc3012acda5f6ea50d58128ae
|
7
|
+
data.tar.gz: 8fb1c37bc2f065c08a08dbdc25f04dbfe2aab5d67eb57c297a50fb5665e9840014fe1c3bd7257fc2dfa463919507fdf450dcaa71d1c17dc5cde0441b949c108b
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -3,25 +3,26 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2024, by Samuel Williams.
|
5
5
|
|
6
|
+
require_relative '../../coder'
|
7
|
+
|
6
8
|
module Async
|
7
9
|
module Job
|
8
10
|
module Backend
|
9
11
|
module Inline
|
10
12
|
class Server
|
11
|
-
def initialize(
|
12
|
-
@
|
13
|
-
end
|
14
|
-
|
15
|
-
def enqueue(job)
|
16
|
-
Async do
|
17
|
-
@handler.call(job)
|
18
|
-
end
|
13
|
+
def initialize(delegate)
|
14
|
+
@delegate = delegate
|
19
15
|
end
|
20
16
|
|
21
|
-
def
|
17
|
+
def call(job)
|
18
|
+
scheduled_at = Coder::Time(job["scheduled_at"])
|
19
|
+
|
22
20
|
Async do
|
23
|
-
|
24
|
-
|
21
|
+
if scheduled_at
|
22
|
+
sleep(scheduled_at - Time.now)
|
23
|
+
end
|
24
|
+
|
25
|
+
@delegate.call(job)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
@@ -9,18 +9,21 @@ require_relative 'processing_queue'
|
|
9
9
|
require_relative 'ready_queue'
|
10
10
|
|
11
11
|
require 'securerandom'
|
12
|
+
require_relative '../../coder'
|
12
13
|
|
13
14
|
module Async
|
14
15
|
module Job
|
15
16
|
module Backend
|
16
17
|
module Redis
|
17
18
|
class Server
|
18
|
-
def initialize(
|
19
|
-
@
|
19
|
+
def initialize(delegate, client, prefix: 'async-job', coder: Coder::DEFAULT, resolution: 10)
|
20
|
+
@delegate = delegate
|
20
21
|
|
21
22
|
@id = SecureRandom.uuid
|
22
23
|
@client = client
|
23
24
|
@prefix = prefix
|
25
|
+
@coder = coder
|
26
|
+
@resolution = resolution
|
24
27
|
|
25
28
|
@job_store = JobStore.new(@client, "#{@prefix}:jobs")
|
26
29
|
|
@@ -33,7 +36,7 @@ module Async
|
|
33
36
|
def start
|
34
37
|
Console.info(self, "Starting server...")
|
35
38
|
# Start the delayed queue, which will move jobs to the ready queue when they are ready:
|
36
|
-
@delayed_queue.start(@ready_queue)
|
39
|
+
@delayed_queue.start(@ready_queue, resolution: @resolution)
|
37
40
|
|
38
41
|
# Start the processing queue, which will move jobs to the ready queue when they are abandoned:
|
39
42
|
@processing_queue.start
|
@@ -43,12 +46,14 @@ module Async
|
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
def call(job)
|
50
|
+
scheduled_at = Coder::Time(job["scheduled_at"])
|
51
|
+
|
52
|
+
if scheduled_at
|
53
|
+
@delayed_queue.add(@coder.dump(job), scheduled_at, @job_store)
|
54
|
+
else
|
55
|
+
@ready_queue.add(@coder.dump(job), @job_store)
|
56
|
+
end
|
52
57
|
end
|
53
58
|
|
54
59
|
protected
|
@@ -56,8 +61,8 @@ module Async
|
|
56
61
|
def dequeue
|
57
62
|
id = @processing_queue.fetch
|
58
63
|
begin
|
59
|
-
job = @job_store.get(id)
|
60
|
-
@
|
64
|
+
job = @coder.load(@job_store.get(id))
|
65
|
+
@delegate.call(job)
|
61
66
|
@processing_queue.complete(id)
|
62
67
|
rescue => error
|
63
68
|
@processing_queue.retry(id)
|
@@ -10,9 +10,9 @@ module Async
|
|
10
10
|
module Job
|
11
11
|
module Backend
|
12
12
|
module Redis
|
13
|
-
def self.new(
|
13
|
+
def self.new(delegate, endpoint: Async::Redis.local_endpoint, **options)
|
14
14
|
client = Async::Redis::Client.new(endpoint)
|
15
|
-
return Server.new(
|
15
|
+
return Server.new(delegate, client, **options)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/async/job/buffer.rb
CHANGED
@@ -1,16 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
1
6
|
require 'async/queue'
|
2
7
|
|
3
8
|
module Async
|
4
9
|
module Job
|
5
10
|
class Buffer
|
6
|
-
def initialize
|
11
|
+
def initialize(delegate = nil)
|
7
12
|
@jobs = Async::Queue.new
|
13
|
+
@delegate = delegate
|
8
14
|
end
|
9
15
|
|
10
16
|
attr :jobs
|
11
17
|
|
12
18
|
def call(job)
|
13
19
|
@jobs.enqueue(job)
|
20
|
+
@delegate&.call(job)
|
14
21
|
end
|
15
22
|
|
16
23
|
def pop
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
module Async
|
7
|
+
module Job
|
8
|
+
class Builder
|
9
|
+
Pipeline = Struct.new(:producer, :consumer, :delegate)
|
10
|
+
|
11
|
+
def self.build(delegate = nil, &block)
|
12
|
+
builder = self.new(delegate)
|
13
|
+
|
14
|
+
builder.instance_eval(&block)
|
15
|
+
|
16
|
+
return builder.build
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(delegate = nil)
|
20
|
+
@enqueue = []
|
21
|
+
@dequeue = []
|
22
|
+
@delegate = delegate
|
23
|
+
|
24
|
+
@queue = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def enqueue(middleware)
|
28
|
+
@enqueue << middleware
|
29
|
+
end
|
30
|
+
|
31
|
+
def queue(queue, *arguments, **options)
|
32
|
+
# The delegate is the output side of the queue, e.g. a Queuedelegate or similar wrapper.
|
33
|
+
# The queue itself is instantiated with the delegate.
|
34
|
+
@queue = ->(delegate){queue.new(delegate, *arguments, **options)}
|
35
|
+
end
|
36
|
+
|
37
|
+
def dequeue(middleware)
|
38
|
+
@dequeue << middleware
|
39
|
+
end
|
40
|
+
|
41
|
+
def delegate(delegate)
|
42
|
+
@delegate = delegate
|
43
|
+
end
|
44
|
+
|
45
|
+
def build(&block)
|
46
|
+
# To construct the queue, we need the delegate.
|
47
|
+
delegate = @delegate
|
48
|
+
|
49
|
+
# We then wrap the delegate with the middleware in reverse order:
|
50
|
+
@dequeue.reverse_each do |middleware|
|
51
|
+
delegate = middleware.new(delegate)
|
52
|
+
end
|
53
|
+
|
54
|
+
# We can now construct the queue with the delegate:
|
55
|
+
producer = consumer = @queue.call(delegate)
|
56
|
+
|
57
|
+
# We now construct the queue producer:
|
58
|
+
@enqueue.reverse_each do |middleware|
|
59
|
+
producer = middleware.new(queue)
|
60
|
+
end
|
61
|
+
|
62
|
+
if block_given?
|
63
|
+
producer = yield(producer)
|
64
|
+
end
|
65
|
+
|
66
|
+
return Pipeline.new(producer, consumer, @delegate)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Async
|
9
|
+
module Job
|
10
|
+
module Coder
|
11
|
+
class JSON
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def dump(job)
|
16
|
+
::JSON.dump(job)
|
17
|
+
end
|
18
|
+
|
19
|
+
def load(data)
|
20
|
+
::JSON.parse(data, symbolize_names: true)
|
21
|
+
end
|
22
|
+
|
23
|
+
DEFAULT = self.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'msgpack'
|
7
|
+
|
8
|
+
module Async
|
9
|
+
module Job
|
10
|
+
module Coder
|
11
|
+
class Marshal
|
12
|
+
def dump(job)
|
13
|
+
::Marshal.dump(job)
|
14
|
+
end
|
15
|
+
|
16
|
+
def load(data)
|
17
|
+
::Marshal.load(data)
|
18
|
+
end
|
19
|
+
|
20
|
+
DEFAULT = self.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'msgpack'
|
7
|
+
|
8
|
+
module Async
|
9
|
+
module Job
|
10
|
+
module Coder
|
11
|
+
class MessagePack
|
12
|
+
def initialize
|
13
|
+
@factory = ::MessagePack::Factory.new
|
14
|
+
|
15
|
+
@factory.register_type(0x01, Symbol)
|
16
|
+
|
17
|
+
@factory.register_type(0x02, Time,
|
18
|
+
packer: ::MessagePack::Time::Packer,
|
19
|
+
unpacker: ::MessagePack::Time::Unpacker
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def dump(job)
|
24
|
+
@factory.pack(job)
|
25
|
+
end
|
26
|
+
|
27
|
+
def load(data)
|
28
|
+
@factory.unpack(data)
|
29
|
+
end
|
30
|
+
|
31
|
+
DEFAULT = self.new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative 'coder/json'
|
7
|
+
|
8
|
+
module Async
|
9
|
+
module Job
|
10
|
+
module Coder
|
11
|
+
DEFAULT = JSON::DEFAULT
|
12
|
+
|
13
|
+
# Type-cast for time values. See <https://bugs.ruby-lang.org/issues/20298> for background.
|
14
|
+
# @parameter value [Time || Integer || String || nil]
|
15
|
+
def self.Time(value)
|
16
|
+
case value
|
17
|
+
when ::Time
|
18
|
+
value
|
19
|
+
when Integer
|
20
|
+
::Time.at(value)
|
21
|
+
when String
|
22
|
+
::Time.new(value)
|
23
|
+
when nil
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
value.to_time
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/async/job/generic.rb
CHANGED
@@ -10,13 +10,13 @@ module Async
|
|
10
10
|
self.new(...).enqueue
|
11
11
|
end
|
12
12
|
|
13
|
-
def initialize(id,
|
13
|
+
def initialize(id, scheduled_at: nil)
|
14
14
|
@id = id
|
15
|
-
@
|
15
|
+
@scheduled_at = scheduled_at
|
16
16
|
end
|
17
17
|
|
18
18
|
attr :id
|
19
|
-
attr :
|
19
|
+
attr :scheduled_at
|
20
20
|
|
21
21
|
def serialize
|
22
22
|
raise NotImplementedError
|
data/lib/async/job/version.rb
CHANGED
data/lib/async/job.rb
CHANGED
data/readme.md
CHANGED
@@ -6,7 +6,11 @@ Provides an asynchronous job server.
|
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
|
-
|
9
|
+
Please see the [project documentation](https://socketry.github.io/async-job/) for more details.
|
10
|
+
|
11
|
+
- [Getting Started](https://socketry.github.io/async-job/guides/getting-started/index) - This guide gives you an overview of the `async-job` gem and explains the core concepts.
|
12
|
+
|
13
|
+
- [Redis Backend](https://socketry.github.io/async-job/guides/redis-backend/index) - This guide gives a brief overview of the implementation of the Redis backend.
|
10
14
|
|
11
15
|
## Contributing
|
12
16
|
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async-job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -37,7 +37,7 @@ cert_chain:
|
|
37
37
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
38
38
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
39
39
|
-----END CERTIFICATE-----
|
40
|
-
date: 2024-02-
|
40
|
+
date: 2024-02-26 00:00:00.000000000 Z
|
41
41
|
dependencies:
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: async
|
@@ -84,6 +84,11 @@ files:
|
|
84
84
|
- lib/async/job/backend/redis/ready_queue.rb
|
85
85
|
- lib/async/job/backend/redis/server.rb
|
86
86
|
- lib/async/job/buffer.rb
|
87
|
+
- lib/async/job/builder.rb
|
88
|
+
- lib/async/job/coder.rb
|
89
|
+
- lib/async/job/coder/json.rb
|
90
|
+
- lib/async/job/coder/marshal.rb
|
91
|
+
- lib/async/job/coder/message_pack.rb
|
87
92
|
- lib/async/job/generic.rb
|
88
93
|
- lib/async/job/version.rb
|
89
94
|
- license.md
|
@@ -92,7 +97,7 @@ homepage:
|
|
92
97
|
licenses:
|
93
98
|
- MIT
|
94
99
|
metadata:
|
95
|
-
documentation_uri: https://socketry.github.io/async-job
|
100
|
+
documentation_uri: https://socketry.github.io/async-job/
|
96
101
|
post_install_message:
|
97
102
|
rdoc_options: []
|
98
103
|
require_paths:
|
metadata.gz.sig
CHANGED
Binary file
|