taski 0.5.0 → 0.7.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.
data/sig/taski.rbs CHANGED
@@ -3,7 +3,8 @@ module Taski
3
3
 
4
4
  self.@global_registry: Execution::Registry?
5
5
  self.@progress_display: Execution::TreeProgressDisplay?
6
- self.@context: Context?
6
+ self.@args: Args?
7
+ self.@args_monitor: Monitor
7
8
 
8
9
  # Type alias for Task class (singleton type with class methods)
9
10
  # This represents a Class that inherits from Taski::Task
@@ -15,9 +16,10 @@ module Taski
15
16
  def self.progress_display: () -> Execution::TreeProgressDisplay?
16
17
  def self.progress_disabled?: () -> bool
17
18
  def self.reset_progress_display!: () -> void
18
- def self.context: () -> Hash[Symbol, untyped]
19
- def self.start_context: (options: Hash[Symbol, untyped], root_task: Class) -> void
20
- def self.reset_context!: () -> void
19
+ def self.args: () -> Args?
20
+ def self.start_args: (options: Hash[Symbol, untyped], root_task: Class) -> void
21
+ def self.reset_args!: () -> void
22
+ def self.args_worker_count: () -> Integer?
21
23
 
22
24
  # Custom exceptions
23
25
  class TaskAbortException < StandardError
@@ -31,8 +33,52 @@ module Taski
31
33
  def initialize: (Array[Array[Class]] cyclic_tasks) -> void
32
34
  end
33
35
 
34
- # Context class for execution context management
35
- class Context
36
+ # Represents a single task failure with its context
37
+ class TaskFailure
38
+ @task_class: Class
39
+ @error: Exception
40
+
41
+ attr_reader task_class: Class
42
+ attr_reader error: Exception
43
+
44
+ def initialize: (task_class: Class, error: Exception) -> void
45
+ end
46
+
47
+ # Mixin for exception classes to enable transparent rescue matching with AggregateError
48
+ module AggregateAware
49
+ def ===: (untyped other) -> bool
50
+ end
51
+
52
+ # Base class for task-specific error wrappers
53
+ class TaskError < StandardError
54
+ extend AggregateAware
55
+
56
+ @cause: Exception
57
+ @task_class: Class
58
+
59
+ attr_reader cause: Exception
60
+ attr_reader task_class: Class
61
+
62
+ def initialize: (Exception cause, task_class: Class) -> void
63
+ end
64
+
65
+ # Raised when multiple tasks fail during parallel execution
66
+ class AggregateError < StandardError
67
+ @errors: Array[TaskFailure]
68
+
69
+ attr_reader errors: Array[TaskFailure]
70
+
71
+ def initialize: (Array[TaskFailure] errors) -> void
72
+ def cause: () -> Exception?
73
+ def includes?: (Class exception_class) -> bool
74
+
75
+ private
76
+
77
+ def build_message: () -> String
78
+ end
79
+
80
+ # Args class for execution arguments management
81
+ class Args
36
82
  @options: Hash[Symbol | String, untyped]
37
83
  @root_task: Class
38
84
  @started_at: Time
@@ -55,13 +101,15 @@ module Taski
55
101
  self.@circular_dependency_checked: bool
56
102
 
57
103
  # Class methods
104
+ def self.inherited: (Class subclass) -> void
58
105
  def self.exports: (*Symbol names) -> void
59
106
  def self.exported_methods: () -> Array[Symbol]
60
107
  def self.new: () -> Execution::TaskWrapper
61
108
  def self.cached_dependencies: () -> Set[task_class]
62
109
  def self.clear_dependency_cache: () -> void
63
- def self.run: (?context: Hash[Symbol, untyped]) -> untyped
64
- def self.clean: (?context: Hash[Symbol, untyped]) -> void
110
+ def self.run: (?args: Hash[Symbol, untyped], ?workers: Integer?) -> untyped
111
+ def self.clean: (?args: Hash[Symbol, untyped], ?workers: Integer?) -> void
112
+ def self.run_and_clean: (?args: Hash[Symbol, untyped], ?workers: Integer?) -> untyped
65
113
  def self.registry: () -> Execution::Registry
66
114
  def self.reset!: () -> void
67
115
  def self.tree: () -> String
@@ -69,6 +117,7 @@ module Taski
69
117
  # Instance methods
70
118
  def run: () -> void
71
119
  def clean: () -> void
120
+ def system: (*untyped args, **untyped opts) -> bool?
72
121
  def reset!: () -> void
73
122
 
74
123
  private
@@ -78,6 +127,7 @@ module Taski
78
127
  def self.define_instance_reader: (Symbol method_name) -> void
79
128
  def self.define_class_accessor: (Symbol method_name) -> void
80
129
  def self.validate_no_circular_dependencies!: () -> void
130
+ def self.validate_workers!: (untyped workers) -> void
81
131
  end
