fractor 0.1.3 → 0.1.6

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop-https---raw-githubusercontent-com-riboseinc-oss-guides-main-ci-rubocop-yml +552 -0
  3. data/.rubocop.yml +14 -8
  4. data/.rubocop_todo.yml +154 -48
  5. data/README.adoc +1371 -317
  6. data/examples/auto_detection/README.adoc +52 -0
  7. data/examples/auto_detection/auto_detection.rb +170 -0
  8. data/examples/continuous_chat_common/message_protocol.rb +53 -0
  9. data/examples/continuous_chat_fractor/README.adoc +217 -0
  10. data/examples/continuous_chat_fractor/chat_client.rb +303 -0
  11. data/examples/continuous_chat_fractor/chat_common.rb +83 -0
  12. data/examples/continuous_chat_fractor/chat_server.rb +167 -0
  13. data/examples/continuous_chat_fractor/simulate.rb +345 -0
  14. data/examples/continuous_chat_server/README.adoc +135 -0
  15. data/examples/continuous_chat_server/chat_client.rb +303 -0
  16. data/examples/continuous_chat_server/chat_server.rb +359 -0
  17. data/examples/continuous_chat_server/simulate.rb +343 -0
  18. data/examples/hierarchical_hasher/hierarchical_hasher.rb +12 -8
  19. data/examples/multi_work_type/multi_work_type.rb +30 -29
  20. data/examples/pipeline_processing/pipeline_processing.rb +15 -15
  21. data/examples/producer_subscriber/producer_subscriber.rb +20 -16
  22. data/examples/scatter_gather/scatter_gather.rb +29 -28
  23. data/examples/simple/sample.rb +38 -6
  24. data/examples/specialized_workers/specialized_workers.rb +44 -37
  25. data/lib/fractor/continuous_server.rb +188 -0
  26. data/lib/fractor/result_aggregator.rb +1 -1
  27. data/lib/fractor/supervisor.rb +291 -108
  28. data/lib/fractor/version.rb +1 -1
  29. data/lib/fractor/work_queue.rb +68 -0
  30. data/lib/fractor/work_result.rb +1 -1
  31. data/lib/fractor/worker.rb +2 -1
  32. data/lib/fractor/wrapped_ractor.rb +12 -2
  33. data/lib/fractor.rb +2 -0
  34. metadata +17 -2
@@ -8,7 +8,7 @@ module ProducerSubscriber
8
8
  def initialize(data, depth = 0)
9
9
  super({
10
10
  data: data,
11
- depth: depth
11
+ depth: depth,
12
12
  })
13
13
  end
14
14
 
@@ -31,7 +31,7 @@ module ProducerSubscriber
31
31
  super({
32
32
  data: data,
33
33
  parent_id: parent_id,
34
- depth: depth
34
+ depth: depth,
35
35
  })
36
36
  end
37
37
 
@@ -63,7 +63,7 @@ module ProducerSubscriber
63
63
  else
64
64
  Fractor::WorkResult.new(
65
65
  error: "Unknown work type: #{work.class}",
66
- work: work
66
+ work: work,
67
67
  )
68
68
  end
69
69
  end
@@ -80,13 +80,13 @@ module ProducerSubscriber
80
80
  # Return the result with metadata about sub-works
81
81
  result = {
82
82
  processed_data: processed_data,
83
- sub_works: [] # Will be populated by the supervisor
83
+ sub_works: [], # Will be populated by the supervisor
84
84
  }
85
85
 
86
86
  # Return a successful result
87
87
  Fractor::WorkResult.new(
88
88
  result: result,
89
- work: work
89
+ work: work,
90
90
  )
91
91
  end
92
92
 
@@ -101,9 +101,9 @@ module ProducerSubscriber
101
101
  Fractor::WorkResult.new(
102
102
  result: {
103
103
  processed_data: processed_data,
104
- parent_id: work.parent_id
104
+ parent_id: work.parent_id,
105
105
  },
106
- work: work
106
+ work: work,
107
107
  )
