taski 0.4.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +51 -33
- data/Steepfile +1 -0
- data/docs/GUIDE.md +340 -0
- data/examples/README.md +68 -20
- data/examples/{context_demo.rb → args_demo.rb} +27 -27
- data/examples/clean_demo.rb +204 -0
- data/examples/data_pipeline_demo.rb +3 -3
- data/examples/group_demo.rb +113 -0
- data/examples/nested_section_demo.rb +161 -0
- data/examples/parallel_progress_demo.rb +1 -1
- data/examples/reexecution_demo.rb +93 -80
- data/examples/system_call_demo.rb +56 -0
- data/examples/tree_progress_demo.rb +164 -0
- data/lib/taski/{context.rb → args.rb} +3 -3
- data/lib/taski/execution/execution_context.rb +379 -0
- data/lib/taski/execution/executor.rb +538 -0
- data/lib/taski/execution/registry.rb +26 -2
- data/lib/taski/execution/scheduler.rb +308 -0
- data/lib/taski/execution/task_output_pipe.rb +42 -0
- data/lib/taski/execution/task_output_router.rb +216 -0
- data/lib/taski/execution/task_wrapper.rb +295 -146
- data/lib/taski/execution/tree_progress_display.rb +793 -0
- data/lib/taski/execution/worker_pool.rb +104 -0
- data/lib/taski/section.rb +23 -0
- data/lib/taski/static_analysis/analyzer.rb +4 -2
- data/lib/taski/static_analysis/visitor.rb +86 -5
- data/lib/taski/task.rb +223 -120
- data/lib/taski/version.rb +1 -1
- data/lib/taski.rb +147 -28
- data/sig/taski.rbs +310 -67
- metadata +17 -8
- data/docs/advanced-features.md +0 -625
- data/docs/api-guide.md +0 -509
- data/docs/error-handling.md +0 -684
- data/lib/taski/execution/coordinator.rb +0 -63
- data/lib/taski/execution/parallel_progress_display.rb +0 -201
data/sig/taski.rbs
CHANGED
|
@@ -2,7 +2,9 @@ module Taski
|
|
|
2
2
|
VERSION: String
|
|
3
3
|
|
|
4
4
|
self.@global_registry: Execution::Registry?
|
|
5
|
-
self.@progress_display: Execution::
|
|
5
|
+
self.@progress_display: Execution::TreeProgressDisplay?
|
|
6
|
+
self.@args: Args?
|
|
7
|
+
self.@args_monitor: Monitor
|
|
6
8
|
|
|
7
9
|
# Type alias for Task class (singleton type with class methods)
|
|
8
10
|
# This represents a Class that inherits from Taski::Task
|
|
@@ -11,9 +13,13 @@ module Taski
|
|
|
11
13
|
# Module-level methods
|
|
12
14
|
def self.global_registry: () -> Execution::Registry
|
|
13
15
|
def self.reset_global_registry!: () -> void
|
|
14
|
-
def self.progress_display: () -> Execution::
|
|
15
|
-
def self.
|
|
16
|
+
def self.progress_display: () -> Execution::TreeProgressDisplay?
|
|
17
|
+
def self.progress_disabled?: () -> bool
|
|
16
18
|
def self.reset_progress_display!: () -> 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?
|
|
17
23
|
|
|
18
24
|
# Custom exceptions
|
|
19
25
|
class TaskAbortException < StandardError
|
|
@@ -27,55 +33,101 @@ module Taski
|
|
|
27
33
|
def initialize: (Array[Array[Class]] cyclic_tasks) -> void
|
|
28
34
|
end
|
|
29
35
|
|
|
30
|
-
#
|
|
31
|
-
class
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
82
|
+
@options: Hash[Symbol | String, untyped]
|
|
83
|
+
@root_task: Class
|
|
84
|
+
@started_at: Time
|
|
85
|
+
@working_directory: String
|
|
86
|
+
|
|
87
|
+
attr_reader started_at: Time
|
|
88
|
+
attr_reader working_directory: String
|
|
89
|
+
attr_reader root_task: Class
|
|
90
|
+
|
|
91
|
+
def initialize: (options: Hash[Symbol | String, untyped], root_task: Class) -> void
|
|
92
|
+
def []: (Symbol | String key) -> untyped
|
|
93
|
+
def fetch: (Symbol | String key, ?untyped default) ?{ () -> untyped } -> untyped
|
|
94
|
+
def key?: (Symbol | String key) -> bool
|
|
42
95
|
end
|
|
43
96
|
|
|
44
97
|
# Main Task class
|
|
45
98
|
class Task
|
|
46
99
|
self.@exported_methods: Array[Symbol]
|
|
47
100
|
self.@dependencies_cache: Set[task_class]?
|
|
48
|
-
self.@coordinator: Execution::Coordinator?
|
|
49
101
|
self.@circular_dependency_checked: bool
|
|
50
102
|
|
|
51
103
|
# Class methods
|
|
104
|
+
def self.inherited: (Class subclass) -> void
|
|
52
105
|
def self.exports: (*Symbol names) -> void
|
|
53
106
|
def self.exported_methods: () -> Array[Symbol]
|
|
54
107
|
def self.new: () -> Execution::TaskWrapper
|
|
55
108
|
def self.cached_dependencies: () -> Set[task_class]
|
|
56
109
|
def self.clear_dependency_cache: () -> void
|
|
57
|
-
def self.run: () -> untyped
|
|
58
|
-
def self.clean: () -> 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
|
|
59
113
|
def self.registry: () -> Execution::Registry
|
|
60
|
-
def self.coordinator: () -> Execution::Coordinator
|
|
61
114
|
def self.reset!: () -> void
|
|
62
115
|
def self.tree: () -> String
|
|
63
116
|
|
|
64
117
|
# Instance methods
|
|
65
118
|
def run: () -> void
|
|
66
119
|
def clean: () -> void
|
|
120
|
+
def system: (*untyped args, **untyped opts) -> bool?
|
|
67
121
|
def reset!: () -> void
|
|
68
122
|
|
|
69
123
|
private
|
|
70
124
|
|
|
71
125
|
# Private class methods
|
|
72
|
-
def self.build_tree: (task_class task_class, String prefix, Set[task_class] visited) -> String
|
|
73
|
-
def self.format_dependency_branch: (task_class dep, String prefix, bool is_last, Set[task_class] visited) -> String
|
|
74
|
-
def self.tree_connector_chars: (bool is_last) -> [String, String]
|
|
75
126
|
def self.cached_wrapper: () -> Execution::TaskWrapper
|
|
76
127
|
def self.define_instance_reader: (Symbol method_name) -> void
|
|
77
128
|
def self.define_class_accessor: (Symbol method_name) -> void
|
|
78
129
|
def self.validate_no_circular_dependencies!: () -> void
|
|
130
|
+
def self.validate_workers!: (untyped workers) -> void
|
|
79
131
|
end
|
|
80
132
|
|
|
81
133
|
# Section class for abstraction layers (inherits from Task)
|
|
@@ -119,43 +171,191 @@ module Taski
|
|
|
119
171
|
|
|
120
172
|
def initialize: () -> void
|
|
121
173
|
def get_or_create: (Class task_class) { () -> TaskWrapper } -> TaskWrapper
|
|
122
|
-
def get_task: (Class task_class) -> TaskWrapper
|
|
174
|
+
def get_task: (Class task_class) -> TaskWrapper?
|
|
175
|
+
def register: (Class task_class, TaskWrapper wrapper) -> void
|
|
123
176
|
def register_thread: (Thread thread) -> void
|
|
124
177
|
def wait_all: () -> void
|
|
125
178
|
def reset!: () -> void
|
|
126
179
|
def request_abort!: () -> void
|
|
127
180
|
def abort_requested?: () -> bool
|
|
128
181
|
def run: (Class task_class, Array[Symbol] exported_methods) -> untyped
|
|
182
|
+
def failed_wrappers: () -> Array[TaskWrapper]
|
|
183
|
+
def failed_clean_wrappers: () -> Array[TaskWrapper]
|
|
129
184
|
end
|
|
130
185
|
|
|
131
|
-
#
|
|
132
|
-
class
|
|
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
|
|
241
|
+
STATE_PENDING: Symbol
|
|
242
|
+
STATE_ENQUEUED: Symbol
|
|
243
|
+
STATE_COMPLETED: Symbol
|
|
244
|
+
CLEAN_STATE_PENDING: Symbol
|
|
245
|
+
CLEAN_STATE_ENQUEUED: Symbol
|
|
246
|
+
CLEAN_STATE_COMPLETED: Symbol
|
|
247
|
+
|
|
248
|
+
@dependencies: Hash[Class, Set[Class]]
|
|
249
|
+
@task_states: Hash[Class, Symbol]
|
|
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]
|
|
254
|
+
|
|
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
|
|
133
281
|
@registry: Registry
|
|
134
|
-
@
|
|
282
|
+
@on_execute: ^(Class, TaskWrapper) -> void
|
|
283
|
+
@execution_queue: Thread::Queue
|
|
284
|
+
@workers: Array[Thread]
|
|
135
285
|
|
|
136
|
-
def initialize: (registry: Registry,
|
|
137
|
-
def
|
|
138
|
-
def
|
|
139
|
-
def
|
|
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
|
|
140
291
|
|
|
141
292
|
private
|
|
142
293
|
|
|
143
|
-
def
|
|
144
|
-
def
|
|
145
|
-
def
|
|
294
|
+
def default_worker_count: () -> Integer
|
|
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
|
+
|
|
317
|
+
def enqueue_ready_tasks: () -> void
|
|
318
|
+
def enqueue_task: (Class task_class) -> void
|
|
319
|
+
def get_or_create_wrapper: (Class task_class) -> TaskWrapper
|
|
320
|
+
def execute_task: (Class task_class, TaskWrapper wrapper) -> void
|
|
321
|
+
def run_main_loop: (Class root_task_class) -> void
|
|
322
|
+
def handle_completion: (Hash[Symbol, untyped] event) -> 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
|
|
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
|
|
146
342
|
end
|
|
147
343
|
|
|
148
344
|
# TaskWrapper class for task execution
|
|
149
345
|
class TaskWrapper
|
|
150
346
|
attr_reader task: Task
|
|
151
347
|
attr_reader result: untyped
|
|
348
|
+
attr_reader error: StandardError?
|
|
349
|
+
attr_reader clean_error: StandardError?
|
|
350
|
+
attr_reader timing: TaskTiming?
|
|
152
351
|
|
|
153
352
|
@task: Task
|
|
154
353
|
@registry: Registry
|
|
155
|
-
@
|
|
354
|
+
@execution_context: ExecutionContext?
|
|
156
355
|
@result: untyped
|
|
157
356
|
@clean_result: untyped
|
|
158
357
|
@error: StandardError?
|
|
358
|
+
@clean_error: StandardError?
|
|
159
359
|
@monitor: Monitor
|
|
160
360
|
@condition: MonitorMixin::ConditionVariable
|
|
161
361
|
@clean_condition: MonitorMixin::ConditionVariable
|
|
@@ -166,39 +366,45 @@ module Taski
|
|
|
166
366
|
STATE_PENDING: Symbol
|
|
167
367
|
STATE_RUNNING: Symbol
|
|
168
368
|
STATE_COMPLETED: Symbol
|
|
169
|
-
|
|
170
|
-
|
|
369
|
+
STATE_FAILED: Symbol
|
|
370
|
+
|
|
371
|
+
def initialize: (Task task, registry: Registry, ?execution_context: ExecutionContext?) -> void
|
|
372
|
+
def state: () -> Symbol
|
|
373
|
+
def pending?: () -> bool
|
|
374
|
+
def completed?: () -> bool
|
|
375
|
+
def failed?: () -> bool
|
|
376
|
+
def clean_failed?: () -> bool
|
|
171
377
|
def run: () -> untyped
|
|
172
|
-
def clean: () ->
|
|
378
|
+
def clean: () -> untyped
|
|
379
|
+
def run_and_clean: () -> untyped
|
|
173
380
|
def get_exported_value: (Symbol method_name) -> untyped
|
|
174
|
-
def
|
|
175
|
-
def
|
|
176
|
-
def
|
|
177
|
-
def
|
|
178
|
-
def
|
|
179
|
-
def
|
|
180
|
-
def
|
|
181
|
-
def start_async_clean: () -> void
|
|
182
|
-
def execute_clean: () -> void
|
|
183
|
-
def wait_for_clean_dependencies: () -> void
|
|
184
|
-
def mark_completed: () -> void
|
|
185
|
-
def mark_clean_completed: () -> void
|
|
186
|
-
def wait_for_completion: () -> untyped
|
|
381
|
+
def mark_running: () -> bool
|
|
382
|
+
def mark_completed: (untyped result) -> void
|
|
383
|
+
def mark_failed: (StandardError error) -> void
|
|
384
|
+
def mark_clean_running: () -> bool
|
|
385
|
+
def mark_clean_completed: (untyped result) -> void
|
|
386
|
+
def mark_clean_failed: (StandardError error) -> void
|
|
387
|
+
def wait_for_completion: () -> void
|
|
187
388
|
def wait_for_clean_completion: () -> void
|
|
188
|
-
def debug_log: (String message) -> void
|
|
189
|
-
def log_start: () -> void
|
|
190
|
-
def log_completion: () -> void
|
|
191
|
-
def log_clean_start: () -> void
|
|
192
|
-
def log_clean_completion: () -> void
|
|
193
|
-
def register_with_progress_display: () -> void
|
|
194
|
-
def update_progress: (Symbol state, ?duration: Numeric?, ?error: Exception?) -> void
|
|
195
389
|
def method_missing: (Symbol name, *untyped args) ?{ (*untyped) -> untyped } -> untyped
|
|
196
390
|
def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
|
|
391
|
+
|
|
392
|
+
private
|
|
393
|
+
|
|
394
|
+
def trigger_execution_and_wait: () -> void
|
|
395
|
+
def trigger_clean_and_wait: () -> void
|
|
396
|
+
def execute_clean: () -> void
|
|
397
|
+
def wait_for_clean_dependencies: () -> void
|
|
398
|
+
def check_abort!: () -> void
|
|
399
|
+
def update_progress: (Symbol state, ?duration: Numeric?, ?error: Exception?) -> void
|
|
400
|
+
def debug_log: (String message) -> void
|
|
197
401
|
end
|
|
198
402
|
|
|
199
|
-
#
|
|
200
|
-
class
|
|
403
|
+
# TreeProgressDisplay class for tree-based progress visualization
|
|
404
|
+
class TreeProgressDisplay
|
|
201
405
|
SPINNER_FRAMES: Array[String]
|
|
406
|
+
COLORS: Hash[Symbol, String]
|
|
407
|
+
ICONS: Hash[Symbol, String]
|
|
202
408
|
|
|
203
409
|
@output: IO
|
|
204
410
|
@tasks: Hash[Class, TaskProgress]
|
|
@@ -206,6 +412,30 @@ module Taski
|
|
|
206
412
|
@spinner_index: Integer
|
|
207
413
|
@renderer_thread: Thread?
|
|
208
414
|
@running: bool
|
|
415
|
+
@nest_level: Integer
|
|
416
|
+
@root_task_class: Class?
|
|
417
|
+
@tree_structure: Hash[Symbol, untyped]?
|
|
418
|
+
@section_impl_map: Hash[Class, Class]
|
|
419
|
+
@last_line_count: Integer
|
|
420
|
+
|
|
421
|
+
# Shared class methods
|
|
422
|
+
def self.section_class?: (Class klass) -> bool
|
|
423
|
+
def self.nested_class?: (Class child_class, Class parent_class) -> bool
|
|
424
|
+
def self.render_static_tree: (Class root_task_class) -> String
|
|
425
|
+
|
|
426
|
+
# Static tree renderer (internal class)
|
|
427
|
+
class StaticTreeRenderer
|
|
428
|
+
@task_index_map: Hash[Class, Integer]
|
|
429
|
+
|
|
430
|
+
def render: (Class root_task_class) -> String
|
|
431
|
+
|
|
432
|
+
private
|
|
433
|
+
|
|
434
|
+
def build_tree: (Class task_class, String prefix, bool is_impl, Set[Class] ancestors) -> String
|
|
435
|
+
def render_dependency_branch: (Class dep, String prefix, bool is_last, bool is_impl, Set[Class] ancestors) -> String
|
|
436
|
+
def get_task_number: (Class task_class) -> String
|
|
437
|
+
def colored_type_label: (Class klass) -> String
|
|
438
|
+
end
|
|
209
439
|
|
|
210
440
|
class TaskProgress
|
|
211
441
|
attr_accessor state: Symbol
|
|
@@ -213,28 +443,37 @@ module Taski
|
|
|
213
443
|
attr_accessor end_time: Time?
|
|
214
444
|
attr_accessor error: Exception?
|
|
215
445
|
attr_accessor duration: Numeric?
|
|
446
|
+
attr_accessor is_impl_candidate: bool
|
|
216
447
|
|
|
217
448
|
def initialize: () -> void
|
|
218
449
|
end
|
|
219
450
|
|
|
220
451
|
def initialize: (?output: IO) -> void
|
|
452
|
+
def set_root_task: (Class root_task_class) -> void
|
|
453
|
+
def register_section_impl: (Class section_class, Class impl_class) -> void
|
|
221
454
|
def register_task: (Class task_class) -> void
|
|
222
455
|
def task_registered?: (Class task_class) -> bool
|
|
223
456
|
def update_task: (Class task_class, state: Symbol, ?duration: Numeric?, ?error: Exception?) -> void
|
|
224
457
|
def task_state: (Class task_class) -> Symbol?
|
|
225
|
-
def render: () -> void
|
|
226
458
|
def start: () -> void
|
|
227
459
|
def stop: () -> void
|
|
228
460
|
|
|
229
461
|
private
|
|
230
462
|
|
|
231
|
-
def
|
|
463
|
+
def build_tree_structure: () -> void
|
|
464
|
+
def build_tree_node: (Class task_class, Set[Class] ancestors) -> Hash[Symbol, untyped]?
|
|
465
|
+
def register_tasks_from_tree: (Hash[Symbol, untyped] node) -> void
|
|
232
466
|
def render_live: () -> void
|
|
233
467
|
def render_final: () -> void
|
|
234
|
-
def
|
|
235
|
-
def
|
|
468
|
+
def build_tree_display: () -> Array[String]
|
|
469
|
+
def build_root_tree_lines: (Hash[Symbol, untyped] node, String prefix, Array[String] lines) -> void
|
|
470
|
+
def render_children: (Hash[Symbol, untyped] node, String prefix, Array[String] lines, Class parent_task_class, bool ancestor_selected) -> void
|
|
471
|
+
def format_tree_line: (Class task_class, TaskProgress? progress, bool is_impl, bool is_selected) -> String
|
|
472
|
+
def format_unknown_task: (Class task_class, ?bool is_selected) -> String
|
|
236
473
|
def spinner_char: () -> String
|
|
237
|
-
def
|
|
474
|
+
def type_label_for: (Class task_class, ?bool is_selected) -> String
|
|
475
|
+
def section_class?: (Class klass) -> bool
|
|
476
|
+
def nested_class?: (Class child_class, Class parent_class) -> bool
|
|
238
477
|
end
|
|
239
478
|
end
|
|
240
479
|
|
|
@@ -246,19 +485,21 @@ module Taski
|
|
|
246
485
|
|
|
247
486
|
private
|
|
248
487
|
|
|
249
|
-
def self.
|
|
488
|
+
def self.target_method_for: (Class task_class) -> Symbol
|
|
489
|
+
def self.extract_method_location: (Class task_class, Symbol method_name) -> [String, Integer]?
|
|
250
490
|
end
|
|
251
491
|
|
|
252
492
|
# Visitor class for AST traversal
|
|
253
493
|
class Visitor < Prism::Visitor
|
|
254
494
|
@target_task_class: Class
|
|
495
|
+
@target_method: Symbol
|
|
255
496
|
@dependencies: Set[task_class]
|
|
256
|
-
@
|
|
497
|
+
@in_target_method: bool
|
|
257
498
|
@current_namespace_path: Array[String?]
|
|
258
499
|
|
|
259
500
|
attr_reader dependencies: Set[task_class]
|
|
260
501
|
|
|
261
|
-
def initialize: (Class task_class) -> void
|
|
502
|
+
def initialize: (Class task_class, Symbol target_method) -> void
|
|
262
503
|
def visit_class_node: (Prism::ClassNode node) -> untyped
|
|
263
504
|
def visit_module_node: (Prism::ModuleNode node) -> untyped
|
|
264
505
|
def visit_def_node: (Prism::DefNode node) -> untyped
|
|
@@ -268,8 +509,10 @@ module Taski
|
|
|
268
509
|
|
|
269
510
|
def within_namespace: (String? name) { () -> void } -> void
|
|
270
511
|
def in_target_class?: () -> bool
|
|
512
|
+
def in_impl_method?: () -> bool
|
|
271
513
|
def extract_constant_name: (untyped node) -> String?
|
|
272
514
|
def detect_task_dependency: (Prism::CallNode node) -> void
|
|
515
|
+
def detect_impl_candidate: (untyped node) -> void
|
|
273
516
|
def extract_receiver_constant: (untyped receiver) -> String?
|
|
274
517
|
def resolve_and_add_dependency: (String constant_name) -> void
|
|
275
518
|
def resolve_constant: (String name) -> task_class?
|
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.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ahogappa
|
|
@@ -50,26 +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/
|
|
58
|
-
- docs/api-guide.md
|
|
59
|
-
- docs/error-handling.md
|
|
58
|
+
- docs/GUIDE.md
|
|
60
59
|
- examples/README.md
|
|
61
|
-
- examples/
|
|
60
|
+
- examples/args_demo.rb
|
|
61
|
+
- examples/clean_demo.rb
|
|
62
62
|
- examples/data_pipeline_demo.rb
|
|
63
|
+
- examples/group_demo.rb
|
|
64
|
+
- examples/nested_section_demo.rb
|
|
63
65
|
- examples/parallel_progress_demo.rb
|
|
64
66
|
- examples/quick_start.rb
|
|
65
67
|
- examples/reexecution_demo.rb
|
|
66
68
|
- examples/section_demo.rb
|
|
69
|
+
- examples/system_call_demo.rb
|
|
70
|
+
- examples/tree_progress_demo.rb
|
|
67
71
|
- lib/taski.rb
|
|
68
|
-
- lib/taski/
|
|
69
|
-
- lib/taski/execution/
|
|
70
|
-
- lib/taski/execution/
|
|
72
|
+
- lib/taski/args.rb
|
|
73
|
+
- lib/taski/execution/execution_context.rb
|
|
74
|
+
- lib/taski/execution/executor.rb
|
|
71
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
|
|
72
79
|
- lib/taski/execution/task_wrapper.rb
|
|
80
|
+
- lib/taski/execution/tree_progress_display.rb
|
|
81
|
+
- lib/taski/execution/worker_pool.rb
|
|
73
82
|
- lib/taski/section.rb
|
|
74
83
|
- lib/taski/static_analysis/analyzer.rb
|
|
75
84
|
- lib/taski/static_analysis/dependency_graph.rb
|