82
132
 
83
133
  # Section class for abstraction layers (inherits from Task)
@@ -129,43 +179,166 @@ module Taski
129
179
  def request_abort!: () -> void
130
180
  def abort_requested?: () -> bool
131
181
  def run: (Class task_class, Array[Symbol] exported_methods) -> untyped
182
+ def failed_wrappers: () -> Array[TaskWrapper]
183
+ def failed_clean_wrappers: () -> Array[TaskWrapper]
132
184
  end
133
185
 
134
- # Executor class for parallel task execution (Producer-Consumer pattern)
135
- class Executor
186
+ # ExecutionContext manages execution state and notifies observers about execution events
187
+ class ExecutionContext
188
+ THREAD_LOCAL_KEY: Symbol
189
+
190
+ @monitor: Monitor
191
+ @observers: Array[untyped]
192
+ @execution_trigger: (^(Class, Registry) -> void)?
193
+ @clean_trigger: (^(Class, Registry) -> void)?
194
+ @output_capture: TaskOutputRouter?
195
+ @original_stdout: IO?
196
+ @runtime_dependencies: Hash[Class, Set[Class]]
197
+
198
+ def self.current: () -> ExecutionContext?
199
+ def self.current=: (ExecutionContext? context) -> void
200
+
201
+ def initialize: () -> void
202
+ def output_capture_active?: () -> bool
203
+ def setup_output_capture: (IO output_io) -> void
204
+ def teardown_output_capture: () -> void
205
+ def output_capture: () -> TaskOutputRouter?
206
+ def execution_trigger=: ((^(Class, Registry) -> void)? trigger) -> void
207
+ def clean_trigger=: ((^(Class, Registry) -> void)? trigger) -> void
208
+ def trigger_execution: (Class task_class, registry: Registry) -> void
209
+ def trigger_clean: (Class task_class, registry: Registry) -> untyped
210
+ def register_runtime_dependency: (Class from_class, Class to_class) -> void
211
+ def runtime_dependencies: () -> Hash[Class, Set[Class]]
212
+ def add_observer: (untyped observer) -> void
213
+ def remove_observer: (untyped observer) -> void
214
+ def observers: () -> Array[untyped]
215
+ def notify_task_registered: (Class task_class) -> void
216
+ def notify_task_started: (Class task_class) -> void
217
+ def notify_task_completed: (Class task_class, ?duration: Float?, ?error: Exception?) -> void
218
+ def notify_section_impl_selected: (Class section_class, Class impl_class) -> void
219
+ def notify_set_root_task: (Class task_class) -> void
220
+ def notify_set_output_capture: (TaskOutputRouter output_capture) -> void
221
+ def notify_start: () -> void
222
+ def notify_stop: () -> void
223
+ def notify_clean_started: (Class task_class) -> void
224
+ def notify_clean_completed: (Class task_class, ?duration: Float?, ?error: Exception?) -> void
225
+
226
+ private
227
+
228
+ def dispatch: (Symbol method_name, *untyped args, **untyped kwargs) -> void
229
+ end
230
+
231
+ # TaskOutputRouter for routing task output
232
+ class TaskOutputRouter
233
+ def initialize: (IO original_io) -> void
234
+ def current_write_io: () -> IO?
235
+ def start_capture: (Class task_class) -> void
236
+ def stop_capture: () -> void
237
+ end
238
+
239
+ # Scheduler manages task dependency state and determines execution order
240
+ class Scheduler
136
241
  STATE_PENDING: Symbol
137
242
  STATE_ENQUEUED: Symbol
138
243
  STATE_COMPLETED: Symbol
244
+ CLEAN_STATE_PENDING: Symbol
245
+ CLEAN_STATE_ENQUEUED: Symbol
246
+ CLEAN_STATE_COMPLETED: Symbol
139
247
 
140
- @registry: Registry
141
- @worker_count: Integer
142
- @execution_queue: Thread::Queue
143
- @completion_queue: Thread::Queue
144
- @workers: Array[Thread]
145
248
  @dependencies: Hash[Class, Set[Class]]
146
249
  @task_states: Hash[Class, Symbol]
147
250
  @completed_tasks: Set[Class]
251
+ @reverse_dependencies: Hash[Class, Set[Class]]
252
+ @clean_task_states: Hash[Class, Symbol]
253
+ @clean_completed_tasks: Set[Class]
148
254
 