108
108
  end
109
109
  end
@@ -122,8 +122,8 @@ module ProducerSubscriber
122
122
  # Create the supervisor
123
123
  supervisor = Fractor::Supervisor.new(
124
124
  worker_pools: [
125
- { worker_class: MultiWorker, num_workers: @worker_count }
126
- ]
125
+ { worker_class: MultiWorker, num_workers: @worker_count },
126
+ ],
127
127
  )
128
128
 
129
129
  # Create and add initial work items
@@ -144,12 +144,14 @@ module ProducerSubscriber
144
144
  # Create a new supervisor for sub-works
145
145
  sub_supervisor = Fractor::Supervisor.new(
146
146
  worker_pools: [
147
- { worker_class: MultiWorker, num_workers: @worker_count }
148
- ]
147
+ { worker_class: MultiWorker, num_workers: @worker_count },
148
+ ],
149
149
  )
150
150
 
151
151
  # Create and add the sub-work items
152
- sub_work_items = sub_works.map { |sw| SubWork.new(sw[:data], sw[:parent_id], sw[:depth]) }
152
+ sub_work_items = sub_works.map do |sw|
153
+ SubWork.new(sw[:data], sw[:parent_id], sw[:depth])
154
+ end
153
155
  sub_supervisor.add_work_items(sub_work_items)
154
156
  sub_supervisor.run
155
157
 
@@ -179,12 +181,14 @@ module ProducerSubscriber
179
181
  sub_works << {
180
182
  data: sub_data,
181
183
  parent_id: work.object_id,
182
- depth: work.depth + 1
184
+ depth: work.depth + 1,
183
185
  }
184
186
  end
185
187
 
186
188
  # Store the sub-work IDs in the result for reference
187
- result.result[:sub_works] = sub_works.last(3).map { |sw| sw[:parent_id] }
189
+ result.result[:sub_works] = sub_works.last(3).map do |sw|
190
+ sw[:parent_id]
191
+ end
188
192
  end
189
193
 
190
194
  sub_works
@@ -195,7 +199,7 @@ module ProducerSubscriber
195
199
  initial_results.results.each do |result|
196
200
  @result_tree[result.work.object_id] = {
197
201
  data: result.result[:processed_data],
198
- children: []
202
+ children: [],
199
203
  }
200
204
  end
201
205
 
@@ -236,7 +240,7 @@ if __FILE__ == $PROGRAM_NAME
236
240
  documents = [
237
241
  "Annual Report 2025",
238
242
  "Technical Documentation",
239
- "Research Paper"
243
+ "Research Paper",
240
244
  ]
241
245
 
242
246
  worker_count = 4
@@ -42,7 +42,7 @@ module ScatterGather
42
42
  error = ArgumentError.new("Unknown source: #{work.source}")
43
43
  return Fractor::WorkResult.new(
44
44
  error: error,
45
- work: work
45
+ work: work,
46
46
  )
47
47
  end
48
48
 
@@ -53,9 +53,9 @@ module ScatterGather
53
53
  query: work.query,
54
54
  hits: result[:hits],
55
55
  metadata: result[:metadata],
56
- timing: result[:timing]
56
+ timing: result[:timing],
57
57
  },
58
- work: work
58
+ work: work,
59
59
  )
60
60
  end
61
61
 
@@ -72,12 +72,12 @@ module ScatterGather
72
72
 
73
73
  # Generate simulated records
74
74
  record_count = rand(3..10)
75
- hits = record_count.times.map do |i|
75
+ hits = Array.new(record_count) do |i|
76
76
  {
77
77
  id: "db-#{i + 1}",
78
78
  title: "Database Result #{i + 1} for '#{work.query}'",
79
79
  content: "This is database content for #{work.query}",
80
- relevance: rand(0.1..1.0).round(2)
80
+ relevance: rand(0.1..1.0).round(2),
81
81
  }
82
82
  end
83
83
 
