patient_http-solid_queue 1.0.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 +7 -0
- data/ARCHITECTURE.md +119 -0
- data/CHANGELOG.md +16 -0
- data/MIT-LICENSE +20 -0
- data/README.md +598 -0
- data/VERSION +1 -0
- data/db/migrate/20260216000000_create_solid_queue_async_http_tables.rb +27 -0
- data/lib/patient_http/solid_queue/callback_job.rb +73 -0
- data/lib/patient_http/solid_queue/configuration.rb +142 -0
- data/lib/patient_http/solid_queue/context.rb +36 -0
- data/lib/patient_http/solid_queue/engine.rb +14 -0
- data/lib/patient_http/solid_queue/gc_lock.rb +14 -0
- data/lib/patient_http/solid_queue/inflight_request.rb +14 -0
- data/lib/patient_http/solid_queue/lifecycle_hooks.rb +21 -0
- data/lib/patient_http/solid_queue/process_registration.rb +14 -0
- data/lib/patient_http/solid_queue/processor_observer.rb +38 -0
- data/lib/patient_http/solid_queue/record.rb +10 -0
- data/lib/patient_http/solid_queue/request_executor.rb +78 -0
- data/lib/patient_http/solid_queue/request_job.rb +46 -0
- data/lib/patient_http/solid_queue/task_handler.rb +53 -0
- data/lib/patient_http/solid_queue/task_monitor.rb +260 -0
- data/lib/patient_http/solid_queue/task_monitor_thread.rb +133 -0
- data/lib/patient_http/solid_queue.rb +284 -0
- data/lib/patient_http-solid_queue.rb +3 -0
- data/lib/tasks/patient_http_solid_queue.rake +21 -0
- data/patient_http-solid_queue.gemspec +44 -0
- metadata +110 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a3dff2ec8890085fac33d90459fae8756ba79fbf357579ac1cacb71a49f7e8fe
|
|
4
|
+
data.tar.gz: 8664f9bad61dc7db22fd7e3908ea705b094703863e9d13598f0f787e91e6d1f9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 106fc849d06ab190c8d691cf4f99066bd7fcc6c3cc0be20da1a95a43fbc73e4ff7cb1517a555bd008c4a55113394096985eb58835c04a579be098b371f2fdb14
|
|
7
|
+
data.tar.gz: 502cd86c858693f6c70edc88a97e2cae08e9a6f85712dc7f2fb06d5066124ae679351e7b685fa4fba4a4c0da97020f096c3673ca451aa768b329d2c7b01d61a3
|
data/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
PatientHttp::SolidQueue provides a Solid Queue integration layer for the [patient_http](https://github.com/bdurand/patient_http) gem, enabling long-running HTTP requests to be offloaded from worker execution to a dedicated async I/O processor. This integration uses Active Job for request enqueueing and callback invocation, while leveraging patient_http's Fiber-based concurrency to handle many concurrent HTTP requests without blocking worker threads.
|
|
6
|
+
|
|
7
|
+
## Key Design Principles
|
|
8
|
+
|
|
9
|
+
1. **Non-blocking workers**: Jobs enqueue HTTP requests and quickly return so worker capacity remains available
|
|
10
|
+
2. **Singleton processor per process**: One async I/O processor per worker process handles request concurrency
|
|
11
|
+
3. **Callback service pattern**: HTTP results are delivered to callback services via `on_complete` and `on_error`
|
|
12
|
+
4. **Lifecycle integration**: Processor lifecycle is tied to Solid Queue worker start/stop hooks
|
|
13
|
+
5. **Active Job-native task handling**: Request execution, callback jobs, and retries use Active Job semantics
|
|
14
|
+
|
|
15
|
+
## Core Components
|
|
16
|
+
|
|
17
|
+
### PatientHttp::Processor (from patient_http)
|
|
18
|
+
A dedicated processor thread that runs an async fiber reactor and manages concurrent HTTP execution.
|
|
19
|
+
|
|
20
|
+
### PatientHttp::SolidQueue::RequestJob
|
|
21
|
+
Active Job entry point for async requests. It:
|
|
22
|
+
- receives serialized request payloads
|
|
23
|
+
- decrypts and loads request data
|
|
24
|
+
- submits the request to `RequestExecutor`
|
|
25
|
+
|
|
26
|
+
### PatientHttp::SolidQueue::TaskHandler
|
|
27
|
+
Implements patient_http task handling for Active Job integration. It:
|
|
28
|
+
- enqueues `CallbackJob` on completion/error
|
|
29
|
+
- retries original jobs via `ActiveJob::Base.deserialize(...).enqueue`
|
|
30
|
+
- stores large payloads using external storage when configured
|
|
31
|
+
|
|
32
|
+
### PatientHttp::SolidQueue::CallbackJob
|
|
33
|
+
Active Job that resolves the callback class and invokes:
|
|
34
|
+
- `on_complete(response)` for successful requests
|
|
35
|
+
- `on_error(error)` for request errors
|
|
36
|
+
|
|
37
|
+
### PatientHttp::SolidQueue::LifecycleHooks
|
|
38
|
+
Registers hooks to automatically:
|
|
39
|
+
- start processor on `SolidQueue.on_worker_start`
|
|
40
|
+
- stop processor on `SolidQueue.on_worker_stop`
|
|
41
|
+
|
|
42
|
+
### PatientHttp::SolidQueue::ProcessorObserver
|
|
43
|
+
Observes processor task lifecycle and updates task monitor records.
|
|
44
|
+
|
|
45
|
+
### PatientHttp::SolidQueue::TaskMonitor
|
|
46
|
+
Tracks in-flight requests in database tables and performs orphan recovery. It:
|
|
47
|
+
- records request heartbeats
|
|
48
|
+
- tracks active processes
|
|
49
|
+
- re-enqueues orphaned requests from stale processes
|
|
50
|
+
|
|
51
|
+
### PatientHttp::SolidQueue::TaskMonitorThread
|
|
52
|
+
Background thread that periodically:
|
|
53
|
+
- updates in-flight heartbeats
|
|
54
|
+
- pings process registration
|
|
55
|
+
- runs orphan cleanup under a distributed DB lock
|
|
56
|
+
|
|
57
|
+
### Configuration
|
|
58
|
+
`PatientHttp::SolidQueue::Configuration` wraps patient_http configuration and adds Solid Queue-specific options such as:
|
|
59
|
+
- `queue_name`
|
|
60
|
+
- `heartbeat_interval`
|
|
61
|
+
- `orphan_threshold`
|
|
62
|
+
- `payload_store_threshold`
|
|
63
|
+
|
|
64
|
+
## Request Lifecycle
|
|
65
|
+
|
|
66
|
+
1. Application code calls `PatientHttp.get/post/put/patch/delete` (which delegates to the registered Solid Queue handler) or `PatientHttp::SolidQueue.execute` directly.
|
|
67
|
+
2. `RequestJob` is enqueued with serialized request data and callback metadata.
|
|
68
|
+
3. `RequestJob` decrypts/deserializes and calls `RequestExecutor.execute`.
|
|
69
|
+
4. `RequestExecutor` creates an async task and enqueues it on the processor.
|
|
70
|
+
5. Processor executes HTTP request asynchronously.
|
|
71
|
+
6. `TaskHandler` enqueues `CallbackJob` with serialized response/error.
|
|
72
|
+
7. `CallbackJob` invokes the callback service method.
|
|
73
|
+
|
|
74
|
+
## Process Model
|
|
75
|
+
|
|
76
|
+
Each worker process runs:
|
|
77
|
+
- worker threads for regular Active Job execution
|
|
78
|
+
- one async HTTP processor thread
|
|
79
|
+
- one task monitor thread for heartbeat and orphan recovery
|
|
80
|
+
|
|
81
|
+
## State Management
|
|
82
|
+
|
|
83
|
+
Processor lifecycle states are managed by patient_http and exposed via:
|
|
84
|
+
- `PatientHttp::SolidQueue.running?`
|
|
85
|
+
- `PatientHttp::SolidQueue.draining?`
|
|
86
|
+
- `PatientHttp::SolidQueue.stopping?`
|
|
87
|
+
- `PatientHttp::SolidQueue.stopped?`
|
|
88
|
+
|
|
89
|
+
On shutdown, the processor waits up to `shutdown_timeout` for in-flight requests before interrupting remaining tasks.
|
|
90
|
+
|
|
91
|
+
## Crash Recovery
|
|
92
|
+
|
|
93
|
+
Crash recovery is database-backed:
|
|
94
|
+
|
|
95
|
+
- In-flight requests are stored in `patient_http_solid_queue_inflight_requests`
|
|
96
|
+
- Active processes are tracked in `patient_http_solid_queue_processes`
|
|
97
|
+
- Distributed GC/orphan cleanup coordination uses `patient_http_solid_queue_gc_locks`
|
|
98
|
+
|
|
99
|
+
Recovery flow:
|
|
100
|
+
1. A request is registered with process ID + heartbeat timestamp
|
|
101
|
+
2. Heartbeats are updated while request remains in-flight
|
|
102
|
+
3. If a process stops heartbeating past `orphan_threshold`, another process can reclaim the request
|
|
103
|
+
4. The original Active Job is re-enqueued with executions reset
|
|
104
|
+
|
|
105
|
+
## Monitoring Hooks
|
|
106
|
+
|
|
107
|
+
Instrumentation hooks are available globally:
|
|
108
|
+
- `PatientHttp::SolidQueue.after_completion { |response| ... }`
|
|
109
|
+
- `PatientHttp::SolidQueue.after_error { |error| ... }`
|
|
110
|
+
|
|
111
|
+
These callbacks support metrics pipelines (StatsD, Prometheus adapters, etc.) and error reporting integrations.
|
|
112
|
+
|
|
113
|
+
## Testing Behavior
|
|
114
|
+
|
|
115
|
+
In test mode (`PatientHttp.testing?`), request execution runs synchronously to make specs deterministic while keeping the same public API.
|
|
116
|
+
|
|
117
|
+
## Further Reading
|
|
118
|
+
|
|
119
|
+
- [README](README.md)
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## 1.0.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Dedicated async HTTP processor integration for Solid Queue to avoid blocking worker threads during in-flight requests.
|
|
12
|
+
- `PatientHttp::SolidQueue` API with convenience methods for common HTTP verbs (`get`, `post`, `put`, `patch`, and `delete`).
|
|
13
|
+
- Callback-based completion and error handling via `on_complete` and `on_error`, executed through Active Job via `PatientHttp::SolidQueue::CallbackJob`.
|
|
14
|
+
- Support for callback context via `callback_args`, available from response and error objects.
|
|
15
|
+
- Automatic processor lifecycle integration with `SolidQueue.on_worker_start` and `SolidQueue.on_worker_stop` hooks.
|
|
16
|
+
- Database-backed in-flight request tracking with heartbeat updates, orphan detection, and automatic re-enqueue of interrupted requests.
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2026 Brian Durand
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|