149
- def self.execute: (Class root_task_class, registry: Registry) -> void
150
- def initialize: (registry: Registry, ?worker_count: Integer?) -> void
151
- def execute: (Class root_task_class) -> void
255
+ def initialize: () -> void
256
+ def build_dependency_graph: (Class root_task_class) -> void
257
+ def next_ready_tasks: () -> Array[Class]
258
+ def mark_enqueued: (Class task_class) -> void
259
+ def mark_completed: (Class task_class) -> void
260
+ def completed?: (Class task_class) -> bool
261
+ def running_tasks?: () -> bool
262
+ def merge_runtime_dependencies: (Hash[Class, Set[Class]] runtime_deps) -> void
263
+ def build_reverse_dependency_graph: (Class root_task_class) -> void
264
+ def next_ready_clean_tasks: () -> Array[Class]
265
+ def mark_clean_enqueued: (Class task_class) -> void
266
+ def mark_clean_completed: (Class task_class) -> void
267
+ def clean_completed?: (Class task_class) -> bool
268
+ def running_clean_tasks?: () -> bool
269
+
270
+ private
271
+
272
+ def ready_to_execute?: (Class task_class) -> bool
273
+ def ready_to_clean?: (Class task_class) -> bool
274
+ end
275
+
276
+ # WorkerPool manages a pool of worker threads that execute tasks
277
+ class WorkerPool
278
+ attr_reader execution_queue: Thread::Queue
279
+
280
+ @worker_count: Integer
281
+ @registry: Registry
282
+ @on_execute: ^(Class, TaskWrapper) -> void
283
+ @execution_queue: Thread::Queue
284
+ @workers: Array[Thread]
285
+
286
+ def initialize: (registry: Registry, ?worker_count: Integer?) { (Class, TaskWrapper) -> void } -> void
287
+ def start: () -> void
288
+ def enqueue: (Class task_class, TaskWrapper wrapper) -> void
289
+ def shutdown: () -> void
290
+ def enqueue_shutdown_signals: () -> void
152
291
 
153
292
  private
154
293
 
155
294
  def default_worker_count: () -> Integer
156
- def build_dependency_graph: (Class root_task_class) -> void
295
+ def worker_loop: () -> void
296
+ def debug_log: (String message) -> void
297
+ end
298
+
299
+ # Executor class for parallel task execution (Producer-Consumer pattern)
300
+ class Executor
301
+ @registry: Registry
302
+ @completion_queue: Thread::Queue
303
+ @execution_context: ExecutionContext
304
+ @scheduler: Scheduler
305
+ @effective_worker_count: Integer?
306
+ @worker_pool: WorkerPool
307
+ @clean_worker_pool: WorkerPool?
308
+
309
+ def self.execute: (Class root_task_class, registry: Registry, ?execution_context: ExecutionContext?) -> void
310
+ def self.execute_clean: (Class root_task_class, registry: Registry, ?execution_context: ExecutionContext?) -> void
311
+ def initialize: (registry: Registry, ?worker_count: Integer?, ?execution_context: ExecutionContext?) -> void
312
+ def execute: (Class root_task_class) -> void
313
+ def execute_clean: (Class root_task_class) -> void
314
+
315
+ private
316
+
157
317
  def enqueue_ready_tasks: () -> void
158
- def ready_to_execute?: (Class task_class) -> bool
159
318
  def enqueue_task: (Class task_class) -> void
160
319
  def get_or_create_wrapper: (Class task_class) -> TaskWrapper
161
- def start_workers: () -> void
162
- def worker_loop: () -> void
163
320
  def execute_task: (Class task_class, TaskWrapper wrapper) -> void
164
321
  def run_main_loop: (Class root_task_class) -> void
165
- def no_running_tasks?: () -> bool
166
322
  def handle_completion: (Hash[Symbol, untyped] event) -> void
167
- def shutdown_workers: () -> void
323
+ def enqueue_ready_clean_tasks: () -> void
324
+ def enqueue_clean_task: (Class task_class) -> void
325
+ def execute_clean_task: (Class task_class, TaskWrapper wrapper) -> void
326
+ def run_clean_main_loop: (Class root_task_class) -> void
327
+ def handle_clean_completion: (Hash[Symbol, untyped] event) -> void
328
+ def all_tasks_cleaned?: () -> bool
329
+ def setup_progress_display: (Class root_task_class) -> void
330
+ def setup_output_capture_if_needed: () -> bool
331
+ def teardown_output_capture: () -> void
332
+ def start_progress_display: () -> void
333
+ def stop_progress_display: () -> void
334
+ def create_default_execution_context: () -> ExecutionContext
168
335
  def debug_log: (String message) -> void
336
+ def raise_if_any_failures: () -> void
337
+ def flatten_failures: (Array[TaskWrapper] failed_wrappers) -> Array[TaskFailure]
338
+ def wrap_with_task_error: (Class task_class, Exception error) -> TaskError
339
+ def raise_if_any_clean_failures: () -> void
340
+ def flatten_clean_failures: (Array[TaskWrapper] failed_wrappers) -> Array[TaskFailure]
341
+ def error_identity: (Exception error) -> Integer
169
342
  end
170
343
 
171
344
  # TaskWrapper class for task execution
