taski 0.8.1 → 0.8.2
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 +9 -0
- data/README.md +42 -1
- data/docs/GUIDE.md +18 -4
- data/examples/README.md +33 -45
- data/examples/progress_demo.rb +154 -0
- data/lib/taski/execution/base_progress_display.rb +16 -0
- data/lib/taski/execution/execution_context.rb +2 -21
- data/lib/taski/execution/executor.rb +0 -8
- data/lib/taski/execution/simple_progress_display.rb +8 -2
- data/lib/taski/execution/task_output_router.rb +2 -1
- data/lib/taski/version.rb +1 -1
- data/lib/taski.rb +3 -3
- metadata +2 -8
- data/examples/data_pipeline_demo.rb +0 -231
- data/examples/large_tree_demo.rb +0 -519
- data/examples/nested_section_demo.rb +0 -161
- data/examples/parallel_progress_demo.rb +0 -72
- data/examples/simple_progress_demo.rb +0 -80
- data/examples/system_call_demo.rb +0 -56
- data/examples/tree_progress_demo.rb +0 -164
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ecbd73a50d1f39207625cda94e9f90a90ce212d270a70ed49cd94705bb30a5c
|
|
4
|
+
data.tar.gz: d5efd7fcf8c5c0d5bdfacf147e302375e63d41acd00f428924e87ba3a4e54ac0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e263e9c974f17ff46f545adc3cf90cddf66cbfe273c783d07f036a2d3fc4c7f8ec4759c1a94ff72ab0b302d8c4fae50a4654cda5b4b17d9f218ae897ba67572a
|
|
7
|
+
data.tar.gz: 9bf8d6b053ee781ef9ba2535926ef663be9ed45d88249d59a5325d7cbd600468ae5bacc69e506ae5bc7f2819707b9e4451a0faf0aa377dbbfb33fe04a7d9199b
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.2] - 2026-01-26
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Queue `Taski.message` output until progress display stops to prevent interleaved output ([#133](https://github.com/ahogappa/taski/pull/133))
|
|
14
|
+
- Correct task count display in SimpleProgressDisplay ([#132](https://github.com/ahogappa/taski/pull/132))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Consolidate examples from 15 to 8 files for better maintainability ([#131](https://github.com/ahogappa/taski/pull/131))
|
|
18
|
+
|
|
10
19
|
## [0.8.1] - 2026-01-26
|
|
11
20
|
|
|
12
21
|
### Added
|
data/README.md
CHANGED
|
@@ -262,6 +262,34 @@ end
|
|
|
262
262
|
|
|
263
263
|
When `TaskAbortException` is raised, no new tasks will start. Already running tasks will complete, then execution stops.
|
|
264
264
|
|
|
265
|
+
### Lifecycle Management
|
|
266
|
+
|
|
267
|
+
Define `clean` methods for resource cleanup. Clean runs in reverse dependency order:
|
|
268
|
+
|
|
269
|
+
```ruby
|
|
270
|
+
class DatabaseSetup < Taski::Task
|
|
271
|
+
exports :connection
|
|
272
|
+
|
|
273
|
+
def run
|
|
274
|
+
@connection = connect_to_database
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def clean
|
|
278
|
+
@connection&.close
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Run then clean in one call
|
|
283
|
+
DatabaseSetup.run_and_clean
|
|
284
|
+
|
|
285
|
+
# Or separately
|
|
286
|
+
DatabaseSetup.run
|
|
287
|
+
# ... do work ...
|
|
288
|
+
DatabaseSetup.clean
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
See [docs/guide.md](docs/guide.md#lifecycle-management) for details.
|
|
292
|
+
|
|
265
293
|
### Progress Display
|
|
266
294
|
|
|
267
295
|
Tree-based progress visualization is enabled by default:
|
|
@@ -281,14 +309,27 @@ WebServer (Task)
|
|
|
281
309
|
✓ [5/5] All tasks completed (1234ms)
|
|
282
310
|
```
|
|
283
311
|
|
|
312
|
+
**Plain mode** provides text output without escape codes (for CI/logs):
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
[START] DatabaseSetup
|
|
316
|
+
[DONE] DatabaseSetup (45.2ms)
|
|
317
|
+
[START] WebServer
|
|
318
|
+
[DONE] WebServer (120.5ms)
|
|
319
|
+
[TASKI] Completed: 2/2 tasks (165ms)
|
|
320
|
+
```
|
|
321
|
+
|
|
284
322
|
**Configuration:**
|
|
285
323
|
|
|
286
324
|
```ruby
|
|
287
325
|
# Via API
|
|
288
|
-
Taski.progress_mode = :
|
|
326
|
+
Taski.progress_mode = :tree # Tree display (default)
|
|
327
|
+
Taski.progress_mode = :simple # Single-line display
|
|
328
|
+
Taski.progress_mode = :plain # Plain text (CI/logs)
|
|
289
329
|
|
|
290
330
|
# Via environment variable
|
|
291
331
|
TASKI_PROGRESS_MODE=simple ruby your_script.rb
|
|
332
|
+
TASKI_PROGRESS_MODE=plain ruby your_script.rb
|
|
292
333
|
```
|
|
293
334
|
|
|
294
335
|
To disable: `TASKI_PROGRESS_DISABLE=1 ruby your_script.rb`
|
data/docs/GUIDE.md
CHANGED
|
@@ -324,20 +324,34 @@ On failure:
|
|
|
324
324
|
✗ [3/5] DeployTask failed: Connection refused
|
|
325
325
|
```
|
|
326
326
|
|
|
327
|
+
#### Plain Mode
|
|
328
|
+
|
|
329
|
+
Plain text output without escape codes, designed for CI/logs:
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
[START] DatabaseSetup
|
|
333
|
+
[DONE] DatabaseSetup (45.2ms)
|
|
334
|
+
[START] WebServer
|
|
335
|
+
[DONE] WebServer (120.5ms)
|
|
336
|
+
[TASKI] Completed: 2/2 tasks (165ms)
|
|
337
|
+
```
|
|
338
|
+
|
|
327
339
|
### Configuring Progress Mode
|
|
328
340
|
|
|
329
341
|
**Via API:**
|
|
330
342
|
|
|
331
343
|
```ruby
|
|
332
|
-
Taski.progress_mode = :
|
|
333
|
-
Taski.progress_mode = :
|
|
344
|
+
Taski.progress_mode = :tree # Tree display (default)
|
|
345
|
+
Taski.progress_mode = :simple # Single-line display
|
|
346
|
+
Taski.progress_mode = :plain # Plain text (CI/logs)
|
|
334
347
|
```
|
|
335
348
|
|
|
336
349
|
**Via environment variable:**
|
|
337
350
|
|
|
338
351
|
```bash
|
|
339
|
-
TASKI_PROGRESS_MODE=simple ruby your_script.rb
|
|
340
352
|
TASKI_PROGRESS_MODE=tree ruby your_script.rb
|
|
353
|
+
TASKI_PROGRESS_MODE=simple ruby your_script.rb
|
|
354
|
+
TASKI_PROGRESS_MODE=plain ruby your_script.rb
|
|
341
355
|
```
|
|
342
356
|
|
|
343
357
|
### Disabling Progress Display
|
|
@@ -363,7 +377,7 @@ ruby build.rb > build.log 2>&1
|
|
|
363
377
|
| Variable | Purpose |
|
|
364
378
|
|----------|---------|
|
|
365
379
|
| `TASKI_PROGRESS_DISABLE=1` | Disable progress display |
|
|
366
|
-
| `TASKI_PROGRESS_MODE=simple\|
|
|
380
|
+
| `TASKI_PROGRESS_MODE=tree\|simple\|plain` | Set progress display mode (default: tree) |
|
|
367
381
|
| `TASKI_DEBUG=1` | Enable debug output |
|
|
368
382
|
|
|
369
383
|
### Dependency Tree Visualization
|
data/examples/README.md
CHANGED
|
@@ -67,78 +67,67 @@ TASKI_PROGRESS_DISABLE=1 ruby examples/reexecution_demo.rb
|
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
70
|
-
### 5.
|
|
70
|
+
### 5. clean_demo.rb - Lifecycle Management
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
ruby examples/data_pipeline_demo.rb
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**Covers:**
|
|
79
|
-
- Multiple data sources in parallel
|
|
80
|
-
- Data transformation stages
|
|
81
|
-
- Aggregation and reporting
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
### 6. parallel_progress_demo.rb - Progress Display
|
|
86
|
-
|
|
87
|
-
Real-time progress visualization during parallel execution.
|
|
72
|
+
Demonstrates resource cleanup with clean methods.
|
|
88
73
|
|
|
89
74
|
```bash
|
|
90
|
-
ruby examples/
|
|
75
|
+
ruby examples/clean_demo.rb
|
|
91
76
|
```
|
|
92
77
|
|
|
93
78
|
**Covers:**
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
79
|
+
- Defining `clean` methods for resource cleanup
|
|
80
|
+
- Reverse dependency order execution
|
|
81
|
+
- `run_and_clean` combined operation
|
|
97
82
|
|
|
98
83
|
---
|
|
99
84
|
|
|
100
|
-
###
|
|
85
|
+
### 6. group_demo.rb - Task Output Grouping
|
|
101
86
|
|
|
102
|
-
|
|
87
|
+
Organize task output into logical phases with groups.
|
|
103
88
|
|
|
104
89
|
```bash
|
|
105
|
-
ruby examples/
|
|
90
|
+
ruby examples/group_demo.rb
|
|
106
91
|
```
|
|
107
92
|
|
|
108
93
|
**Covers:**
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
94
|
+
- `group("label") { ... }` for organizing output
|
|
95
|
+
- Groups displayed as children in progress tree
|
|
96
|
+
- Multiple groups within a single task
|
|
112
97
|
|
|
113
98
|
---
|
|
114
99
|
|
|
115
|
-
###
|
|
100
|
+
### 7. message_demo.rb - User-Facing Messages
|
|
116
101
|
|
|
117
|
-
|
|
102
|
+
Output messages that bypass the progress display capture.
|
|
118
103
|
|
|
119
104
|
```bash
|
|
120
|
-
ruby examples/
|
|
105
|
+
ruby examples/message_demo.rb
|
|
121
106
|
```
|
|
122
107
|
|
|
123
108
|
**Covers:**
|
|
124
|
-
- `
|
|
125
|
-
-
|
|
126
|
-
-
|
|
109
|
+
- `Taski.message(text)` for user-facing output
|
|
110
|
+
- Messages queued during progress and shown after completion
|
|
111
|
+
- Difference between `puts` (captured) and `Taski.message` (bypassed)
|
|
127
112
|
|
|
128
113
|
---
|
|
129
114
|
|
|
130
|
-
###
|
|
115
|
+
### 8. progress_demo.rb - Progress Display Modes
|
|
131
116
|
|
|
132
|
-
|
|
117
|
+
Real-time progress visualization during parallel execution.
|
|
133
118
|
|
|
134
119
|
```bash
|
|
135
|
-
|
|
120
|
+
ruby examples/progress_demo.rb # Tree mode
|
|
121
|
+
TASKI_PROGRESS_MODE=simple ruby examples/progress_demo.rb # Simple mode
|
|
122
|
+
TASKI_PROGRESS_DISABLE=1 ruby examples/progress_demo.rb # Disabled
|
|
136
123
|
```
|
|
137
124
|
|
|
138
125
|
**Covers:**
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
126
|
+
- Tree progress display (default)
|
|
127
|
+
- Simple one-line progress display
|
|
128
|
+
- Parallel task execution
|
|
129
|
+
- Task output capture and streaming
|
|
130
|
+
- system() output integration
|
|
142
131
|
|
|
143
132
|
---
|
|
144
133
|
|
|
@@ -148,13 +137,12 @@ TASKI_PROGRESS_DISABLE=1 ruby examples/nested_section_demo.rb
|
|
|
148
137
|
|---------|---------|------------|
|
|
149
138
|
| quick_start | Exports API | Basic |
|
|
150
139
|
| section_demo | Section API | Intermediate |
|
|
151
|
-
| args_demo | Args API | Intermediate |
|
|
140
|
+
| args_demo | Args/Env API | Intermediate |
|
|
152
141
|
| reexecution_demo | Scope-Based Execution | Intermediate |
|
|
153
|
-
| data_pipeline_demo | ETL Pipeline | Advanced |
|
|
154
|
-
| parallel_progress_demo | Progress Display | Advanced |
|
|
155
142
|
| clean_demo | Lifecycle Management | Intermediate |
|
|
156
|
-
|
|
|
157
|
-
|
|
|
143
|
+
| group_demo | Output Grouping | Intermediate |
|
|
144
|
+
| message_demo | User Messages | Basic |
|
|
145
|
+
| progress_demo | Progress Display | Advanced |
|
|
158
146
|
|
|
159
147
|
## Running All Examples
|
|
160
148
|
|
|
@@ -163,7 +151,7 @@ TASKI_PROGRESS_DISABLE=1 ruby examples/nested_section_demo.rb
|
|
|
163
151
|
for f in examples/*.rb; do echo "=== $f ===" && ruby "$f" && echo; done
|
|
164
152
|
|
|
165
153
|
# Disable progress display if needed
|
|
166
|
-
TASKI_PROGRESS_DISABLE=1 ruby examples/
|
|
154
|
+
TASKI_PROGRESS_DISABLE=1 ruby examples/progress_demo.rb
|
|
167
155
|
```
|
|
168
156
|
|
|
169
157
|
## Next Steps
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Taski Progress Display Demo
|
|
5
|
+
#
|
|
6
|
+
# This example demonstrates the progress display modes:
|
|
7
|
+
# - Tree mode (default): Shows task hierarchy with real-time updates
|
|
8
|
+
# - Simple mode: One-line spinner with current task name
|
|
9
|
+
#
|
|
10
|
+
# Run:
|
|
11
|
+
# ruby examples/progress_demo.rb # Tree mode (default)
|
|
12
|
+
# TASKI_PROGRESS_MODE=simple ruby examples/progress_demo.rb # Simple mode
|
|
13
|
+
# TASKI_PROGRESS_DISABLE=1 ruby examples/progress_demo.rb # No progress
|
|
14
|
+
#
|
|
15
|
+
# Covers:
|
|
16
|
+
# - Parallel task execution with progress display
|
|
17
|
+
# - Tree vs simple progress modes
|
|
18
|
+
# - Task output capture and display
|
|
19
|
+
# - system() output streaming
|
|
20
|
+
|
|
21
|
+
require_relative "../lib/taski"
|
|
22
|
+
|
|
23
|
+
# Configuration section with multiple implementations
|
|
24
|
+
class DatabaseSection < Taski::Section
|
|
25
|
+
interfaces :connection_string
|
|
26
|
+
|
|
27
|
+
def impl
|
|
28
|
+
(ENV["USE_PROD_DB"] == "1") ? ProductionDB : DevelopmentDB
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class ProductionDB < Taski::Task
|
|
32
|
+
def run
|
|
33
|
+
puts "Connecting to production database..."
|
|
34
|
+
sleep(0.4)
|
|
35
|
+
@connection_string = "postgresql://prod-server:5432/myapp"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class DevelopmentDB < Taski::Task
|
|
40
|
+
def run
|
|
41
|
+
puts "Connecting to development database..."
|
|
42
|
+
sleep(0.3)
|
|
43
|
+
@connection_string = "postgresql://localhost:5432/myapp_dev"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Parallel download tasks (executed concurrently)
|
|
49
|
+
class DownloadLayer1 < Taski::Task
|
|
50
|
+
exports :layer1_data
|
|
51
|
+
|
|
52
|
+
def run
|
|
53
|
+
puts "Downloading base image..."
|
|
54
|
+
sleep(0.8)
|
|
55
|
+
puts "Base image complete"
|
|
56
|
+
@layer1_data = "Layer 1 (base)"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class DownloadLayer2 < Taski::Task
|
|
61
|
+
exports :layer2_data
|
|
62
|
+
|
|
63
|
+
def run
|
|
64
|
+
puts "Downloading dependencies..."
|
|
65
|
+
sleep(1.2)
|
|
66
|
+
puts "Dependencies complete"
|
|
67
|
+
@layer2_data = "Layer 2 (deps)"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class DownloadLayer3 < Taski::Task
|
|
72
|
+
exports :layer3_data
|
|
73
|
+
|
|
74
|
+
def run
|
|
75
|
+
puts "Downloading application..."
|
|
76
|
+
sleep(0.4)
|
|
77
|
+
puts "Application complete"
|
|
78
|
+
@layer3_data = "Layer 3 (app)"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Task that depends on all downloads (waits for parallel completion)
|
|
83
|
+
class ExtractLayers < Taski::Task
|
|
84
|
+
exports :extracted_data
|
|
85
|
+
|
|
86
|
+
def run
|
|
87
|
+
layer1 = DownloadLayer1.layer1_data
|
|
88
|
+
layer2 = DownloadLayer2.layer2_data
|
|
89
|
+
layer3 = DownloadLayer3.layer3_data
|
|
90
|
+
|
|
91
|
+
puts "Extracting layers..."
|
|
92
|
+
sleep(0.3)
|
|
93
|
+
@extracted_data = [layer1, layer2, layer3]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Task demonstrating system() output capture
|
|
98
|
+
class RunSystemCommand < Taski::Task
|
|
99
|
+
exports :command_result
|
|
100
|
+
|
|
101
|
+
def run
|
|
102
|
+
puts "Running system command..."
|
|
103
|
+
@command_result = system("echo 'Step 1: Preparing...' && sleep 0.2 && echo 'Step 2: Processing...' && sleep 0.2 && echo 'Step 3: Done'")
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Final task combining all dependencies
|
|
108
|
+
class BuildApplication < Taski::Task
|
|
109
|
+
exports :result
|
|
110
|
+
|
|
111
|
+
def run
|
|
112
|
+
db = DatabaseSection.connection_string
|
|
113
|
+
layers = ExtractLayers.extracted_data
|
|
114
|
+
RunSystemCommand.command_result
|
|
115
|
+
|
|
116
|
+
puts "Building application..."
|
|
117
|
+
sleep(0.3)
|
|
118
|
+
puts "Finalizing build..."
|
|
119
|
+
sleep(0.2)
|
|
120
|
+
|
|
121
|
+
@result = {
|
|
122
|
+
database: db,
|
|
123
|
+
layers: layers,
|
|
124
|
+
status: "success"
|
|
125
|
+
}
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Main execution
|
|
130
|
+
puts "Taski Progress Display Demo"
|
|
131
|
+
puts "=" * 50
|
|
132
|
+
puts "Progress mode: #{Taski.progress_mode || "tree (default)"}"
|
|
133
|
+
puts
|
|
134
|
+
|
|
135
|
+
puts "Task Tree Structure:"
|
|
136
|
+
puts "-" * 50
|
|
137
|
+
puts BuildApplication.tree
|
|
138
|
+
puts "-" * 50
|
|
139
|
+
puts
|
|
140
|
+
|
|
141
|
+
# Reset for fresh execution
|
|
142
|
+
BuildApplication.reset!
|
|
143
|
+
|
|
144
|
+
# Execute (progress display is automatic)
|
|
145
|
+
result = BuildApplication.result
|
|
146
|
+
|
|
147
|
+
puts
|
|
148
|
+
puts "=" * 50
|
|
149
|
+
puts "Execution completed!"
|
|
150
|
+
puts "Result: #{result.inspect}"
|
|
151
|
+
puts
|
|
152
|
+
puts "Try different modes:"
|
|
153
|
+
puts " TASKI_PROGRESS_MODE=simple ruby examples/progress_demo.rb"
|
|
154
|
+
puts " TASKI_PROGRESS_DISABLE=1 ruby examples/progress_demo.rb"
|
|
@@ -85,6 +85,7 @@ module Taski
|
|
|
85
85
|
@root_task_class = nil
|
|
86
86
|
@output_capture = nil
|
|
87
87
|
@start_time = nil
|
|
88
|
+
@message_queue = []
|
|
88
89
|
end
|
|
89
90
|
|
|
90
91
|
# Set the output capture for getting task output
|
|
@@ -199,6 +200,14 @@ module Taski
|
|
|
199
200
|
return unless should_stop
|
|
200
201
|
|
|
201
202
|
on_stop
|
|
203
|
+
flush_queued_messages
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Queue a message to be displayed after progress display stops.
|
|
207
|
+
# Thread-safe for concurrent task execution.
|
|
208
|
+
# @param text [String] The message text to queue
|
|
209
|
+
def queue_message(text)
|
|
210
|
+
@monitor.synchronize { @message_queue << text }
|
|
202
211
|
end
|
|
203
212
|
|
|
204
213
|
protected
|
|
@@ -283,6 +292,13 @@ module Taski
|
|
|
283
292
|
|
|
284
293
|
private
|
|
285
294
|
|
|
295
|
+
# Flush all queued messages to output.
|
|
296
|
+
# Called when progress display stops.
|
|
297
|
+
def flush_queued_messages
|
|
298
|
+
messages = @monitor.synchronize { @message_queue.dup.tap { @message_queue.clear } }
|
|
299
|
+
messages.each { |msg| @output.puts(msg) }
|
|
300
|
+
end
|
|
301
|
+
|
|
286
302
|
# Apply state transition to TaskProgress
|
|
287
303
|
def apply_state_transition(progress, state, duration, error)
|
|
288
304
|
case state
|
|
@@ -81,7 +81,6 @@ module Taski
|
|
|
81
81
|
@output_capture = nil
|
|
82
82
|
@original_stdout = nil
|
|
83
83
|
@runtime_dependencies = {}
|
|
84
|
-
@message_queue = []
|
|
85
84
|
end
|
|
86
85
|
|
|
87
86
|
# Check if output capture is already active.
|
|
@@ -90,23 +89,6 @@ module Taski
|
|
|
90
89
|
@monitor.synchronize { !@output_capture.nil? }
|
|
91
90
|
end
|
|
92
91
|
|
|
93
|
-
# Queue a message to be displayed after execution completes.
|
|
94
|
-
# Thread-safe for access from worker threads.
|
|
95
|
-
#
|
|
96
|
-
# @param text [String] The message text to queue
|
|
97
|
-
def queue_message(text)
|
|
98
|
-
@monitor.synchronize { @message_queue << text }
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Flush all queued messages to the given output.
|
|
102
|
-
# Clears the queue after flushing.
|
|
103
|
-
#
|
|
104
|
-
# @param output [IO] The output stream to write messages to
|
|
105
|
-
def flush_messages(output)
|
|
106
|
-
messages = @monitor.synchronize { @message_queue.dup.tap { @message_queue.clear } }
|
|
107
|
-
messages.each { |msg| output.puts(msg) }
|
|
108
|
-
end
|
|
109
|
-
|
|
110
92
|
# Get the original stdout before output capture was set up.
|
|
111
93
|
# Thread-safe accessor.
|
|
112
94
|
#
|
|
@@ -123,7 +105,7 @@ module Taski
|
|
|
123
105
|
def setup_output_capture(output_io)
|
|
124
106
|
@monitor.synchronize do
|
|
125
107
|
@original_stdout = output_io
|
|
126
|
-
@output_capture = TaskOutputRouter.new(@original_stdout)
|
|
108
|
+
@output_capture = TaskOutputRouter.new(@original_stdout, self)
|
|
127
109
|
@output_capture.start_polling
|
|
128
110
|
$stdout = @output_capture
|
|
129
111
|
end
|
|
@@ -321,8 +303,7 @@ module Taski
|
|
|
321
303
|
dispatch(:start)
|
|
322
304
|
end
|
|
323
305
|
|
|
324
|
-
|
|
325
|
-
# Notify registered observers that execution has stopped.
|
|
306
|
+
# Notify observers to stop.
|
|
326
307
|
def notify_stop
|
|
327
308
|
dispatch(:stop)
|
|
328
309
|
end
|
|
@@ -418,17 +418,9 @@ module Taski
|
|
|
418
418
|
ensure
|
|
419
419
|
stop_progress_display
|
|
420
420
|
@saved_output_capture = @execution_context.output_capture
|
|
421
|
-
flush_queued_messages if should_teardown_capture
|
|
422
421
|
teardown_output_capture if should_teardown_capture
|
|
423
422
|
end
|
|
424
423
|
|
|
425
|
-
# Flush queued messages from ExecutionContext to original stdout.
|
|
426
|
-
# Called after progress display stops to show user messages.
|
|
427
|
-
def flush_queued_messages
|
|
428
|
-
output = @execution_context.original_stdout || $stdout
|
|
429
|
-
@execution_context.flush_messages(output)
|
|
430
|
-
end
|
|
431
|
-
|
|
432
424
|
def create_default_execution_context
|
|
433
425
|
context = ExecutionContext.new
|
|
434
426
|
progress = Taski.progress_display
|
|
@@ -49,6 +49,11 @@ module Taski
|
|
|
49
49
|
@tasks[impl_class] ||= TaskProgress.new
|
|
50
50
|
@tasks[impl_class].is_impl_candidate = false
|
|
51
51
|
|
|
52
|
+
# Mark the section itself as completed (it's represented by its impl)
|
|
53
|
+
if @tasks[section_class]
|
|
54
|
+
@tasks[section_class].run_state = :completed
|
|
55
|
+
end
|
|
56
|
+
|
|
52
57
|
# Mark unselected candidates as completed (skipped)
|
|
53
58
|
candidates = @section_candidates[section_class] || []
|
|
54
59
|
candidates.each do |candidate|
|
|
@@ -148,7 +153,8 @@ module Taski
|
|
|
148
153
|
def build_status_line
|
|
149
154
|
running_tasks = @tasks.select { |_, p| p.run_state == :running }
|
|
150
155
|
cleaning_tasks = @tasks.select { |_, p| p.clean_state == :cleaning }
|
|
151
|
-
|
|
156
|
+
# Count both completed and failed tasks as "done"
|
|
157
|
+
done = @tasks.values.count { |p| p.run_state == :completed || p.run_state == :failed }
|
|
152
158
|
failed = @tasks.values.count { |p| p.run_state == :failed }
|
|
153
159
|
total = @tasks.size
|
|
154
160
|
|
|
@@ -174,7 +180,7 @@ module Taski
|
|
|
174
180
|
# Get last output message if available
|
|
175
181
|
output_suffix = build_output_suffix(running_tasks.keys.first || cleaning_tasks.keys.first)
|
|
176
182
|
|
|
177
|
-
parts = ["#{status_icon} [#{
|
|
183
|
+
parts = ["#{status_icon} [#{done}/#{total}]"]
|
|
178
184
|
parts << task_names if task_names && !task_names.empty?
|
|
179
185
|
parts << "|" << output_suffix if output_suffix
|
|
180
186
|
|
|
@@ -22,9 +22,10 @@ module Taski
|
|
|
22
22
|
READ_BUFFER_SIZE = 4096
|
|
23
23
|
MAX_RECENT_LINES = 30 # Maximum number of recent lines to keep per task
|
|
24
24
|
|
|
25
|
-
def initialize(original_stdout)
|
|
25
|
+
def initialize(original_stdout, execution_context = nil)
|
|
26
26
|
super()
|
|
27
27
|
@original = original_stdout
|
|
28
|
+
@execution_context = execution_context
|
|
28
29
|
@pipes = {} # task_class => TaskOutputPipe
|
|
29
30
|
@thread_map = {} # Thread => task_class
|
|
30
31
|
@recent_lines = {} # task_class => Array<String>
|
data/lib/taski/version.rb
CHANGED
data/lib/taski.rb
CHANGED
|
@@ -162,9 +162,9 @@ module Taski
|
|
|
162
162
|
# @param text [String] The message text to display
|
|
163
163
|
def self.message(text)
|
|
164
164
|
@message_monitor.synchronize do
|
|
165
|
-
|
|
166
|
-
if
|
|
167
|
-
|
|
165
|
+
progress = progress_display
|
|
166
|
+
if progress&.respond_to?(:queue_message)
|
|
167
|
+
progress.queue_message(text)
|
|
168
168
|
else
|
|
169
169
|
$stdout.puts(text)
|
|
170
170
|
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.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ahogappa
|
|
@@ -59,18 +59,12 @@ files:
|
|
|
59
59
|
- examples/README.md
|
|
60
60
|
- examples/args_demo.rb
|
|
61
61
|
- examples/clean_demo.rb
|
|
62
|
-
- examples/data_pipeline_demo.rb
|
|
63
62
|
- examples/group_demo.rb
|
|
64
|
-
- examples/large_tree_demo.rb
|
|
65
63
|
- examples/message_demo.rb
|
|
66
|
-
- examples/
|
|
67
|
-
- examples/parallel_progress_demo.rb
|
|
64
|
+
- examples/progress_demo.rb
|
|
68
65
|
- examples/quick_start.rb
|
|
69
66
|
- examples/reexecution_demo.rb
|
|
70
67
|
- examples/section_demo.rb
|
|
71
|
-
- examples/simple_progress_demo.rb
|
|
72
|
-
- examples/system_call_demo.rb
|
|
73
|
-
- examples/tree_progress_demo.rb
|
|
74
68
|
- lib/taski.rb
|
|
75
69
|
- lib/taski/args.rb
|
|
76
70
|
- lib/taski/env.rb
|