async-job-processor-redis 0.1.0 → 0.3.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
- checksums.yaml.gz.sig +0 -0
- data/lib/async/job/processor/redis/delayed_jobs.rb +27 -1
- data/lib/async/job/processor/redis/job_store.rb +9 -0
- data/lib/async/job/processor/redis/processing_list.rb +61 -10
- data/lib/async/job/processor/redis/ready_list.rb +15 -0
- data/lib/async/job/processor/redis/server.rb +56 -11
- data/lib/async/job/processor/redis/version.rb +1 -1
- data/lib/async/job/processor/redis.rb +12 -2
- data/license.md +1 -1
- data/readme.md +18 -0
- data/releases.md +14 -0
- data.tar.gz.sig +0 -0
- metadata +5 -10
- 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: 5dd229182e417f662b414408d5b49a3c789791f63d7178d2d3acd4c30345b097
|
4
|
+
data.tar.gz: 2f28fd28ebbe51ea344810a039aa2985f68bf4b3934240dabb5d5949e9ffa06c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8818c38d052f06d17c8ada64d537ac996c3bb62bfbbb11c6965e7efa55f4c08b25f19ac9d50c44799b0dd3adcc7b8592ab573cf9793e0fab4500a09c3cfe560a
|
7
|
+
data.tar.gz: 9f8a5d182e4f9e7fff41bd01a328a6c50a1349a6dc9136e5fb1566d549e5558e624ccb9442d56e15a32779b5f6b0de4c67b2da619ebc6d8815f58e9183636cc0
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -7,6 +7,9 @@ module Async
|
|
7
7
|
module Job
|
8
8
|
module Processor
|
9
9
|
module Redis
|
10
|
+
# Manages delayed job scheduling using Redis sorted sets.
|
11
|
+
# Jobs are stored with their execution timestamps and automatically moved
|
12
|
+
# to the ready queue when their scheduled time arrives.
|
10
13
|
class DelayedJobs
|
11
14
|
ADD = <<~LUA
|
12
15
|
redis.call('HSET', KEYS[1], ARGV[1], ARGV[2])
|
@@ -22,6 +25,9 @@ module Async
|
|
22
25
|
return #jobs
|
23
26
|
LUA
|
24
27
|
|
28
|
+
# Initialize a new delayed jobs manager.
|
29
|
+
# @parameter client [Async::Redis::Client] The Redis client instance.
|
30
|
+
# @parameter key [String] The Redis key for the delayed jobs sorted set.
|
25
31
|
def initialize(client, key)
|
26
32
|
@client = client
|
27
33
|
@key = key
|
@@ -30,6 +36,16 @@ module Async
|
|
30
36
|
@move = @client.script(:load, MOVE)
|
31
37
|
end
|
32
38
|
|
39
|
+
# @returns [Integer] The number of jobs currently in the delayed queue.
|
40
|
+
def size
|
41
|
+
@client.zcard(@key)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Start the background task that moves ready delayed jobs to the ready queue.
|
45
|
+
# @parameter ready_list [ReadyList] The ready list to move jobs to.
|
46
|
+
# @parameter resolution [Integer] The check interval in seconds.
|
47
|
+
# @parameter parent [Async::Task] The parent task to run the background loop in.
|
48
|
+
# @returns [Async::Task] The background processing task.
|
33
49
|
def start(ready_list, resolution: 10, parent: Async::Task.current)
|
34
50
|
parent.async do
|
35
51
|
while true
|
@@ -44,8 +60,14 @@ module Async
|
|
44
60
|
end
|
45
61
|
end
|
46
62
|
|
63
|
+
# @attribute [String] The Redis key for this delayed jobs queue.
|
47
64
|
attr :key
|
48
65
|
|
66
|
+
# Add a job to the delayed queue with a specified execution time.
|
67
|
+
# @parameter job [String] The serialized job data.
|
68
|
+
# @parameter timestamp [Time] When the job should be executed.
|
69
|
+
# @parameter job_store [JobStore] The job store to save the job data.
|
70
|
+
# @returns [String] The unique job ID.
|
49
71
|
def add(job, timestamp, job_store)
|
50
72
|
id = SecureRandom.uuid
|
51
73
|
|
@@ -54,7 +76,11 @@ module Async
|
|
54
76
|
return id
|
55
77
|
end
|
56
78
|
|
57
|
-
|
79
|
+
# Move jobs that are ready to be processed from the delayed queue to the destination.
|
80
|
+
# @parameter destination [String] The Redis key of the destination queue.
|
81
|
+
# @parameter now [Integer] The current timestamp to check against.
|
82
|
+
# @returns [Integer] The number of jobs moved.
|
83
|
+
def move(destination:, now: Time.now.to_f)
|
58
84
|
@client.evalsha(@move, 2, @key, destination, now)
|
59
85
|
end
|
60
86
|
end
|
@@ -7,14 +7,23 @@ module Async
|
|
7
7
|
module Job
|
8
8
|
module Processor
|
9
9
|
module Redis
|
10
|
+
# Stores job data using Redis hashes.
|
11
|
+
# Provides persistent storage for job payloads indexed by job ID.
|
10
12
|
class JobStore
|
13
|
+
# Initialize a new job store.
|
14
|
+
# @parameter client [Async::Redis::Client] The Redis client instance.
|
15
|
+
# @parameter key [String] The Redis key for the job data hash.
|
11
16
|
def initialize(client, key)
|
12
17
|
@client = client
|
13
18
|
@key = key
|
14
19
|
end
|
15
20
|
|
21
|
+
# @attribute [String] The Redis key for this job store.
|
16
22
|
attr :key
|
17
23
|
|
24
|
+
# Retrieve job data by ID.
|
25
|
+
# @parameter id [String] The job ID to retrieve.
|
26
|
+
# @returns [String, nil] The serialized job data, or nil if not found.
|
18
27
|
def get(id)
|
19
28
|
@client.hget(@key, id)
|
20
29
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2024, by Samuel Williams.
|
4
|
+
# Copyright, 2024-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
module Async
|
7
7
|
module Job
|
8
8
|
module Processor
|
9
9
|
module Redis
|
10
|
+
# Manages jobs currently being processed and handles abandoned job recovery.
|
11
|
+
# Maintains heartbeats for active workers and automatically requeues
|
12
|
+
# jobs from workers that have stopped responding.
|
10
13
|
class ProcessingList
|
11
14
|
REQUEUE = <<~LUA
|
12
15
|
local cursor = "0"
|
@@ -50,6 +53,12 @@ module Async
|
|
50
53
|
redis.call('HDEL', KEYS[2], ARGV[1])
|
51
54
|
LUA
|
52
55
|
|
56
|
+
# Initialize a new processing list manager.
|
57
|
+
# @parameter client [Async::Redis::Client] The Redis client instance.
|
58
|
+
# @parameter key [String] The base Redis key for processing data.
|
59
|
+
# @parameter id [String] The unique server/worker ID.
|
60
|
+
# @parameter ready_list [ReadyList] The ready job queue.
|
61
|
+
# @parameter job_store [JobStore] The job data store.
|
53
62
|
def initialize(client, key, id, ready_list, job_store)
|
54
63
|
@client = client
|
55
64
|
@key = key
|
@@ -64,36 +73,78 @@ module Async
|
|
64
73
|
@requeue = @client.script(:load, REQUEUE)
|
65
74
|
@retry = @client.script(:load, RETRY)
|
66
75
|
@complete = @client.script(:load, COMPLETE)
|
76
|
+
|
77
|
+
@complete_count = 0
|
67
78
|
end
|
68
79
|
|
80
|
+
# @attribute [String] The base Redis key for this processing list.
|
69
81
|
attr :key
|
70
82
|
|
83
|
+
# @attribute [String] The Redis key for this worker's heartbeat.
|
84
|
+
attr :heartbeat_key
|
85
|
+
|
86
|
+
# @attribute [Integer] The total count of all jobs completed by this worker.
|
87
|
+
attr :complete_count
|
88
|
+
|
89
|
+
# @returns [Integer] The number of jobs currently being processed by this worker.
|
90
|
+
def size
|
91
|
+
@client.llen(@pending_key)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Fetch the next job from the ready queue, moving it to this worker's pending list.
|
95
|
+
# This is a blocking operation that waits until a job is available.
|
96
|
+
# @returns [String, nil] The job ID, or nil if no job is available.
|
71
97
|
def fetch
|
72
98
|
@client.brpoplpush(@ready_list.key, @pending_key, 0)
|
73
99
|
end
|
74
100
|
|
101
|
+
# Mark a job as completed, removing it from the pending list and job store.
|
102
|
+
# @parameter id [String] The job ID to complete.
|
75
103
|
def complete(id)
|
104
|
+
@complete_count += 1
|
105
|
+
|
76
106
|
@client.evalsha(@complete, 2, @pending_key, @job_store.key, id)
|
77
107
|
end
|
78
108
|
|
109
|
+
# Retry a failed job by moving it back to the ready queue.
|
110
|
+
# @parameter id [String] The job ID to retry.
|
79
111
|
def retry(id)
|
80
112
|
Console.warn(self, "Retrying job: #{id}")
|
81
113
|
@client.evalsha(@retry, 2, @pending_key, @ready_list.key, id)
|
82
114
|
end
|
83
115
|
|
116
|
+
# Update heartbeat and requeue any abandoned jobs from inactive workers.
|
117
|
+
# @parameter start_time [Float] The start time for calculating uptime.
|
118
|
+
# @parameter delay [Numeric] The heartbeat update interval.
|
119
|
+
# @parameter factor [Numeric] The heartbeat expiration factor.
|
120
|
+
# @returns [Integer] The number of jobs requeued from abandoned workers.
|
121
|
+
def requeue(start_time, delay, factor)
|
122
|
+
uptime = (Time.now.to_f - start_time).round(2)
|
123
|
+
expiry = (delay*factor).ceil
|
124
|
+
@client.set(@heartbeat_key, JSON.dump(uptime: uptime), seconds: expiry)
|
125
|
+
|
126
|
+
# Requeue any jobs that have been abandoned:
|
127
|
+
count = @client.evalsha(@requeue, 2, @key, @ready_list.key)
|
128
|
+
|
129
|
+
return count
|
130
|
+
end
|
131
|
+
|
132
|
+
# Start the background heartbeat and abandoned job recovery task.
|
133
|
+
# @parameter delay [Integer] The heartbeat update interval in seconds.
|
134
|
+
# @parameter factor [Integer] The heartbeat expiration factor.
|
135
|
+
# @parameter parent [Async::Task] The parent task to run the background loop in.
|
136
|
+
# @returns [Async::Task] The background processing task.
|
84
137
|
def start(delay: 5, factor: 2, parent: Async::Task.current)
|
85
|
-
heartbeat_key = "#{@key}:#{@id}"
|
86
138
|
start_time = Time.now.to_f
|
87
139
|
|
88
|
-
parent.async do
|
140
|
+
parent.async do |task|
|
89
141
|
while true
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Console.warn(self, "Requeued #{count} abandoned jobs.")
|
142
|
+
task.defer_stop do
|
143
|
+
count = self.requeue(start_time, delay, factor)
|
144
|
+
|
145
|
+
if count > 0
|
146
|
+
Console.warn(self, "Requeued #{count} abandoned jobs.")
|
147
|
+
end
|
97
148
|
end
|
98
149
|
|
99
150
|
sleep(delay)
|
@@ -7,12 +7,17 @@ module Async
|
|
7
7
|
module Job
|
8
8
|
module Processor
|
9
9
|
module Redis
|
10
|
+
# Manages the queue of jobs ready for immediate processing.
|
11
|
+
# Jobs are stored in Redis lists with FIFO (first-in, first-out) ordering.
|
10
12
|
class ReadyList
|
11
13
|
ADD = <<~LUA
|
12
14
|
redis.call('HSET', KEYS[1], ARGV[1], ARGV[2])
|
13
15
|
redis.call('LPUSH', KEYS[2], ARGV[1])
|
14
16
|
LUA
|
15
17
|
|
18
|
+
# Initialize a new ready list manager.
|
19
|
+
# @parameter client [Async::Redis::Client] The Redis client instance.
|
20
|
+
# @parameter key [String] The Redis key for the ready job list.
|
16
21
|
def initialize(client, key)
|
17
22
|
@client = client
|
18
23
|
@key = key
|
@@ -20,8 +25,18 @@ module Async
|
|
20
25
|
@add = @client.script(:load, ADD)
|
21
26
|
end
|
22
27
|
|
28
|
+
# @attribute [String] The Redis key for this ready list.
|
23
29
|
attr :key
|
24
30
|
|
31
|
+
# @returns [Integer] The number of jobs currently in the ready list.
|
32
|
+
def size
|
33
|
+
@client.llen(@key)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add a new job to the ready queue.
|
37
|
+
# @parameter job [String] The serialized job data.
|
38
|
+
# @parameter job_store [JobStore] The job store to save the job data.
|
39
|
+
# @returns [String] The unique job ID.
|
25
40
|
def add(job, job_store)
|
26
41
|
id = SecureRandom.uuid
|
27
42
|
|
@@ -1,25 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2024, by Samuel Williams.
|
4
|
+
# Copyright, 2024-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
6
|
+
require "async/idler"
|
7
|
+
require "async/job/coder"
|
8
|
+
require "async/job/processor/generic"
|
9
9
|
|
10
|
-
require
|
10
|
+
require "securerandom"
|
11
11
|
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
15
|
-
require_relative
|
12
|
+
require_relative "delayed_jobs"
|
13
|
+
require_relative "job_store"
|
14
|
+
require_relative "processing_list"
|
15
|
+
require_relative "ready_list"
|
16
16
|
|
17
17
|
module Async
|
18
18
|
module Job
|
19
19
|
module Processor
|
20
20
|
module Redis
|
21
|
+
# Redis-backed job processor server.
|
22
|
+
# Manages job queues using Redis for distributed job processing across multiple workers.
|
23
|
+
# Handles immediate jobs, delayed jobs, and job retry/recovery mechanisms.
|
21
24
|
class Server < Generic
|
22
|
-
|
25
|
+
# Initialize a new Redis job processor server.
|
26
|
+
# @parameter delegate [Object] The delegate object that will process jobs.
|
27
|
+
# @parameter client [Async::Redis::Client] The Redis client instance.
|
28
|
+
# @parameter prefix [String] The Redis key prefix for job data.
|
29
|
+
# @parameter coder [Async::Job::Coder] The job serialization codec.
|
30
|
+
# @parameter resolution [Integer] The resolution in seconds for delayed job processing.
|
31
|
+
# @parameter parent [Async::Task] The parent task for background processing.
|
32
|
+
def initialize(delegate, client, prefix: "async-job", coder: Coder::DEFAULT, resolution: 10, parent: nil)
|
23
33
|
super(delegate)
|
24
34
|
|
25
35
|
@id = SecureRandom.uuid
|
@@ -36,6 +46,8 @@ module Async
|
|
36
46
|
@parent = parent || Async::Idler.new
|
37
47
|
end
|
38
48
|
|
49
|
+
# Start the job processing loop immediately.
|
50
|
+
# @returns [Async::Task | false] The processing task or false if already started.
|
39
51
|
def start!
|
40
52
|
return false if @task
|
41
53
|
|
@@ -52,6 +64,8 @@ module Async
|
|
52
64
|
end
|
53
65
|
end
|
54
66
|
|
67
|
+
# Start the server and all background processing tasks.
|
68
|
+
# Initializes delayed job processing, abandoned job recovery, and the main processing loop.
|
55
69
|
def start
|
56
70
|
super
|
57
71
|
|
@@ -64,12 +78,31 @@ module Async
|
|
64
78
|
self.start!
|
65
79
|
end
|
66
80
|
|
81
|
+
# Stop the server and all background processing tasks.
|
67
82
|
def stop
|
68
83
|
@task&.stop
|
69
84
|
|
70
85
|
super
|
71
86
|
end
|
72
87
|
|
88
|
+
# Generates a human-readable string representing the current statistics.
|
89
|
+
#
|
90
|
+
# e.g. `R=3.42K D=1.23K P=7/2.34K``
|
91
|
+
#
|
92
|
+
# This can be interpreted as:
|
93
|
+
#
|
94
|
+
# - R: Number of jobs in the ready list
|
95
|
+
# - D: Number of jobs in the delayed queue
|
96
|
+
# - P: Number of jobs currently being processed / total number of completed jobs.
|
97
|
+
#
|
98
|
+
# @returns [String] A string representing the current statistics.
|
99
|
+
def status_string
|
100
|
+
"R=#{format_count(@ready_list.size)} D=#{format_count(@delayed_jobs.size)} P=#{format_count(@processing_list.size)}/#{format_count(@processing_list.complete_count)}"
|
101
|
+
end
|
102
|
+
|
103
|
+
# Submit a new job for processing.
|
104
|
+
# Jobs with a scheduled_at time are queued for delayed processing, while immediate jobs are added to the ready queue.
|
105
|
+
# @parameter job [Hash] The job data to process.
|
73
106
|
def call(job)
|
74
107
|
scheduled_at = Coder::Time(job["scheduled_at"])
|
75
108
|
|
@@ -97,12 +130,24 @@ module Async
|
|
97
130
|
@delegate.call(job)
|
98
131
|
@processing_list.complete(id)
|
99
132
|
rescue => error
|
100
|
-
Console
|
133
|
+
Console.error(self, "Job failed with error!", id: id, exception: error)
|
101
134
|
@processing_list.retry(id)
|
102
135
|
end
|
103
136
|
ensure
|
104
137
|
@processing_list.retry(_id) if _id
|
105
138
|
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def format_count(value)
|
143
|
+
if value > 1_000_000
|
144
|
+
"#{(value/1_000_000.0).round(2)}M"
|
145
|
+
elsif value > 1_000
|
146
|
+
"#{(value/1_000.0).round(2)}K"
|
147
|
+
else
|
148
|
+
value
|
149
|
+
end
|
150
|
+
end
|
106
151
|
end
|
107
152
|
end
|
108
153
|
end
|
@@ -3,13 +3,23 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
7
|
-
require
|
6
|
+
require_relative "redis/server"
|
7
|
+
require "async/redis/client"
|
8
8
|
|
9
|
+
# @namespace
|
9
10
|
module Async
|
11
|
+
# @namespace
|
10
12
|
module Job
|
13
|
+
# @namespace
|
11
14
|
module Processor
|
15
|
+
# Redis-based job processor implementation.
|
16
|
+
# Provides distributed job processing capabilities using Redis as the backend.
|
12
17
|
module Redis
|
18
|
+
# Create a new Redis job processor server.
|
19
|
+
# @parameter delegate [Object] The delegate object that will process jobs.
|
20
|
+
# @parameter endpoint [Async::Redis::Endpoint] The Redis endpoint to connect to.
|
21
|
+
# @parameter options [Hash] Additional options passed to the server.
|
22
|
+
# @returns [Server] A new Redis job processor server instance.
|
13
23
|
def self.new(delegate, endpoint: Async::Redis.local_endpoint, **options)
|
14
24
|
client = Async::Redis::Client.new(endpoint)
|
15
25
|
return Server.new(delegate, client, **options)
|
data/license.md
CHANGED
data/readme.md
CHANGED
@@ -12,8 +12,26 @@ Please see the [project documentation](https://socketry.github.io/async-job-proc
|
|
12
12
|
|
13
13
|
- [Redis Queue](https://socketry.github.io/async-job-processor-redis/guides/redis-queue/index) - This guide gives a brief overview of the implementation of the Redis queue.
|
14
14
|
|
15
|
+
## Releases
|
16
|
+
|
17
|
+
Please see the [project releases](https://socketry.github.io/async-job-processor-redis/releases/index) for all releases.
|
18
|
+
|
19
|
+
### v0.3.0
|
20
|
+
|
21
|
+
- Add `Async::Job::Processor::Redis::Server#status_string` method to return a string with the current job counts.
|
22
|
+
|
23
|
+
### v0.2.0
|
24
|
+
|
25
|
+
- Achieve 100% documentation coverage.
|
26
|
+
- Achieve 100% test coverage.
|
27
|
+
|
28
|
+
### v0.1.0
|
29
|
+
|
30
|
+
- Initial release of async-job-processor-redis, migrated from the async-job project.
|
31
|
+
|
15
32
|
## See Also
|
16
33
|
|
34
|
+
- [async-job](https://github.com/socketry/async-job) - Asynchronous job processing framework.
|
17
35
|
- [async-job-adapter-active\_job](https://github.com/socketry/async-job-adapter-active_job) - ActiveJob adapter for `async-job`.
|
18
36
|
|
19
37
|
## Contributing
|
data/releases.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Releases
|
2
|
+
|
3
|
+
## v0.3.0
|
4
|
+
|
5
|
+
- Add `Async::Job::Processor::Redis::Server#status_string` method to return a string with the current job counts.
|
6
|
+
|
7
|
+
## v0.2.0
|
8
|
+
|
9
|
+
- Achieve 100% documentation coverage.
|
10
|
+
- Achieve 100% test coverage.
|
11
|
+
|
12
|
+
## v0.1.0
|
13
|
+
|
14
|
+
- Initial release of async-job-processor-redis, migrated from the async-job project.
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async-job-processor-redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain:
|
11
10
|
- |
|
@@ -37,7 +36,7 @@ cert_chain:
|
|
37
36
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
38
37
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
39
38
|
-----END CERTIFICATE-----
|
40
|
-
date:
|
39
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
41
40
|
dependencies:
|
42
41
|
- !ruby/object:Gem::Dependency
|
43
42
|
name: async-job
|
@@ -67,8 +66,6 @@ dependencies:
|
|
67
66
|
- - ">="
|
68
67
|
- !ruby/object:Gem::Version
|
69
68
|
version: '0'
|
70
|
-
description:
|
71
|
-
email:
|
72
69
|
executables: []
|
73
70
|
extensions: []
|
74
71
|
extra_rdoc_files: []
|
@@ -82,13 +79,12 @@ files:
|
|
82
79
|
- lib/async/job/processor/redis/version.rb
|
83
80
|
- license.md
|
84
81
|
- readme.md
|
85
|
-
|
82
|
+
- releases.md
|
86
83
|
licenses:
|
87
84
|
- MIT
|
88
85
|
metadata:
|
89
86
|
documentation_uri: https://socketry.github.io/async-job-processor-redis/
|
90
87
|
source_code_uri: https://github.com/socketry/async-job-processor-redis
|
91
|
-
post_install_message:
|
92
88
|
rdoc_options: []
|
93
89
|
require_paths:
|
94
90
|
- lib
|
@@ -96,15 +92,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
92
|
requirements:
|
97
93
|
- - ">="
|
98
94
|
- !ruby/object:Gem::Version
|
99
|
-
version: '3.
|
95
|
+
version: '3.2'
|
100
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
97
|
requirements:
|
102
98
|
- - ">="
|
103
99
|
- !ruby/object:Gem::Version
|
104
100
|
version: '0'
|
105
101
|
requirements: []
|
106
|
-
rubygems_version: 3.
|
107
|
-
signing_key:
|
102
|
+
rubygems_version: 3.6.7
|
108
103
|
specification_version: 4
|
109
104
|
summary: A asynchronous job queue for Ruby.
|
110
105
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|