@@ -86,9 +86,9 @@ module ScatterGather
86
86
  metadata: {
87
87
  source_type: "PostgreSQL Database",
88
88
  total_available: record_count + rand(10..50),
89
- query_type: "Full-text search"
89
+ query_type: "Full-text search",
90
90
  },
91
- timing: rand(0.01..0.3).round(3)
91
+ timing: rand(0.01..0.3).round(3),
92
92
  }
93
93
  end
94
94
 
@@ -98,12 +98,12 @@ module ScatterGather
98
98
 
99
99
  # Generate simulated API results
100
100
  record_count = rand(2..8)
101
- hits = record_count.times.map do |i|
101
+ hits = Array.new(record_count) do |i|
102
102
  {
103
103
  id: "api-#{i + 1}",
104
104
  title: "API Result #{i + 1} for '#{work.query}'",
105
105
  content: "This is API content for #{work.query}",
106
- relevance: rand(0.1..1.0).round(2)
106
+ relevance: rand(0.1..1.0).round(2),
107
107
  }
108
108
  end
109
109
 
@@ -112,9 +112,9 @@ module ScatterGather
112
112
  metadata: {
113
113
  source_type: "External REST API",
114
114
  provider: %w[Google Bing DuckDuckGo].sample,
115
- response_code: 200
115
+ response_code: 200,
116
116
  },
117
- timing: rand(0.1..0.5).round(3)
117
+ timing: rand(0.1..0.5).round(3),
118
118
  }
119
119
  end
120
120
 
@@ -128,12 +128,12 @@ module ScatterGather
128
128
  if cache_hit
129
129
  # Cache hit - return cached results
130
130
  record_count = rand(1..5)
131
- hits = record_count.times.map do |i|
131
+ hits = Array.new(record_count) do |i|
132
132
  {
133
133
  id: "cache-#{i + 1}",
134
134
  title: "Cached Result #{i + 1} for '#{work.query}'",
135
135
  content: "This is cached content for #{work.query}",
136
- relevance: rand(0.1..1.0).round(2)
136
+ relevance: rand(0.1..1.0).round(2),
137
137
  }
138
138
  end
139
139
 
@@ -142,9 +142,9 @@ module ScatterGather
142
142
  metadata: {
143
143
  source_type: "In-memory Cache",
144
144
  cache_hit: true,
145
- age: rand(1..3600)
145
+ age: rand(1..3600),
146
146
  },
147
- timing: rand(0.001..0.05).round(3)
147
+ timing: rand(0.001..0.05).round(3),
148
148
  }
149
149
  else
150
150
  # Cache miss
@@ -152,9 +152,9 @@ module ScatterGather
152
152
  hits: [],
153
153
  metadata: {
154
154
  source_type: "In-memory Cache",
155
- cache_hit: false
155
+ cache_hit: false,
156
156
  },
157
- timing: rand(0.001..0.01).round(3)
157
+ timing: rand(0.001..0.01).round(3),
158
158
  }
159
159
  end
160
160
  end
@@ -165,13 +165,13 @@ module ScatterGather
165
165
 
166
166
  # Generate simulated file results
167
167
  record_count = rand(1..12)
168
- hits = record_count.times.map do |i|
168
+ hits = Array.new(record_count) do |i|
169
169
  {
170
170
  id: "file-#{i + 1}",
171
171
  title: "File Result #{i + 1} for '#{work.query}'",
172
172
  path: "/path/to/file_#{i + 1}.txt",
173
173
  content: "This is file content matching #{work.query}",
174
- relevance: rand(0.1..1.0).round(2)
174
+ relevance: rand(0.1..1.0).round(2),
175
175
  }
176
176
  end
177
177
 
@@ -180,9 +180,9 @@ module ScatterGather
180
180
  metadata: {
181
181
  source_type: "File System",
182
182
  directories_searched: rand(5..20),
183
- files_scanned: rand(50..500)
183
+ files_scanned: rand(50..500),
184
184
  },