@@ -173,13 +346,16 @@ module Taski
173
346
  attr_reader task: Task
174
347
  attr_reader result: untyped
175
348
  attr_reader error: StandardError?
349
+ attr_reader clean_error: StandardError?
176
350
  attr_reader timing: TaskTiming?
177
351
 
178
352
  @task: Task
179
353
  @registry: Registry
354
+ @execution_context: ExecutionContext?
180
355
  @result: untyped
181
356
  @clean_result: untyped
182
357
  @error: StandardError?
358
+ @clean_error: StandardError?
183
359
  @monitor: Monitor
184
360
  @condition: MonitorMixin::ConditionVariable
185
361
  @clean_condition: MonitorMixin::ConditionVariable
@@ -190,18 +366,24 @@ module Taski
190
366
  STATE_PENDING: Symbol
191
367
  STATE_RUNNING: Symbol
192
368
  STATE_COMPLETED: Symbol
369
+ STATE_FAILED: Symbol
193
370
 
194
- def initialize: (Task task, registry: Registry) -> void
371
+ def initialize: (Task task, registry: Registry, ?execution_context: ExecutionContext?) -> void
195
372
  def state: () -> Symbol
196
373
  def pending?: () -> bool
197
374
  def completed?: () -> bool
375
+ def failed?: () -> bool
376
+ def clean_failed?: () -> bool
198
377
  def run: () -> untyped
199
378
  def clean: () -> untyped
379
+ def run_and_clean: () -> untyped
200
380
  def get_exported_value: (Symbol method_name) -> untyped
201
381
  def mark_running: () -> bool
202
382
  def mark_completed: (untyped result) -> void
203
383
  def mark_failed: (StandardError error) -> void
384
+ def mark_clean_running: () -> bool
204
385
  def mark_clean_completed: (untyped result) -> void
386
+ def mark_clean_failed: (StandardError error) -> void
205
387
  def wait_for_completion: () -> void
206
388
  def wait_for_clean_completion: () -> void
207
389
  def method_missing: (Symbol name, *untyped args) ?{ (*untyped) -> untyped } -> untyped
@@ -288,10 +470,8 @@ module Taski
288
470
  def render_children: (Hash[Symbol, untyped] node, String prefix, Array[String] lines, Class parent_task_class, bool ancestor_selected) -> void
289
471
  def format_tree_line: (Class task_class, TaskProgress? progress, bool is_impl, bool is_selected) -> String
290
472
  def format_unknown_task: (Class task_class, ?bool is_selected) -> String
291
- def task_status_icon: (Symbol state, bool is_selected) -> String
292
473
  def spinner_char: () -> String
293
474
  def type_label_for: (Class task_class, ?bool is_selected) -> String
294
- def task_details: (TaskProgress progress) -> String
295
475
  def section_class?: (Class klass) -> bool
296
476
  def nested_class?: (Class child_class, Class parent_class) -> bool
297
477
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taski
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ahogappa
@@ -50,29 +50,35 @@ extensions: []
50
50
  extra_rdoc_files: []
51
51
  files:
52
52
  - ".standard.yml"
53
+ - CHANGELOG.md
53
54
  - LICENSE
54
55
  - README.md
55
56
  - Rakefile
56
57
  - Steepfile
57
- - docs/advanced-features.md
58
- - docs/api-guide.md
59
- - docs/error-handling.md
58
+ - docs/GUIDE.md
60
59
  - examples/README.md
61
- - examples/context_demo.rb
60
+ - examples/args_demo.rb
61
+ - examples/clean_demo.rb
62
62
  - examples/data_pipeline_demo.rb
63
+ - examples/group_demo.rb
63
64
  - examples/nested_section_demo.rb
64
65
  - examples/parallel_progress_demo.rb
65
66
  - examples/quick_start.rb
66
67
  - examples/reexecution_demo.rb
67
68
  - examples/section_demo.rb
68
- - examples/section_progress_demo.rb
69
+ - examples/system_call_demo.rb
69
70
  - examples/tree_progress_demo.rb
70
71
  - lib/taski.rb
71
- - lib/taski/context.rb
72
+ - lib/taski/args.rb
73
+ - lib/taski/execution/execution_context.rb
72
74
  - lib/taski/execution/executor.rb
73
75
  - lib/taski/execution/registry.rb
76
+ - lib/taski/execution/scheduler.rb
77
+ - lib/taski/execution/task_output_pipe.rb
78
+ - lib/taski/execution/task_output_router.rb
74
79
  - lib/taski/execution/task_wrapper.rb
75
80
  - lib/taski/execution/tree_progress_display.rb
81
+ - lib/taski/execution/worker_pool.rb
76
82
  - lib/taski/section.rb
77
83
  - lib/taski/static_analysis/analyzer.rb
78
84
  - lib/taski/static_analysis/dependency_graph.rb