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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ad491a59ec06c6199846bdbbb072f3298ed932533ba87de9b3d5da807b7f6a7
4
- data.tar.gz: e703c1552897344e3f26830c7a6c386db5ba961bf97f9bfea27c819696d802f5
3
+ metadata.gz: 6a5b6d65b9cbfbe699e5bbfe1dd2854eeebc74d711d22243ec9c1c647d6986f7
4
+ data.tar.gz: d2642c37fe82af94a577d6b0806e9178842b8b0a53b64fe2eefeb1362f748a06
5
5
  SHA512:
6
- metadata.gz: 730efd4a32941cd408e39e5b43772b5627736f232d7632d10564e6c273d9af45986522b550db1deef32f87abcb89808ac39e2b762174c66a3d0d09537e054f9f
7
- data.tar.gz: 9706f6a827bdbc916eb26004e6d267c377b4f51d1f6f568423e3aed1c8eeaf9ec1d784a6bd8623f7d41234618fc88ed31db4a0dddcc4c26ea7ef5a5688e22582
6
+ metadata.gz: 8d276d47fd5dced75511522900f1328ee1cb7cb076f833e6dc0d8eb597cafdc1933986ebb17a2ec37390d0d3e74b2c183fdabba204cc0e41c2010ccb2adefcdb
7
+ data.tar.gz: 644d5eba7e6fca4fbf2f21d805d98985be8e72fcfa5e06dc8402a26fefb292c2a204134071e0e31ca345ab74863ea6191aa934479e6eb1b865a31e4bea2ff817
data/Appraisals CHANGED
@@ -1,7 +1,9 @@
1
1
  appraise "rails-7" do
2
2
  gem "rails", "< 8.0"
3
+ gem "async", "~> 2.25"
3
4
  end
4
5
 
5
6
  appraise "rails-8" do
6
7
  gem "rails", ">= 8.0"
8
+ gem "async", "~> 2.25"
7
9
  end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [0.2.0]
2
+
3
+ - Introduce fiber execution for workers
4
+
1
5
  ## [0.1.16]
2
6
 
3
7
  - Actualy suppress DEBUG level logs in `suppressing_sql_logs` :facepalm:
data/Gemfile CHANGED
@@ -6,3 +6,4 @@ gemspec
6
6
  gem "standard", require: false
7
7
  gem "rake", "~> 13.0"
8
8
  gem "minitest", "~> 5.0"
9
+ gem "async", "~> 2.25"
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 . 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 has crashed or hung. The value can also be used to build a table of currently running workers.
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
- ## Web UI
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
- At the moment the Gouda UI is proprietary, so this gem only provides a "headless" implementation. We expect this to change in the future.
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."
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  gem "standard", require: false
6
6
  gem "rake", "~> 13.0"
7
7
  gem "minitest", "~> 5.0"
8
+ gem "async", "~> 2.25"
8
9
  gem "rails", "< 8.0"
9
10
 
10
11
  gemspec path: "../"
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- gouda (0.1.14)
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)
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  gem "standard", require: false
6
6
  gem "rake", "~> 13.0"
7
7
  gem "minitest", "~> 5.0"
8
+ gem "async", "~> 2.25"
8
9
  gem "rails", ">= 8.0"
9
10
 
10
11
  gemspec path: "../"
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- gouda (0.1.14)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gouda
4
- VERSION = "0.1.16"
4
+ VERSION = "0.2.0"
5
5
  end