185
- timing: rand(0.01..0.2).round(3)
185
+ timing: rand(0.01..0.2).round(3),
186
186
  }
187
187
  end
188
188
  end
@@ -194,8 +194,8 @@ module ScatterGather
194
194
  def initialize(worker_count = 4)
195
195
  @supervisor = Fractor::Supervisor.new(
196
196
  worker_pools: [
197
- { worker_class: SearchWorker, num_workers: worker_count }
198
- ]
197
+ { worker_class: SearchWorker, num_workers: worker_count },
198
+ ],
199
199
  )
200
200
 
201
201
  @merged_results = nil
@@ -204,10 +204,11 @@ module ScatterGather
204
204
  def search(query, sources = nil)
205
205
  # Define search sources with their parameters
206
206
  sources ||= [
207
- { source: :database, params: { max_results: 50, include_archived: false } },
207
+ { source: :database,
208
+ params: { max_results: 50, include_archived: false } },
208
209
  { source: :api, params: { format: "json", timeout: 5 } },
209
210
  { source: :cache, params: { max_age: 3600 } },
210
- { source: :filesystem, params: { extensions: %w[txt md pdf] } }
211
+ { source: :filesystem, params: { extensions: %w[txt md pdf] } },
211
212
  ]
212
213
 
213
214
  start_time = Time.now
@@ -262,7 +263,7 @@ module ScatterGather
262
263
  content: hit[:content],
263
264
  source: source,
264
265
  original_relevance: hit[:relevance],
265
- weighted_relevance: hit[:relevance] * source_weight
266
+ weighted_relevance: hit[:relevance] * source_weight,
266
267
  }
267
268
  end
268
269
  end
@@ -277,7 +278,7 @@ module ScatterGather
277
278
  execution_time: total_time,
278
279
  sources: results_by_source.keys,
279
280
  ranked_results: ranked_hits,
280
- source_details: results_by_source
281
+ source_details: results_by_source,
281
282
  }
282
283
  end
283
284
  end
@@ -309,7 +310,7 @@ if __FILE__ == $PROGRAM_NAME
309
310
  puts "Query: #{results[:query]}"
310
311
  puts "Total hits: #{results[:total_hits]}"
311
312
  puts "Total execution time: #{results[:execution_time].round(3)} seconds"
312
- puts "Sources searched: #{results[:sources].join(", ")}"
313
+ puts "Sources searched: #{results[:sources].join(', ')}"
313
314
  puts
314
315
 
315
316
  puts "Top 5 Results (by relevance):"
@@ -1,7 +1,38 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative "fractor"
4
+ # =============================================================================
5
+ # Simple Example - Getting Started with Fractor
6
+ # =============================================================================
7
+ #
8
+ # This example demonstrates the basic usage of the Fractor framework.
9
+ #
10
+ # WHAT THIS DEMONSTRATES:
11
+ # - How to create a Work class (MyWork) to encapsulate work items
12
+ # - How to create a Worker class (MyWorker) to process work
13
+ # - How to set up a Supervisor to manage parallel processing
14
+ # - Basic error handling in workers
15
+ # - How to access and display results after processing
16
+ # - Auto-detection of available processors (num_workers not specified)
17
+ #
18
+ # KEY CONCEPTS:
19
+ # 1. Work Class: Inherits from Fractor::Work, stores input data
20
+ # 2. Worker Class: Inherits from Fractor::Worker, implements process() method
21
+ # 3. Supervisor: Manages worker Ractors and distributes work
22
+ # 4. WorkResult: Contains either successful results or errors
23
+ #
24
+ # HOW TO RUN:
25
+ # ruby examples/simple/sample.rb
26
+ #
27
+ # WHAT TO EXPECT:
28
+ # - Creates work items with values 1-10
29
+ # - Processes them in parallel using auto-detected number of workers
30
+ # - Value 5 intentionally produces an error for demonstration
31
+ # - Displays successful results and error information
32
+ #
33
+ # =============================================================================
34
+
35
+ require_relative '../../lib/fractor'
5
36
 
