async-job-processor-redis 0.2.0 → 0.3.1

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
  SHA256:
3
- metadata.gz: cf246106a0b45eade2e2316e3d198a80101b89e83619ae6ebf753a1a153a853c
4
- data.tar.gz: c298e2a87023a73a2014693d09685320ba20b875b1d872eea764ba3d97054cf8
3
+ metadata.gz: 19f21b96ed37f056471ebbb1935460d1be5a2714b4d1e50f9c82f8587587be8c
4
+ data.tar.gz: 8e1d7ba47c50236eeeb43e2b1ac38cdeba3cc1812ec028999aae7ccd87c91c66
5
5
  SHA512:
6
- metadata.gz: c343b68ed4fdefa6473737c65ea4e5d4303573eb60dca28a9f9d7ac36fcb5a35fdf7c37b91d74900aedb335d62701497398a6336073886305998ca3d6668f3c4
7
- data.tar.gz: 17c8c94cdd5a3c08bd09d10c77e129bd9bcffc475f444411afa79fcd8f94f3bce6e80e03c391cb4fb2aadf3c729916fb1a8c1ed9ba44db786bc86c0e0d573300
6
+ metadata.gz: a7600f75d5a7a9b5b0f0d93e8896889b80853a92b59cfc02413ea12c9d02034108c27961d4878dffe4dddcb42eafd9d25825b985842f03a6514e5bd90004b3da
7
+ data.tar.gz: 50fa8c45039c3505aea3f8e3dc6df6a1c442994d5ca4e7eb083d851af7d3bfe9e59a23b74a89e955360bdb6b8d951e14ba226364ebdd78a9f862b40e457a17c8
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,41 @@
1
+ # Getting Started
2
+
3
+ This guide gives you an overview of the `async-job-processor-redis` gem.
4
+
5
+ ## Installation
6
+
7
+ Add the gem to your project:
8
+
9
+ ``` shell
10
+ $ bundle add async-job-processor-redis
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ Here is a full example of the job queue:
16
+
17
+ ``` ruby
18
+ require "async"
19
+ require "async/job"
20
+ require "async/job/processor/redis"
21
+
22
+ Async do
23
+ buffer = Async::Job::Buffer.new
24
+
25
+ queue = Async::Job::Builder.build(buffer) do
26
+ dequeue Async::Job::Processor::Redis
27
+ end
28
+
29
+ # Run the server:
30
+ server = Async{queue.start}
31
+
32
+ # Enqueue a job:
33
+ queue.call({message: "Hello, World!"})
34
+
35
+ # Wait for the job to complete:
36
+ job = buffer.pop
37
+ pp job: job
38
+
39
+ server.stop
40
+ end
41
+ ```
@@ -0,0 +1,16 @@
1
+ # Automatically generated context index for Utopia::Project guides.
2
+ # Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3
+ ---
4
+ description: A asynchronous job queue for Ruby.
5
+ metadata:
6
+ documentation_uri: https://socketry.github.io/async-job-processor-redis/
7
+ source_code_uri: https://github.com/socketry/async-job-processor-redis
8
+ files:
9
+ - path: getting-started.md
10
+ title: Getting Started
11
+ description: This guide gives you an overview of the `async-job-processor-redis`
12
+ gem.
13
+ - path: redis-queue.md
14
+ title: Redis Queue
15
+ description: This guide gives a brief overview of the implementation of the Redis
16
+ queue.
@@ -0,0 +1,19 @@
1
+ # Redis Queue
2
+
3
+ This guide gives a brief overview of the implementation of the Redis queue.
4
+
5
+ ## Overview
6
+
7
+ The Redis queue plays a pivotal role in facilitating a sophisticated and reliable job queue architecture, designed to handle diverse processing needs with efficiency and resilience. The architecture is thoughtfully split into three distinct components, each serving a critical function in the lifecycle of a job: the ready queue, the delayed queue, and the processing queue.
8
+
9
+ ## Ready Queue
10
+
11
+ The ready queue is where jobs that are immediately available for processing are stored. When a job is submitted and is ready to be executed without any delay, it is placed into this queue. Worker processes constantly listen for new jobs on the ready queue, dequeuing and executing them as soon as they become available. This queue operates on a FIFO (First In, First Out) basis, ensuring that jobs are processed in the order they were received.
12
+
13
+ ## Delayed Queue
14
+
15
+ The delayed queue holds jobs that are not meant to be executed immediately but at a specified future time. This functionality is crucial for tasks that need to be executed at a later stage, such as scheduled notifications or time-dependent processes. Jobs in the delayed queue are sorted according to their execution time. When possible, they are moved to the ready queue to be executed by the next available worker. This transition is managed through Redis's sorted sets, allowing efficient retrieval and management of timed events.
16
+
17
+ ## Processing Queue
18
+
19
+ Once a job is dequeued from the ready queue, it enters the processing queue, signifying that it is currently being executed by a worker. The processing queue is crucial for tracking the progress of jobs and for ensuring that jobs can be retried or recovered in case of worker failure. Each worker emits a heartbeat, and if a worker fails to emit a heartbeat within a specified time, any jobs associated with that worker are automatically moved back to the ready queue for reprocessing.
@@ -1,7 +1,7 @@
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
@@ -36,6 +36,11 @@ module Async
36
36
  @move = @client.script(:load, MOVE)
37
37
  end
38
38
 
39
+ # @returns [Integer] The number of jobs currently in the delayed queue.
40
+ def size
41
+ @client.zcard(@key)
42
+ end
43
+
39
44
  # Start the background task that moves ready delayed jobs to the ready queue.
40
45
  # @parameter ready_list [ReadyList] The ready list to move jobs to.
41
46
  # @parameter resolution [Integer] The check interval in seconds.
@@ -1,7 +1,7 @@
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
@@ -73,6 +73,8 @@ module Async
73
73
  @requeue = @client.script(:load, REQUEUE)
74
74
  @retry = @client.script(:load, RETRY)
75
75
  @complete = @client.script(:load, COMPLETE)
76
+
77
+ @complete_count = 0
76
78
  end
77
79
 
78
80
  # @attribute [String] The base Redis key for this processing list.
@@ -81,6 +83,14 @@ module Async
81
83
  # @attribute [String] The Redis key for this worker's heartbeat.
82
84
  attr :heartbeat_key
83
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
+
84
94
  # Fetch the next job from the ready queue, moving it to this worker's pending list.
85
95
  # This is a blocking operation that waits until a job is available.
86
96
  # @returns [String, nil] The job ID, or nil if no job is available.
@@ -91,6 +101,8 @@ module Async
91
101
  # Mark a job as completed, removing it from the pending list and job store.
92
102
  # @parameter id [String] The job ID to complete.
93
103
  def complete(id)
104
+ @complete_count += 1
105
+
94
106
  @client.evalsha(@complete, 2, @pending_key, @job_store.key, id)
95
107
  end
96
108
 
@@ -1,7 +1,7 @@
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
@@ -28,6 +28,11 @@ module Async
28
28
  # @attribute [String] The Redis key for this ready list.
29
29
  attr :key
30
30
 
31
+ # @returns [Integer] The number of jobs currently in the ready list.
32
+ def size
33
+ @client.llen(@key)
34
+ end
35
+
31
36
  # Add a new job to the ready queue.
32
37
  # @parameter job [String] The serialized job data.
33
38
  # @parameter job_store [JobStore] The job store to save the job data.
@@ -85,6 +85,21 @@ module Async
85
85
  super
86
86
  end
87
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
+
88
103
  # Submit a new job for processing.
89
104
  # Jobs with a scheduled_at time are queued for delayed processing, while immediate jobs are added to the ready queue.
90
105
  # @parameter job [Hash] The job data to process.
@@ -121,6 +136,18 @@ module Async
121
136
  ensure
122
137
  @processing_list.retry(_id) if _id
123
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
124
151
  end
125
152
  end
126
153
  end
@@ -1,13 +1,13 @@
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
- VERSION = "0.2.0"
10
+ VERSION = "0.3.1"
11
11
  end
12
12
  end
13
13
  end
@@ -1,7 +1,7 @@
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
  require_relative "redis/server"
7
7
  require "async/redis/client"
data/readme.md CHANGED
@@ -16,6 +16,10 @@ Please see the [project documentation](https://socketry.github.io/async-job-proc
16
16
 
17
17
  Please see the [project releases](https://socketry.github.io/async-job-processor-redis/releases/index) for all releases.
18
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
+
19
23
  ### v0.2.0
20
24
 
21
25
  - Achieve 100% documentation coverage.
data/releases.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Releases
2
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
+
3
7
  ## v0.2.0
4
8
 
5
9
  - Achieve 100% documentation coverage.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-job-processor-redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -70,6 +70,9 @@ executables: []
70
70
  extensions: []
71
71
  extra_rdoc_files: []
72
72
  files:
73
+ - context/getting-started.md
74
+ - context/index.yaml
75
+ - context/redis-queue.md
73
76
  - lib/async/job/processor/redis.rb
74
77
  - lib/async/job/processor/redis/delayed_jobs.rb
75
78
  - lib/async/job/processor/redis/job_store.rb
@@ -99,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
102
  - !ruby/object:Gem::Version
100
103
  version: '0'
101
104
  requirements: []
102
- rubygems_version: 3.6.7
105
+ rubygems_version: 3.6.9
103
106
  specification_version: 4
104
107
  summary: A asynchronous job queue for Ruby.
105
108
  test_files: []
metadata.gz.sig CHANGED
Binary file