gouda 0.1.16 → 0.2.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
- data/Appraisals +2 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +1 -0
- data/README.md +117 -3
- data/examples/async_job_example.rb +116 -0
- data/examples/fiber_configuration.rb +45 -0
- data/examples/fiber_demo.rb +118 -0
- data/gemfiles/rails_7.gemfile +1 -0
- data/gemfiles/rails_7.gemfile.lock +21 -1
- data/gemfiles/rails_8.gemfile +1 -0
- data/gemfiles/rails_8.gemfile.lock +21 -1
- data/gouda.gemspec +1 -0
- data/lib/gouda/railtie.rb +2 -0
- data/lib/gouda/version.rb +1 -1
- data/lib/gouda/worker.rb +150 -59
- data/lib/gouda/workload.rb +17 -0
- data/lib/gouda.rb +74 -3
- data/test/gouda/worker_test.rb +324 -0
- data/test/gouda/workload_test.rb +61 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a5b6d65b9cbfbe699e5bbfe1dd2854eeebc74d711d22243ec9c1c647d6986f7
|
4
|
+
data.tar.gz: d2642c37fe82af94a577d6b0806e9178842b8b0a53b64fe2eefeb1362f748a06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d276d47fd5dced75511522900f1328ee1cb7cb076f833e6dc0d8eb597cafdc1933986ebb17a2ec37390d0d3e74b2c183fdabba204cc0e41c2010ccb2adefcdb
|
7
|
+
data.tar.gz: 644d5eba7e6fca4fbf2f21d805d98985be8e72fcfa5e06dc8402a26fefb292c2a204134071e0e31ca345ab74863ea6191aa934479e6eb1b865a31e4bea2ff817
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -72,7 +72,20 @@ to **prevent concurrent executions** but not to **limit the load on the system**
|
|
72
72
|
|
73
73
|
## Key concepts in Gouda: `executing_on`
|
74
74
|
|
75
|
-
A `Workload` is executing on a particular `executing_on` entity - usually a worker thread. That entity gets a pseudorandom ID
|
75
|
+
A `Workload` is executing on a particular `executing_on` entity - usually a worker thread or fiber. That entity gets a pseudorandom ID. The `executing_on` value can be used to see, for example, whether a particular worker thread has hung. If multiple jobs have a far-behind `updated_at` and are all `executing`, this likely means that the worker executing them has died or has hung.
|
76
|
+
|
77
|
+
The `executing_on` field now clearly indicates the execution context:
|
78
|
+
- Thread-based execution: `hostname-pid-uuid-thread-abc123`
|
79
|
+
- Hybrid execution (threads + fibers): `hostname-pid-uuid-thread-abc123-fiber-def456`
|
80
|
+
|
81
|
+
You can programmatically check the execution context:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
workload = Gouda::Workload.last
|
85
|
+
workload.executed_on_thread? # => true/false
|
86
|
+
workload.uses_async_execution? # => true/false
|
87
|
+
workload.execution_context # => :thread, :fiber, or :unknown
|
88
|
+
```
|
76
89
|
|
77
90
|
## Usage tips: bulkify your enqueues
|
78
91
|
|
@@ -103,7 +116,108 @@ User.transaction do
|
|
103
116
|
end
|
104
117
|
```
|
105
118
|
|
106
|
-
##
|
119
|
+
## Hybrid Execution: Threads + Fibers
|
120
|
+
|
121
|
+
Gouda supports two execution modes: traditional thread-based execution and hybrid execution that combines multiple threads with multiple fibers per thread. The hybrid mode provides non-blocking IO capabilities while still utilizing multiple CPU cores.
|
122
|
+
|
123
|
+
### Execution Modes
|
124
|
+
|
125
|
+
**Thread-based execution (default):**
|
126
|
+
- Multiple worker threads
|
127
|
+
- One job per thread at a time
|
128
|
+
- Simple and reliable
|
129
|
+
- Good for CPU-bound work
|
130
|
+
|
131
|
+
**Hybrid execution (threads + fibers):**
|
132
|
+
- Multiple worker threads, each containing multiple fibers
|
133
|
+
- Much higher concurrency (threads × fibers per thread)
|
134
|
+
- Non-blocking IO within each thread
|
135
|
+
- Best of both worlds: CPU parallelism + IO concurrency
|
136
|
+
|
137
|
+
### Requirements
|
138
|
+
|
139
|
+
- Ruby 3.1+ with Fiber.scheduler support
|
140
|
+
- `async` gem dependency (~> 2.25, automatically included)
|
141
|
+
- **Rails isolation level set to `:fiber`** (critical for hybrid mode)
|
142
|
+
- Async-compatible gems for full benefit
|
143
|
+
|
144
|
+
### Critical Configuration for Hybrid Mode
|
145
|
+
|
146
|
+
**⚠️ IMPORTANT**: When using hybrid execution **with PostgreSQL**, you **must** configure Rails to use fiber-based isolation:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
# config/application.rb
|
150
|
+
class Application < Rails::Application
|
151
|
+
# This is REQUIRED for Gouda hybrid mode with PostgreSQL
|
152
|
+
config.active_support.isolation_level = :fiber
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
**Why this matters for PostgreSQL:**
|
157
|
+
- Prevents segmentation faults with Ruby 3.4+ and PostgreSQL adapter
|
158
|
+
- Ensures ActiveRecord connection pools work correctly with fibers and PostgreSQL connections
|
159
|
+
- Required for proper fiber-based concurrency with PostgreSQL's connection handling
|
160
|
+
|
161
|
+
**Note**: This configuration is specifically required when using PostgreSQL. Other database adapters may not have the same requirement, but setting it to `:fiber` is generally safe and recommended when using Gouda's hybrid mode.
|
107
162
|
|
108
|
-
|
163
|
+
Gouda will automatically detect if this setting is missing when using PostgreSQL and warn you during startup.
|
164
|
+
|
165
|
+
### Configuration
|
166
|
+
|
167
|
+
To enable hybrid execution (threads + fibers):
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
Gouda.configure do |config|
|
171
|
+
# Enable hybrid scheduler (threads + fibers)
|
172
|
+
config.use_fiber_scheduler = true
|
173
|
+
|
174
|
+
# Number of worker threads (should match your CPU cores)
|
175
|
+
config.worker_thread_count = 4
|
176
|
+
|
177
|
+
# Number of fibers per thread (can be much higher)
|
178
|
+
config.fibers_per_thread = 10 # This means 10 fibers PER thread
|
179
|
+
|
180
|
+
# Total concurrency = worker_thread_count × fibers_per_thread
|
181
|
+
# In this example: 4 threads × 10 fibers = 40 concurrent jobs
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
185
|
+
**Traditional thread-based execution (default):**
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
Gouda.configure do |config|
|
189
|
+
# Thread-based execution (default)
|
190
|
+
config.use_fiber_scheduler = false
|
191
|
+
|
192
|
+
# Number of worker threads
|
193
|
+
config.worker_thread_count = 4 # Total concurrency = 4
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
### Benefits
|
198
|
+
|
199
|
+
- **Non-blocking IO**: Database queries, HTTP requests, and file operations don't block other jobs
|
200
|
+
- **CPU parallelism**: Multiple threads utilize multiple CPU cores
|
201
|
+
- **Higher concurrency**: Can handle many more concurrent jobs with less memory overhead than pure threading
|
202
|
+
- **Better resource utilization**: Cooperative scheduling reduces context switching overhead
|
203
|
+
- **Backward compatibility**: Thread-based mode remains the default and continues to work
|
204
|
+
|
205
|
+
### When to use hybrid vs thread execution
|
206
|
+
|
207
|
+
**Use hybrid execution (threads + fibers) for:**
|
208
|
+
- IO-bound jobs (HTTP requests, database queries, file processing)
|
209
|
+
- High-concurrency scenarios
|
210
|
+
- Jobs that spend time waiting for external resources
|
211
|
+
- Mixed workloads with both CPU and IO requirements
|
212
|
+
|
213
|
+
**Use thread-based execution for:**
|
214
|
+
- CPU-intensive jobs
|
215
|
+
- Jobs that use gems without async support
|
216
|
+
- Simpler deployment scenarios
|
217
|
+
- When you want predictable, simple execution
|
218
|
+
|
219
|
+
You can even run both modes simultaneously with different queue constraints to optimize for different job types.
|
220
|
+
|
221
|
+
## Web UI
|
109
222
|
|
223
|
+
At the moment the Gouda UI is proprietary, so this gem only provides a "headless" implementation. We expect this to change in the future.
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# Example of an async-compatible job for use with Gouda's fiber scheduler
|
2
|
+
|
3
|
+
require "async"
|
4
|
+
require "async/http"
|
5
|
+
|
6
|
+
class AsyncHttpJob < ApplicationJob
|
7
|
+
queue_as :default
|
8
|
+
|
9
|
+
def perform(url)
|
10
|
+
# This job will work with both thread-based and fiber-based workers
|
11
|
+
# When using fiber scheduler, HTTP requests will be non-blocking
|
12
|
+
|
13
|
+
# Use async-compatible HTTP client
|
14
|
+
response = fetch_url_async(url)
|
15
|
+
|
16
|
+
# Process the response
|
17
|
+
process_response(response)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def fetch_url_async(url)
|
23
|
+
# When running in Gouda's hybrid mode: concurrent with other async operations in same reactor
|
24
|
+
# When running in thread-only mode: blocks the thread (creates own reactor)
|
25
|
+
Async do |task|
|
26
|
+
internet = Async::HTTP::Internet.new
|
27
|
+
response = internet.get(url)
|
28
|
+
response.read
|
29
|
+
ensure
|
30
|
+
internet&.close
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_response(data)
|
35
|
+
# Process the fetched data
|
36
|
+
Rails.logger.info "Fetched #{data.size} bytes"
|
37
|
+
|
38
|
+
# Example: Save to database (this will also be async with fiber scheduler)
|
39
|
+
MyModel.create!(data: data, processed_at: Time.current)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Example of a job that benefits from fiber concurrency
|
44
|
+
class BulkDataProcessorJob < ApplicationJob
|
45
|
+
queue_as :bulk_processing
|
46
|
+
|
47
|
+
def perform(record_ids)
|
48
|
+
# Process multiple records concurrently using fibers
|
49
|
+
results = []
|
50
|
+
|
51
|
+
# When using fiber scheduler, these database operations can be concurrent
|
52
|
+
record_ids.each do |id|
|
53
|
+
# This will be non-blocking with fiber scheduler
|
54
|
+
record = MyModel.find(id)
|
55
|
+
result = process_record(record)
|
56
|
+
results << result
|
57
|
+
end
|
58
|
+
|
59
|
+
# Aggregate results
|
60
|
+
aggregate_results(results)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def process_record(record)
|
66
|
+
# Simulate some async work (API call, file processing, etc.)
|
67
|
+
# With fiber scheduler, multiple records can be processed concurrently
|
68
|
+
{
|
69
|
+
id: record.id,
|
70
|
+
processed_at: Time.current,
|
71
|
+
result: expensive_operation(record)
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def expensive_operation(record)
|
76
|
+
# This could be an HTTP API call, file processing, etc.
|
77
|
+
# that benefits from non-blocking IO
|
78
|
+
sleep(0.1) # Simulated IO wait
|
79
|
+
"processed_#{record.id}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def aggregate_results(results)
|
83
|
+
# Save aggregated results
|
84
|
+
Rails.logger.info "Processed #{results.size} records"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Example of configuring different queue constraints for fiber workers
|
89
|
+
class FiberWorkerInitializer
|
90
|
+
def self.start_workers
|
91
|
+
if Rails.env.production?
|
92
|
+
# Start multiple workers with different queue constraints
|
93
|
+
|
94
|
+
# High-throughput fiber worker for IO-bound jobs
|
95
|
+
Thread.new do
|
96
|
+
Gouda.configure do |config|
|
97
|
+
config.use_fiber_scheduler = true
|
98
|
+
config.fibers_per_thread = 20
|
99
|
+
end
|
100
|
+
|
101
|
+
Gouda.start
|
102
|
+
end
|
103
|
+
|
104
|
+
# Traditional thread worker for CPU-bound jobs
|
105
|
+
Thread.new do
|
106
|
+
Gouda.configure do |config|
|
107
|
+
config.use_fiber_scheduler = false
|
108
|
+
config.worker_thread_count = 4
|
109
|
+
end
|
110
|
+
|
111
|
+
ENV["GOUDA_QUEUES"] = "cpu_intensive"
|
112
|
+
Gouda.start
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Example configuration for Gouda fiber-based job processing
|
2
|
+
# This shows how to properly configure Rails and Gouda for optimal fiber performance
|
3
|
+
|
4
|
+
# CRITICAL: Set Rails isolation level to :fiber (config/application.rb)
|
5
|
+
# This MUST be set when using PostgreSQL to prevent segfaults and ensure proper fiber concurrency
|
6
|
+
#
|
7
|
+
# # config/application.rb
|
8
|
+
# class Application < Rails::Application
|
9
|
+
# # Required for fiber mode with PostgreSQL - prevents segfaults and connection issues
|
10
|
+
# config.active_support.isolation_level = :fiber
|
11
|
+
# end
|
12
|
+
|
13
|
+
# Gouda fiber configuration
|
14
|
+
Gouda.configure do |config|
|
15
|
+
# Enable fiber-based worker (instead of threads)
|
16
|
+
config.use_fiber_scheduler = true
|
17
|
+
|
18
|
+
# Number of concurrent worker fibers
|
19
|
+
# Can be higher than CPU cores since fibers are lightweight for IO-bound work
|
20
|
+
config.fibers_per_thread = 10
|
21
|
+
|
22
|
+
# Other standard Gouda configuration options work the same
|
23
|
+
config.preserve_job_records = true
|
24
|
+
config.cleanup_preserved_jobs_before = 3.hours
|
25
|
+
end
|
26
|
+
|
27
|
+
# Example of starting the fiber-based worker
|
28
|
+
# Gouda.start
|
29
|
+
|
30
|
+
# The worker will automatically:
|
31
|
+
# 1. Check that Rails isolation level is set to :fiber (warn if not)
|
32
|
+
# 2. Use fiber-based concurrency for non-blocking IO
|
33
|
+
|
34
|
+
# Benefits of fiber-based approach:
|
35
|
+
# 1. Non-blocking IO operations (database queries, HTTP requests, etc.)
|
36
|
+
# 2. Higher concurrency with less memory overhead than threads
|
37
|
+
# 3. Better performance for IO-bound jobs
|
38
|
+
# 4. Cooperative scheduling reduces context switching overhead
|
39
|
+
|
40
|
+
# Important considerations:
|
41
|
+
# 1. Your jobs must use async-compatible gems for full benefit
|
42
|
+
# 2. Database connection pool size should be configured appropriately
|
43
|
+
# 3. CPU-intensive jobs won't benefit much from fiber approach
|
44
|
+
# 4. Requires Ruby 3.1+ with Fiber.scheduler support
|
45
|
+
# 5. When using PostgreSQL: Rails isolation level MUST be set to :fiber
|
@@ -0,0 +1,118 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Demonstration of Gouda's fiber-based non-blocking IO worker
|
4
|
+
# Run this script to see fiber workers in action
|
5
|
+
|
6
|
+
require_relative "../lib/gouda"
|
7
|
+
require "active_record"
|
8
|
+
require "active_job"
|
9
|
+
|
10
|
+
# Setup database connection (assumes PostgreSQL is available)
|
11
|
+
ActiveRecord::Base.establish_connection(
|
12
|
+
adapter: "postgresql",
|
13
|
+
database: "gouda_demo",
|
14
|
+
username: ENV["USER"]
|
15
|
+
)
|
16
|
+
|
17
|
+
# Create tables if they don't exist
|
18
|
+
begin
|
19
|
+
ActiveRecord::Base.connection.execute("SELECT 1 FROM gouda_workloads LIMIT 1")
|
20
|
+
rescue ActiveRecord::StatementInvalid
|
21
|
+
ActiveRecord::Schema.define(version: 1) do |schema|
|
22
|
+
Gouda.create_tables(schema)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Configure Gouda for fiber-based execution
|
27
|
+
Gouda.configure do |config|
|
28
|
+
config.use_fiber_scheduler = true
|
29
|
+
config.fibers_per_thread = 5
|
30
|
+
config.polling_sleep_interval_seconds = 0.1
|
31
|
+
config.preserve_job_records = true
|
32
|
+
end
|
33
|
+
|
34
|
+
# Demo job that simulates IO-bound work
|
35
|
+
class DemoAsyncJob < ActiveJob::Base
|
36
|
+
queue_as :default
|
37
|
+
|
38
|
+
def perform(task_name, duration = 0.1)
|
39
|
+
puts "🚀 Starting #{task_name} (Fiber: #{Fiber.current.object_id})"
|
40
|
+
|
41
|
+
# Simulate async IO work (this will be non-blocking with fiber scheduler)
|
42
|
+
sleep(duration)
|
43
|
+
|
44
|
+
puts "✅ Completed #{task_name} after #{duration}s"
|
45
|
+
|
46
|
+
# Return some result
|
47
|
+
"Task #{task_name} completed at #{Time.now}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Demo job that makes HTTP requests (would be non-blocking with proper async HTTP client)
|
52
|
+
class HttpFetchJob < ActiveJob::Base
|
53
|
+
queue_as :http
|
54
|
+
|
55
|
+
def perform(url)
|
56
|
+
puts "🌐 Fetching #{url} (Fiber: #{Fiber.current.object_id})"
|
57
|
+
|
58
|
+
# In a real scenario, you'd use an async HTTP client like:
|
59
|
+
# require 'async/http'
|
60
|
+
# Async do
|
61
|
+
# internet = Async::HTTP::Internet.new
|
62
|
+
# response = internet.get(url)
|
63
|
+
# puts "📄 Fetched #{response.read.size} bytes from #{url}"
|
64
|
+
# end
|
65
|
+
|
66
|
+
# For demo purposes, simulate the request
|
67
|
+
sleep(0.2)
|
68
|
+
puts "📄 Simulated fetch from #{url}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
puts "🎯 Gouda Fiber Worker Demo"
|
73
|
+
puts "========================="
|
74
|
+
puts "Configuration:"
|
75
|
+
puts " - Fiber scheduler: #{Gouda.config.use_fiber_scheduler}"
|
76
|
+
puts " - Fiber workers: #{Gouda.config.fibers_per_thread}"
|
77
|
+
puts ""
|
78
|
+
|
79
|
+
# Clean up old jobs
|
80
|
+
Gouda::Workload.delete_all
|
81
|
+
|
82
|
+
# Enqueue demo jobs
|
83
|
+
puts "📝 Enqueueing jobs..."
|
84
|
+
Gouda.in_bulk do
|
85
|
+
# Enqueue several IO-bound jobs
|
86
|
+
5.times do |i|
|
87
|
+
DemoAsyncJob.perform_later("Task-#{i}", 0.1 + (i * 0.05))
|
88
|
+
end
|
89
|
+
|
90
|
+
# Enqueue some HTTP jobs
|
91
|
+
3.times do |i|
|
92
|
+
HttpFetchJob.perform_later("https://example.com/page#{i}")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
queued_count = Gouda::Workload.where(state: "enqueued").count
|
97
|
+
puts "📊 Enqueued #{queued_count} jobs"
|
98
|
+
puts ""
|
99
|
+
|
100
|
+
puts "🔄 Starting fiber workers..."
|
101
|
+
puts "Press Ctrl+C to stop"
|
102
|
+
puts ""
|
103
|
+
|
104
|
+
# Run the fiber worker
|
105
|
+
begin
|
106
|
+
Gouda.start
|
107
|
+
rescue Interrupt
|
108
|
+
puts "\n🛑 Stopping workers..."
|
109
|
+
end
|
110
|
+
|
111
|
+
# Show results
|
112
|
+
puts "\n📊 Final Results:"
|
113
|
+
puts " - Finished: #{Gouda::Workload.where(state: "finished").count}"
|
114
|
+
puts " - Enqueued: #{Gouda::Workload.where(state: "enqueued").count}"
|
115
|
+
puts " - Executing: #{Gouda::Workload.where(state: "executing").count}"
|
116
|
+
|
117
|
+
puts "\n💡 Notice how multiple jobs ran concurrently using fibers!"
|
118
|
+
puts " Each job shows its Fiber object ID to demonstrate concurrency."
|
data/gemfiles/rails_7.gemfile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
gouda (0.
|
4
|
+
gouda (0.2.0)
|
5
5
|
activejob (>= 7.2.0)
|
6
6
|
activerecord (>= 7.2.0)
|
7
7
|
activesupport (>= 7.2.0)
|
8
|
+
async (~> 2.25)
|
8
9
|
fugit (~> 1.10)
|
9
10
|
railties (>= 7.2.0)
|
10
11
|
|
@@ -87,6 +88,12 @@ GEM
|
|
87
88
|
rake
|
88
89
|
thor (>= 0.14.0)
|
89
90
|
ast (2.4.2)
|
91
|
+
async (2.25.0)
|
92
|
+
console (~> 1.29)
|
93
|
+
fiber-annotation
|
94
|
+
io-event (~> 1.11)
|
95
|
+
metrics (~> 0.12)
|
96
|
+
traces (~> 0.15)
|
90
97
|
base64 (0.2.0)
|
91
98
|
benchmark (0.4.0)
|
92
99
|
bigdecimal (3.1.9)
|
@@ -94,6 +101,10 @@ GEM
|
|
94
101
|
coderay (1.1.3)
|
95
102
|
concurrent-ruby (1.3.5)
|
96
103
|
connection_pool (2.5.0)
|
104
|
+
console (1.31.0)
|
105
|
+
fiber-annotation
|
106
|
+
fiber-local (~> 1.1)
|
107
|
+
json
|
97
108
|
crass (1.0.6)
|
98
109
|
date (3.4.1)
|
99
110
|
debug (1.10.0)
|
@@ -103,6 +114,10 @@ GEM
|
|
103
114
|
erubi (1.13.1)
|
104
115
|
et-orbi (1.2.11)
|
105
116
|
tzinfo
|
117
|
+
fiber-annotation (0.2.0)
|
118
|
+
fiber-local (1.1.0)
|
119
|
+
fiber-storage
|
120
|
+
fiber-storage (1.0.1)
|
106
121
|
fugit (1.11.1)
|
107
122
|
et-orbi (~> 1, >= 1.2.11)
|
108
123
|
raabro (~> 1.4)
|
@@ -111,6 +126,7 @@ GEM
|
|
111
126
|
i18n (1.14.7)
|
112
127
|
concurrent-ruby (~> 1.0)
|
113
128
|
io-console (0.8.0)
|
129
|
+
io-event (1.11.0)
|
114
130
|
irb (1.15.1)
|
115
131
|
pp (>= 0.6.0)
|
116
132
|
rdoc (>= 4.0.0)
|
@@ -129,6 +145,7 @@ GEM
|
|
129
145
|
net-smtp
|
130
146
|
marcel (1.0.4)
|
131
147
|
method_source (1.1.0)
|
148
|
+
metrics (0.12.2)
|
132
149
|
mini_mime (1.1.5)
|
133
150
|
minitest (5.25.4)
|
134
151
|
net-imap (0.5.6)
|
@@ -239,6 +256,7 @@ GEM
|
|
239
256
|
stringio (3.1.5)
|
240
257
|
thor (1.3.2)
|
241
258
|
timeout (0.4.3)
|
259
|
+
traces (0.15.2)
|
242
260
|
tzinfo (2.0.6)
|
243
261
|
concurrent-ruby (~> 1.0)
|
244
262
|
unicode-display_width (3.1.4)
|
@@ -253,11 +271,13 @@ GEM
|
|
253
271
|
|
254
272
|
PLATFORMS
|
255
273
|
arm64-darwin-21
|
274
|
+
arm64-darwin-23
|
256
275
|
x86_64-darwin
|
257
276
|
x86_64-linux
|
258
277
|
|
259
278
|
DEPENDENCIES
|
260
279
|
appraisal
|
280
|
+
async (~> 2.25)
|
261
281
|
debug
|
262
282
|
gouda!
|
263
283
|
minitest (~> 5.0)
|
data/gemfiles/rails_8.gemfile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
gouda (0.
|
4
|
+
gouda (0.2.0)
|
5
5
|
activejob (>= 7.2.0)
|
6
6
|
activerecord (>= 7.2.0)
|
7
7
|
activesupport (>= 7.2.0)
|
8
|
+
async (~> 2.25)
|
8
9
|
fugit (~> 1.10)
|
9
10
|
railties (>= 7.2.0)
|
10
11
|
|
@@ -87,6 +88,12 @@ GEM
|
|
87
88
|
rake
|
88
89
|
thor (>= 0.14.0)
|
89
90
|
ast (2.4.2)
|
91
|
+
async (2.25.0)
|
92
|
+
console (~> 1.29)
|
93
|
+
fiber-annotation
|
94
|
+
io-event (~> 1.11)
|
95
|
+
metrics (~> 0.12)
|
96
|
+
traces (~> 0.15)
|
90
97
|
base64 (0.2.0)
|
91
98
|
benchmark (0.4.0)
|
92
99
|
bigdecimal (3.1.9)
|
@@ -94,6 +101,10 @@ GEM
|
|
94
101
|
coderay (1.1.3)
|
95
102
|
concurrent-ruby (1.3.5)
|
96
103
|
connection_pool (2.5.0)
|
104
|
+
console (1.31.0)
|
105
|
+
fiber-annotation
|
106
|
+
fiber-local (~> 1.1)
|
107
|
+
json
|
97
108
|
crass (1.0.6)
|
98
109
|
date (3.4.1)
|
99
110
|
debug (1.10.0)
|
@@ -103,6 +114,10 @@ GEM
|
|
103
114
|
erubi (1.13.1)
|
104
115
|
et-orbi (1.2.11)
|
105
116
|
tzinfo
|
117
|
+
fiber-annotation (0.2.0)
|
118
|
+
fiber-local (1.1.0)
|
119
|
+
fiber-storage
|
120
|
+
fiber-storage (1.0.1)
|
106
121
|
fugit (1.11.1)
|
107
122
|
et-orbi (~> 1, >= 1.2.11)
|
108
123
|
raabro (~> 1.4)
|
@@ -111,6 +126,7 @@ GEM
|
|
111
126
|
i18n (1.14.7)
|
112
127
|
concurrent-ruby (~> 1.0)
|
113
128
|
io-console (0.8.0)
|
129
|
+
io-event (1.11.0)
|
114
130
|
irb (1.15.1)
|
115
131
|
pp (>= 0.6.0)
|
116
132
|
rdoc (>= 4.0.0)
|
@@ -129,6 +145,7 @@ GEM
|
|
129
145
|
net-smtp
|
130
146
|
marcel (1.0.4)
|
131
147
|
method_source (1.1.0)
|
148
|
+
metrics (0.12.2)
|
132
149
|
mini_mime (1.1.5)
|
133
150
|
minitest (5.25.4)
|
134
151
|
net-imap (0.5.6)
|
@@ -239,6 +256,7 @@ GEM
|
|
239
256
|
stringio (3.1.5)
|
240
257
|
thor (1.3.2)
|
241
258
|
timeout (0.4.3)
|
259
|
+
traces (0.15.2)
|
242
260
|
tzinfo (2.0.6)
|
243
261
|
concurrent-ruby (~> 1.0)
|
244
262
|
unicode-display_width (3.1.4)
|
@@ -254,11 +272,13 @@ GEM
|
|
254
272
|
|
255
273
|
PLATFORMS
|
256
274
|
arm64-darwin-21
|
275
|
+
arm64-darwin-23
|
257
276
|
x86_64-darwin
|
258
277
|
x86_64-linux
|
259
278
|
|
260
279
|
DEPENDENCIES
|
261
280
|
appraisal
|
281
|
+
async (~> 2.25)
|
262
282
|
debug
|
263
283
|
gouda!
|
264
284
|
minitest (~> 5.0)
|
data/gouda.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_dependency "railties", rails_min
|
27
27
|
spec.add_dependency "activejob", rails_min
|
28
28
|
spec.add_dependency "fugit", "~> 1.10"
|
29
|
+
spec.add_dependency "async", "~> 2.25"
|
29
30
|
|
30
31
|
spec.add_development_dependency "standard"
|
31
32
|
spec.add_development_dependency "pg"
|
data/lib/gouda/railtie.rb
CHANGED
@@ -43,6 +43,8 @@ module Gouda
|
|
43
43
|
Gouda.config.preserve_job_records = config_from_rails[:preserve_job_records]
|
44
44
|
Gouda.config.polling_sleep_interval_seconds = config_from_rails[:polling_sleep_interval_seconds]
|
45
45
|
Gouda.config.worker_thread_count = config_from_rails[:worker_thread_count]
|
46
|
+
Gouda.config.use_fiber_scheduler = config_from_rails[:use_fiber_scheduler]
|
47
|
+
Gouda.config.fibers_per_thread = config_from_rails[:fibers_per_thread]
|
46
48
|
end
|
47
49
|
else
|
48
50
|
Gouda.config.preserve_job_records = false
|
data/lib/gouda/version.rb
CHANGED