6
37
  # Client-specific work item implementation inheriting from Fractor::Work
7
38
  class MyWork < Fractor::Work
@@ -41,14 +72,14 @@ class MyWorker < Fractor::Worker
41
72
  # It should return a Fractor::WorkResult object
42
73
  def process(work)
43
74
  # Only print debug information if FRACTOR_DEBUG is enabled
44
- puts "Working on '#{work.inspect}'" if ENV["FRACTOR_DEBUG"]
75
+ puts "Working on '#{work.inspect}'" if ENV['FRACTOR_DEBUG']
45
76
 
46
77
  # Check work type and handle accordingly
47
78
  if work.is_a?(MyWork)
48
79
  if work.value == 5
49
80
  # Return a Fractor::WorkResult for errors
50
81
  # Store the error object, not just the string
51
- error = StandardError.new("Cannot process value 5")
82
+ error = StandardError.new('Cannot process value 5')
52
83
  return Fractor::WorkResult.new(error: error, work: work)
53
84
  end
54
85
 
@@ -71,9 +102,10 @@ end
71
102
  # MyWorker and MyWork classes.
72
103
  if __FILE__ == $PROGRAM_NAME
73
104
  # Create supervisor, passing the client-specific worker class in a worker pool
105
+ # Note: num_workers is not specified, so it will auto-detect the number of available processors
74
106
  supervisor = Fractor::Supervisor.new(
75
107
  worker_pools: [
76
- { worker_class: MyWorker, num_workers: 2 } # Specify the worker class and number of worker Ractors
108
+ { worker_class: MyWorker } # Worker class without explicit num_workers uses auto-detection
77
109
  ]
78
110
  )
79
111
 
@@ -84,8 +116,8 @@ if __FILE__ == $PROGRAM_NAME
84
116
  # Run the supervisor to start processing work
85
117
  supervisor.run
86
118
 
87
- puts "Processing complete."
88
- puts "Final Aggregated Results:"
119
+ puts 'Processing complete.'
120
+ puts 'Final Aggregated Results:'
89
121
  # Access the results aggregator from the supervisor
90
122
  puts supervisor.results.inspect
91
123
 
@@ -9,7 +9,7 @@ module SpecializedWorkers
9
9
  super({
10
10
  data: data,
11
11
  operation: operation,
12
- parameters: parameters
12
+ parameters: parameters,
13
13
  })
14
14
  end
15
15
 
@@ -32,12 +32,13 @@ module SpecializedWorkers
32
32
 
33
33
  # Second work type: Database operations
34
34
  class DatabaseWork < Fractor::Work
35
- def initialize(data = "", query_type = :select, table = "unknown", conditions = {})
35
+ def initialize(data = "", query_type = :select, table = "unknown",
36
+ conditions = {})
36
37
  super({
37
38
  data: data,
38
39
  query_type: query_type,
39
40
  table: table,
40
- conditions: conditions
41
+ conditions: conditions,
41
42
  })
42
43
  end
43
44
 
@@ -74,14 +75,16 @@ module SpecializedWorkers
74
75
  unless work.is_a?(ComputeWork)
75
76
  return Fractor::WorkResult.new(
76
77
  error: "ComputeWorker can only process ComputeWork, got: #{work.class}",
77
- work: work
78
+ work: work,
78
79
  )
79
80
  end
80
81
 
81
82
  # Process based on the requested operation
82
83
  result = case work.operation
83
- when :matrix_multiply then matrix_multiply(work.data, work.parameters)
84
- when :image_transform then image_transform(work.data, work.parameters)
84
+ when :matrix_multiply then matrix_multiply(work.data,
85
+ work.parameters)
86
+ when :image_transform then image_transform(work.data,
87
+ work.parameters)
85
88
  when :path_finding then path_finding(work.data, work.parameters)
86
89
  else default_computation(work.data, work.parameters)
87
90
  end
