patient_http-sidekiq 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 +496 -0
- data/CHANGELOG.md +16 -0
- data/MIT-LICENSE +20 -0
- data/README.md +620 -0
- data/VERSION +1 -0
- data/lib/patient_http/sidekiq/callback_worker.rb +96 -0
- data/lib/patient_http/sidekiq/configuration.rb +175 -0
- data/lib/patient_http/sidekiq/context.rb +61 -0
- data/lib/patient_http/sidekiq/lifecycle_hooks.rb +42 -0
- data/lib/patient_http/sidekiq/processor_observer.rb +49 -0
- data/lib/patient_http/sidekiq/request_executor.rb +104 -0
- data/lib/patient_http/sidekiq/request_worker.rb +57 -0
- data/lib/patient_http/sidekiq/stats.rb +119 -0
- data/lib/patient_http/sidekiq/task_handler.rb +81 -0
- data/lib/patient_http/sidekiq/task_monitor.rb +542 -0
- data/lib/patient_http/sidekiq/task_monitor_thread.rb +154 -0
- data/lib/patient_http/sidekiq/web_ui/assets/patient-http/css/patient_http.css +249 -0
- data/lib/patient_http/sidekiq/web_ui/locales/ar.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/cs.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/da.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/de.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/el.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/en.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/es.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/fa.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/fr.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/gd.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/he.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/hi.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/it.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/ja.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/ko.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/lt.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/nb.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/nl.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/pl.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/pt-BR.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/pt.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/ru.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/sv.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/ta.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/tr.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/uk.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/ur.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/vi.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/zh-CN.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/locales/zh-TW.yml +26 -0
- data/lib/patient_http/sidekiq/web_ui/views/patient_http.html.erb +142 -0
- data/lib/patient_http/sidekiq/web_ui.rb +69 -0
- data/lib/patient_http/sidekiq.rb +328 -0
- data/lib/patient_http-sidekiq.rb +3 -0
- data/patient_http-sidekiq.gemspec +46 -0
- metadata +140 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sidekiq"
|
|
4
|
+
require "patient_http"
|
|
5
|
+
|
|
6
|
+
# This gem provides a mechanism to offload long-running HTTP requests from Sidekiq workers
|
|
7
|
+
# to a dedicated async I/O processor running in the same process, freeing worker threads
|
|
8
|
+
# immediately while HTTP requests are in flight.
|
|
9
|
+
#
|
|
10
|
+
# == Usage
|
|
11
|
+
#
|
|
12
|
+
# Make HTTP requests from anywhere in your code:
|
|
13
|
+
#
|
|
14
|
+
# request = PatientHttp::Request.new(:get, "https://api.example.com/users/123")
|
|
15
|
+
# PatientHttp::Sidekiq.execute(
|
|
16
|
+
# request,
|
|
17
|
+
# callback: MyCallback,
|
|
18
|
+
# callback_args: {user_id: 123}
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# Define a callback service class with +on_complete+ and +on_error+ methods:
|
|
22
|
+
#
|
|
23
|
+
# class MyCallback
|
|
24
|
+
# def on_complete(response)
|
|
25
|
+
# user_id = response.callback_args[:user_id]
|
|
26
|
+
# User.find(user_id).update!(data: response.json)
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# def on_error(error)
|
|
30
|
+
# Rails.logger.error("Request failed: #{error.message}")
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# == Key Features
|
|
35
|
+
#
|
|
36
|
+
# - Asynchronous HTTP processing using Ruby's Fiber scheduler
|
|
37
|
+
# - Non-blocking worker threads
|
|
38
|
+
# - Automatic connection pooling and HTTP/2 support
|
|
39
|
+
# - Comprehensive error handling and retry logic
|
|
40
|
+
# - Integration with Sidekiq's job lifecycle
|
|
41
|
+
# - Optional Web UI for monitoring
|
|
42
|
+
#
|
|
43
|
+
# = Singleton Processor Pattern
|
|
44
|
+
#
|
|
45
|
+
# This module maintains a single Processor instance at the module level (@processor).
|
|
46
|
+
# This is an intentional design decision driven by integration requirements with Sidekiq's
|
|
47
|
+
# lifecycle and practical operational considerations:
|
|
48
|
+
#
|
|
49
|
+
# == Rationale:
|
|
50
|
+
#
|
|
51
|
+
# 1. **Sidekiq Integration**: The processor lifecycle (start/quiet/stop) must align with
|
|
52
|
+
# Sidekiq's own lifecycle hooks. A single processor instance integrates cleanly with
|
|
53
|
+
# Sidekiq's startup and shutdown signals.
|
|
54
|
+
#
|
|
55
|
+
# 2. **Resource Management**: Running multiple async I/O reactors in a single process would
|
|
56
|
+
# create resource contention and complexity. A single reactor efficiently handles all
|
|
57
|
+
# HTTP requests using connection pooling and fiber-based concurrency.
|
|
58
|
+
#
|
|
59
|
+
# 3. **Configuration Simplicity**: A singleton processor means one configuration, one set
|
|
60
|
+
# of metrics, and one connection pool. Multiple processors would require complex
|
|
61
|
+
# coordination and resource allocation.
|
|
62
|
+
#
|
|
63
|
+
# 4. **Process Model**: Sidekiq's process model (multiple workers, single process) maps
|
|
64
|
+
# naturally to a single async processor per process. Each Sidekiq process gets one
|
|
65
|
+
# processor, workers within that process share it.
|
|
66
|
+
module PatientHttp
|
|
67
|
+
module Sidekiq
|
|
68
|
+
VERSION = File.read(File.expand_path("../../../VERSION", __FILE__)).strip
|
|
69
|
+
|
|
70
|
+
# Sidekiq-specific autoloads
|
|
71
|
+
autoload :CallbackWorker, File.join(__dir__, "sidekiq/callback_worker")
|
|
72
|
+
autoload :Configuration, File.join(__dir__, "sidekiq/configuration")
|
|
73
|
+
autoload :Context, File.join(__dir__, "sidekiq/context")
|
|
74
|
+
autoload :ProcessorObserver, File.join(__dir__, "sidekiq/processor_observer")
|
|
75
|
+
autoload :RequestExecutor, File.join(__dir__, "sidekiq/request_executor")
|
|
76
|
+
autoload :RequestWorker, File.join(__dir__, "sidekiq/request_worker")
|
|
77
|
+
autoload :LifecycleHooks, File.join(__dir__, "sidekiq/lifecycle_hooks")
|
|
78
|
+
autoload :TaskHandler, File.join(__dir__, "sidekiq/task_handler")
|
|
79
|
+
autoload :Stats, File.join(__dir__, "sidekiq/stats")
|
|
80
|
+
autoload :TaskMonitor, File.join(__dir__, "sidekiq/task_monitor")
|
|
81
|
+
autoload :TaskMonitorThread, File.join(__dir__, "sidekiq/task_monitor_thread")
|
|
82
|
+
autoload :WebUI, File.join(__dir__, "sidekiq/web_ui")
|
|
83
|
+
|
|
84
|
+
@processor = nil
|
|
85
|
+
@configuration = nil
|
|
86
|
+
@after_completion_callbacks = []
|
|
87
|
+
@after_error_callbacks = []
|
|
88
|
+
@external_storage = nil
|
|
89
|
+
@request_handler = nil
|
|
90
|
+
|
|
91
|
+
class << self
|
|
92
|
+
attr_writer :configuration
|
|
93
|
+
|
|
94
|
+
# Configure the gem with a block
|
|
95
|
+
# @yield [Configuration] the configuration object
|
|
96
|
+
# @return [Configuration]
|
|
97
|
+
def configure
|
|
98
|
+
configuration = Configuration.new
|
|
99
|
+
yield(configuration) if block_given?
|
|
100
|
+
@configuration = configuration
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Ensure configuration is initialized
|
|
104
|
+
# @return [Configuration]
|
|
105
|
+
def configuration
|
|
106
|
+
@configuration ||= Configuration.new
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Reset configuration to defaults (useful for testing)
|
|
110
|
+
# @return [Configuration]
|
|
111
|
+
def reset_configuration!
|
|
112
|
+
@configuration = nil
|
|
113
|
+
configuration
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Add a callback to be executed after a successful request completion.
|
|
117
|
+
#
|
|
118
|
+
# @yield [response] block to execute after an HTTP request completes
|
|
119
|
+
# @yieldparam response [PatientHttp::Response] the HTTP response
|
|
120
|
+
def after_completion(&block)
|
|
121
|
+
@after_completion_callbacks << block
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Add a callback to be executed after a request error.
|
|
125
|
+
#
|
|
126
|
+
# @yield [error] block to execute after an HTTP request errors
|
|
127
|
+
# @yieldparam error [PatientHttp::Error] information about the error that was raised
|
|
128
|
+
def after_error(&block)
|
|
129
|
+
@after_error_callbacks << block
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Add Sidekiq middleware for context handling. The middleware
|
|
133
|
+
# is already added during initialization. You can call this method again to
|
|
134
|
+
# append the middleware if needed to insert it after other middleware. If you need
|
|
135
|
+
# further control, you can manually add the `PatientHttp::Sidekiq::Context::Middleware`
|
|
136
|
+
# middleware yourself.
|
|
137
|
+
#
|
|
138
|
+
# @return [void]
|
|
139
|
+
def append_middleware
|
|
140
|
+
::Sidekiq.configure_server do |config|
|
|
141
|
+
config.server_middleware do |chain|
|
|
142
|
+
chain.add PatientHttp::Sidekiq::Context::Middleware
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Check if the processor is running.
|
|
148
|
+
#
|
|
149
|
+
# @return [Boolean]
|
|
150
|
+
def running?
|
|
151
|
+
!!@processor&.running?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Check if the processor is draining (not accepting new requests
|
|
155
|
+
# but still processing in-flight ones).
|
|
156
|
+
#
|
|
157
|
+
# @return [Boolean]
|
|
158
|
+
def draining?
|
|
159
|
+
!!@processor&.draining?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Check if the processor is in the process of stopping.
|
|
163
|
+
#
|
|
164
|
+
# @return [Boolean]
|
|
165
|
+
def stopping?
|
|
166
|
+
!!@processor&.stopping?
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Check if the processor is stopped or has not been started.
|
|
170
|
+
#
|
|
171
|
+
# @return [Boolean]
|
|
172
|
+
def stopped?
|
|
173
|
+
@processor.nil? || @processor.stopped?
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Get an ExternalStorage instance for storing and fetching payloads.
|
|
177
|
+
#
|
|
178
|
+
# @return [PatientHttp::ExternalStorage]
|
|
179
|
+
# @api private
|
|
180
|
+
def external_storage
|
|
181
|
+
@external_storage ||= PatientHttp::ExternalStorage.new(configuration)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Encrypt data using the configured encryptor.
|
|
185
|
+
#
|
|
186
|
+
# @param data [Hash] the data to encrypt
|
|
187
|
+
# @return [Hash] the encrypted data (or original if no encryption configured)
|
|
188
|
+
# @api private
|
|
189
|
+
def encrypt(data)
|
|
190
|
+
configuration.encryptor.encrypt(data)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Decrypt data using the configured encryptor.
|
|
194
|
+
#
|
|
195
|
+
# @param data [Hash] the data to decrypt
|
|
196
|
+
# @return [Hash] the decrypted data (or original if not encrypted)
|
|
197
|
+
# @api private
|
|
198
|
+
def decrypt(data)
|
|
199
|
+
configuration.encryptor.decrypt(data)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Execute an async HTTP request.
|
|
203
|
+
#
|
|
204
|
+
# @param request [PatientHttp::Request] the HTTP request to execute
|
|
205
|
+
# @param callback [Class, String] Callback service class with +on_complete+ and +on_error+
|
|
206
|
+
# instance methods, or its fully qualified class name.
|
|
207
|
+
# @param callback_args [#to_h, nil] Arguments to pass to callback via the
|
|
208
|
+
# PatientHttp::Response/PatientHttp::Error object. Must respond to +to_h+ and contain only JSON-native types
|
|
209
|
+
# (nil, true, false, String, Integer, Float, Array, Hash). All hash keys will be
|
|
210
|
+
# converted to strings for serialization. Access via +response.callback_args+ or
|
|
211
|
+
# +error.callback_args+ using symbol or string keys.
|
|
212
|
+
# @param raise_error_responses [Boolean] If true, treats non-2xx responses as errors
|
|
213
|
+
# and calls +on_error+ instead of +on_complete+. Defaults to false.
|
|
214
|
+
# @return [String] the request ID
|
|
215
|
+
def execute(request, callback:, callback_args: nil, raise_error_responses: false)
|
|
216
|
+
PatientHttp::CallbackValidator.validate!(callback)
|
|
217
|
+
callback_name = callback.is_a?(Class) ? callback.name : callback.to_s
|
|
218
|
+
callback_args = PatientHttp::CallbackValidator.validate_callback_args(callback_args)
|
|
219
|
+
request_id = SecureRandom.uuid
|
|
220
|
+
|
|
221
|
+
encrypted = encrypt(request.as_json)
|
|
222
|
+
|
|
223
|
+
data = if external_storage.enabled?
|
|
224
|
+
external_storage.store(encrypted, max_size: configuration.payload_store_threshold)
|
|
225
|
+
else
|
|
226
|
+
encrypted
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
RequestWorker.perform_async(data, callback_name, raise_error_responses, callback_args, request_id)
|
|
230
|
+
|
|
231
|
+
request_id
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Start the processor
|
|
235
|
+
#
|
|
236
|
+
# @return [void]
|
|
237
|
+
def start
|
|
238
|
+
return if running?
|
|
239
|
+
|
|
240
|
+
@processor = PatientHttp::Processor.new(configuration)
|
|
241
|
+
@processor.observe(ProcessorObserver.new(@processor))
|
|
242
|
+
configuration.observers.each do |observer|
|
|
243
|
+
@processor.observe(observer)
|
|
244
|
+
end
|
|
245
|
+
@processor.start
|
|
246
|
+
|
|
247
|
+
@request_handler ||= lambda do |request:, callback:, raise_error_responses:, callback_args:|
|
|
248
|
+
execute(
|
|
249
|
+
request,
|
|
250
|
+
callback: callback,
|
|
251
|
+
raise_error_responses: raise_error_responses,
|
|
252
|
+
callback_args: callback_args
|
|
253
|
+
)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
PatientHttp.register_handler(@request_handler)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Signal the processor to drain (stop accepting new requests)
|
|
260
|
+
#
|
|
261
|
+
# @return [void]
|
|
262
|
+
def quiet
|
|
263
|
+
return unless running?
|
|
264
|
+
|
|
265
|
+
@processor.drain
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Stop the processor gracefully
|
|
269
|
+
#
|
|
270
|
+
# @param timeout [Float, nil] maximum time to wait for in-flight requests to complete
|
|
271
|
+
# @return [void]
|
|
272
|
+
def stop(timeout: nil)
|
|
273
|
+
if @request_handler
|
|
274
|
+
PatientHttp.unregister_handler(@request_handler)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
return unless @processor
|
|
278
|
+
|
|
279
|
+
@processor.stop(timeout: timeout)
|
|
280
|
+
@processor = nil
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Reset all state (useful for testing)
|
|
284
|
+
#
|
|
285
|
+
# @return [void]
|
|
286
|
+
# @api private
|
|
287
|
+
def reset!
|
|
288
|
+
@processor&.stop(timeout: 0)
|
|
289
|
+
@processor = nil
|
|
290
|
+
@configuration = nil
|
|
291
|
+
@external_storage = nil
|
|
292
|
+
@after_completion_callbacks = []
|
|
293
|
+
@after_error_callbacks = []
|
|
294
|
+
PatientHttp.unregister_handler(@request_handler) if @request_handler
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Invoke the registered completion callbacks
|
|
298
|
+
#
|
|
299
|
+
# @param response [PatientHttp::Response] the HTTP response
|
|
300
|
+
# @return [void]
|
|
301
|
+
# @api private
|
|
302
|
+
def invoke_completion_callbacks(response)
|
|
303
|
+
@after_completion_callbacks.each do |callback|
|
|
304
|
+
callback.call(response)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Invoke the registered error callbacks
|
|
309
|
+
#
|
|
310
|
+
# @param error [PatientHttp::Error] information about the error that was raised
|
|
311
|
+
# @return [void]
|
|
312
|
+
# @api private
|
|
313
|
+
def invoke_error_callbacks(error)
|
|
314
|
+
@after_error_callbacks.each do |callback|
|
|
315
|
+
callback.call(error)
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Returns the processor instance (internal accessor)
|
|
320
|
+
#
|
|
321
|
+
# @return [PatientHttp::Processor, nil]
|
|
322
|
+
# @api private
|
|
323
|
+
attr_accessor :processor
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
PatientHttp::Sidekiq::LifecycleHooks.register
|
|
328
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Gem::Specification.new do |spec|
|
|
2
|
+
spec.name = "patient_http-sidekiq"
|
|
3
|
+
spec.version = File.read(File.expand_path("../VERSION", __FILE__)).strip
|
|
4
|
+
spec.authors = ["Brian Durand"]
|
|
5
|
+
spec.email = ["bbdurand@gmail.com"]
|
|
6
|
+
|
|
7
|
+
spec.summary = "Offload long-running HTTP requests from Sidekiq workers to a dedicated async I/O processor"
|
|
8
|
+
spec.description = "This gem provides a mechanism to offload long-running HTTP requests from Sidekiq workers to a dedicated async I/O processor running in the same process, freeing the worker thread immediately while the HTTP request is in flight."
|
|
9
|
+
|
|
10
|
+
spec.homepage = "https://github.com/bdurand/patient_http-sidekiq"
|
|
11
|
+
spec.license = "MIT"
|
|
12
|
+
|
|
13
|
+
spec.metadata = {
|
|
14
|
+
"homepage_uri" => spec.homepage,
|
|
15
|
+
"source_code_uri" => spec.homepage,
|
|
16
|
+
"changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
21
|
+
ignore_files = %w[
|
|
22
|
+
.
|
|
23
|
+
AGENTS.md
|
|
24
|
+
Appraisals
|
|
25
|
+
Gemfile
|
|
26
|
+
Gemfile.lock
|
|
27
|
+
Rakefile
|
|
28
|
+
docker-compose.yml
|
|
29
|
+
bin/
|
|
30
|
+
gemfiles/
|
|
31
|
+
spec/
|
|
32
|
+
test_app/
|
|
33
|
+
]
|
|
34
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
|
35
|
+
`git ls-files -z`.split("\x0").reject { |f| ignore_files.any? { |path| f.start_with?(path) } }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
spec.require_paths = ["lib"]
|
|
39
|
+
|
|
40
|
+
spec.required_ruby_version = ">= 3.2"
|
|
41
|
+
|
|
42
|
+
spec.add_dependency "sidekiq", ">= 7.0"
|
|
43
|
+
spec.add_dependency "patient_http"
|
|
44
|
+
|
|
45
|
+
spec.add_development_dependency "bundler"
|
|
46
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: patient_http-sidekiq
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Brian Durand
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: sidekiq
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: patient_http
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: bundler
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
description: This gem provides a mechanism to offload long-running HTTP requests from
|
|
55
|
+
Sidekiq workers to a dedicated async I/O processor running in the same process,
|
|
56
|
+
freeing the worker thread immediately while the HTTP request is in flight.
|
|
57
|
+
email:
|
|
58
|
+
- bbdurand@gmail.com
|
|
59
|
+
executables: []
|
|
60
|
+
extensions: []
|
|
61
|
+
extra_rdoc_files: []
|
|
62
|
+
files:
|
|
63
|
+
- ARCHITECTURE.md
|
|
64
|
+
- CHANGELOG.md
|
|
65
|
+
- MIT-LICENSE
|
|
66
|
+
- README.md
|
|
67
|
+
- VERSION
|
|
68
|
+
- lib/patient_http-sidekiq.rb
|
|
69
|
+
- lib/patient_http/sidekiq.rb
|
|
70
|
+
- lib/patient_http/sidekiq/callback_worker.rb
|
|
71
|
+
- lib/patient_http/sidekiq/configuration.rb
|
|
72
|
+
- lib/patient_http/sidekiq/context.rb
|
|
73
|
+
- lib/patient_http/sidekiq/lifecycle_hooks.rb
|
|
74
|
+
- lib/patient_http/sidekiq/processor_observer.rb
|
|
75
|
+
- lib/patient_http/sidekiq/request_executor.rb
|
|
76
|
+
- lib/patient_http/sidekiq/request_worker.rb
|
|
77
|
+
- lib/patient_http/sidekiq/stats.rb
|
|
78
|
+
- lib/patient_http/sidekiq/task_handler.rb
|
|
79
|
+
- lib/patient_http/sidekiq/task_monitor.rb
|
|
80
|
+
- lib/patient_http/sidekiq/task_monitor_thread.rb
|
|
81
|
+
- lib/patient_http/sidekiq/web_ui.rb
|
|
82
|
+
- lib/patient_http/sidekiq/web_ui/assets/patient-http/css/patient_http.css
|
|
83
|
+
- lib/patient_http/sidekiq/web_ui/locales/ar.yml
|
|
84
|
+
- lib/patient_http/sidekiq/web_ui/locales/cs.yml
|
|
85
|
+
- lib/patient_http/sidekiq/web_ui/locales/da.yml
|
|
86
|
+
- lib/patient_http/sidekiq/web_ui/locales/de.yml
|
|
87
|
+
- lib/patient_http/sidekiq/web_ui/locales/el.yml
|
|
88
|
+
- lib/patient_http/sidekiq/web_ui/locales/en.yml
|
|
89
|
+
- lib/patient_http/sidekiq/web_ui/locales/es.yml
|
|
90
|
+
- lib/patient_http/sidekiq/web_ui/locales/fa.yml
|
|
91
|
+
- lib/patient_http/sidekiq/web_ui/locales/fr.yml
|
|
92
|
+
- lib/patient_http/sidekiq/web_ui/locales/gd.yml
|
|
93
|
+
- lib/patient_http/sidekiq/web_ui/locales/he.yml
|
|
94
|
+
- lib/patient_http/sidekiq/web_ui/locales/hi.yml
|
|
95
|
+
- lib/patient_http/sidekiq/web_ui/locales/it.yml
|
|
96
|
+
- lib/patient_http/sidekiq/web_ui/locales/ja.yml
|
|
97
|
+
- lib/patient_http/sidekiq/web_ui/locales/ko.yml
|
|
98
|
+
- lib/patient_http/sidekiq/web_ui/locales/lt.yml
|
|
99
|
+
- lib/patient_http/sidekiq/web_ui/locales/nb.yml
|
|
100
|
+
- lib/patient_http/sidekiq/web_ui/locales/nl.yml
|
|
101
|
+
- lib/patient_http/sidekiq/web_ui/locales/pl.yml
|
|
102
|
+
- lib/patient_http/sidekiq/web_ui/locales/pt-BR.yml
|
|
103
|
+
- lib/patient_http/sidekiq/web_ui/locales/pt.yml
|
|
104
|
+
- lib/patient_http/sidekiq/web_ui/locales/ru.yml
|
|
105
|
+
- lib/patient_http/sidekiq/web_ui/locales/sv.yml
|
|
106
|
+
- lib/patient_http/sidekiq/web_ui/locales/ta.yml
|
|
107
|
+
- lib/patient_http/sidekiq/web_ui/locales/tr.yml
|
|
108
|
+
- lib/patient_http/sidekiq/web_ui/locales/uk.yml
|
|
109
|
+
- lib/patient_http/sidekiq/web_ui/locales/ur.yml
|
|
110
|
+
- lib/patient_http/sidekiq/web_ui/locales/vi.yml
|
|
111
|
+
- lib/patient_http/sidekiq/web_ui/locales/zh-CN.yml
|
|
112
|
+
- lib/patient_http/sidekiq/web_ui/locales/zh-TW.yml
|
|
113
|
+
- lib/patient_http/sidekiq/web_ui/views/patient_http.html.erb
|
|
114
|
+
- patient_http-sidekiq.gemspec
|
|
115
|
+
homepage: https://github.com/bdurand/patient_http-sidekiq
|
|
116
|
+
licenses:
|
|
117
|
+
- MIT
|
|
118
|
+
metadata:
|
|
119
|
+
homepage_uri: https://github.com/bdurand/patient_http-sidekiq
|
|
120
|
+
source_code_uri: https://github.com/bdurand/patient_http-sidekiq
|
|
121
|
+
changelog_uri: https://github.com/bdurand/patient_http-sidekiq/blob/main/CHANGELOG.md
|
|
122
|
+
rdoc_options: []
|
|
123
|
+
require_paths:
|
|
124
|
+
- lib
|
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
|
+
requirements:
|
|
127
|
+
- - ">="
|
|
128
|
+
- !ruby/object:Gem::Version
|
|
129
|
+
version: '3.2'
|
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - ">="
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: '0'
|
|
135
|
+
requirements: []
|
|
136
|
+
rubygems_version: 4.0.3
|
|
137
|
+
specification_version: 4
|
|
138
|
+
summary: Offload long-running HTTP requests from Sidekiq workers to a dedicated async
|
|
139
|
+
I/O processor
|
|
140
|
+
test_files: []
|