@@ -90,9 +93,9 @@ module SpecializedWorkers
90
93
  result: {
91
94
  operation: work.operation,
92
95
  computation_result: result,
93
- resources_used: @compute_resources
96
+ resources_used: @compute_resources,
94
97
  },
95
- work: work
98
+ work: work,
96
99
  )
97
100
  end
98
101
 
@@ -110,7 +113,7 @@ module SpecializedWorkers
110
113
  # Simulate image transformation
111
114
  sleep(rand(0.1..0.3))
112
115
  transforms = params[:transforms] || %i[rotate scale]
113
- "Image transformation applied: #{transforms.join(", ")} with parameters #{params}"
116
+ "Image transformation applied: #{transforms.join(', ')} with parameters #{params}"
114
117
  end
115
118
 
116
119
  def path_finding(_data, params)
@@ -140,7 +143,7 @@ module SpecializedWorkers
140
143
  unless work.is_a?(DatabaseWork)
141
144
  return Fractor::WorkResult.new(
142
145
  error: "DatabaseWorker can only process DatabaseWork, got: #{work.class}",
143
- work: work
146
+ work: work,
144
147
  )
145
148
  end
146
149
 
@@ -148,7 +151,8 @@ module SpecializedWorkers
148
151
  result = case work.query_type
149
152
  when :select then perform_select(work.table, work.conditions)
150
153
  when :insert then perform_insert(work.table, work.data)
151
- when :update then perform_update(work.table, work.data, work.conditions)
154
+ when :update then perform_update(work.table, work.data,
155
+ work.conditions)
152
156
  when :delete then perform_delete(work.table, work.conditions)
153
157
  else default_query(work.query_type, work.table, work.conditions)
154
158
  end
@@ -159,9 +163,9 @@ module SpecializedWorkers
159
163
  table: work.table,
160
164
  rows_affected: result[:rows_affected],
161
165
  data: result[:data],
162
- execution_time: result[:time]
166
+ execution_time: result[:time],
163
167
  },
164
- work: work
168
+ work: work,
165
169
  )
166
170
  end
167
171
 
@@ -174,8 +178,10 @@ module SpecializedWorkers
174
178
  record_count = rand(0..20)
175
179
  {
176
180
  rows_affected: record_count,
177
- data: record_count.times.map { |i| { id: i + 1, name: "Record #{i + 1}" } },
178
- time: rand(0.01..0.05)
181
+ data: Array.new(record_count) do |i|
182
+ { id: i + 1, name: "Record #{i + 1}" }
183
+ end,
184
+ time: rand(0.01..0.05),
179
185
  }
180
186
  end
181
187
 
@@ -185,7 +191,7 @@ module SpecializedWorkers
185
191
  {
186
192
  rows_affected: 1,
187
193
  data: { id: rand(1000..9999) },
188
- time: rand(0.01..0.03)
194
+ time: rand(0.01..0.03),
189
195
  }
190
196
  end
191
197
 
@@ -196,7 +202,7 @@ module SpecializedWorkers
196
202
  {
197
203
  rows_affected: affected,
198
204
  data: nil,
199
- time: rand(0.01..0.05)
205
+ time: rand(0.01..0.05),
200
206
  }
201
207
  end
202
208
 
@@ -207,7 +213,7 @@ module SpecializedWorkers
207
213
  {
208
214
  rows_affected: affected,
209
215
  data: nil,
210
- time: rand(0.01..0.03)
216
+ time: rand(0.01..0.03),
211
217
  }
212
218
  end
213
219
 
@@ -217,7 +223,7 @@ module SpecializedWorkers
217
223
  {
218
224
  rows_affected: 0,
219
225
  data: nil,
220
- time: rand(0.005..0.01)
226
+ time: rand(0.005..0.01),
221
227
  }
222
228
  end
223
229
  end
@@ -230,14 +236,14 @@ module SpecializedWorkers
230
236
  # Create separate supervisors for each worker type
231
237
  @compute_supervisor = Fractor::Supervisor.new(
232
238
  worker_pools: [
233
- { worker_class: ComputeWorker, num_workers: compute_workers }
234
- ]
239
+ { worker_class: ComputeWorker, num_workers: compute_workers },
240
+ ],
235
241
  )
236
242
 
237
243
  @db_supervisor = Fractor::Supervisor.new(
238
244
  worker_pools: [
239
- { worker_class: DatabaseWorker, num_workers: db_workers }
240
- ]
245
+ { worker_class: DatabaseWorker, num_workers: db_workers },
246
+ ],
241
247
  )
242
248
 
243
249
  @compute_results = []
@@ -253,7 +259,8 @@ module SpecializedWorkers
253
259
 
254
260
  # Create and add database work items
255
261
  db_work_items = db_tasks.map do |task|
256
- DatabaseWork.new(task[:data], task[:query_type], task[:table], task[:conditions])
262
+ DatabaseWork.new(task[:data], task[:query_type], task[:table],
263
+ task[:conditions])
257
264
  end
258
265
  @db_supervisor.add_work_items(db_work_items)
259
266
 
@@ -277,13 +284,13 @@ module SpecializedWorkers
277
284
  computation: {
278
285
  tasks: compute_tasks.size,
279
286
  completed: @compute_results.size,
280
- results: @compute_results
287
+ results: @compute_results,
281
288
  },
282
289
  database: {
283
290
  tasks: db_tasks.size,
284
291
  completed: @db_results.size,
285
- results: @db_results
286
- }
292
+ results: @db_results,
293
+ },
287
294
  }
288
295
  end
289
296
 
@@ -316,18 +323,18 @@ if __FILE__ == $PROGRAM_NAME
316
323
  {
317
324
  operation: :matrix_multiply,
318
325
  data: "Matrix data...",
319
- parameters: { size: [10, 10] }
326
+ parameters: { size: [10, 10] },
320
327
  },
321
328
  {
322
329
  operation: :image_transform,
323
330
  data: "Image data...",
324
- parameters: { transforms: %i[rotate scale blur], angle: 45, scale: 1.5 }
331
+ parameters: { transforms: %i[rotate scale blur], angle: 45, scale: 1.5 },
325
332
  },
326
333
  {
327
334
  operation: :path_finding,
328
335
  data: "Graph data...",
329
- parameters: { algorithm: :dijkstra, nodes: 20, start: 1, end: 15 }
330
- }
336
+ parameters: { algorithm: :dijkstra, nodes: 20, start: 1, end: 15 },
337
+ },
331
338
  ]
332
339
 
333
340
  # Prepare database tasks
@@ -335,24 +342,24 @@ if __FILE__ == $PROGRAM_NAME
335
342
  {
336
343
  query_type: :select,
337
344
  table: "users",
338
- conditions: { active: true, role: "admin" }
345
+ conditions: { active: true, role: "admin" },
339
346
  },
340
347
  {
341
348
  query_type: :insert,
342
349
  table: "orders",
343
- data: "Order data..."
350
+ data: "Order data...",
344
351
  },
345
352
  {
346
353
  query_type: :update,
347
354
  table: "products",
348
355
  data: "Product data...",
349
- conditions: { category: "electronics" }
356
+ conditions: { category: "electronics" },
350
357
  },
351
358
  {
352
359
  query_type: :delete,
353
360
  table: "sessions",
354
- conditions: { expired: true }
355
- }
361
+ conditions: { expired: true },
362
+ },
356
363
  ]
357
364
 
358
365
  compute_workers = 2
@@ -363,7 +370,7 @@ if __FILE__ == $PROGRAM_NAME
363
370
  start_time = Time.now
364
371
  system = SpecializedWorkers::HybridSystem.new(
365
372
  compute_workers: compute_workers,
366
- db_workers: db_workers
373
+ db_workers: db_workers,
367
374
  )
368
375
  result = system.process_mixed_workload(compute_tasks, db_tasks)
369
376
  end_time = Time.now