taski 0.4.2 → 0.5.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/README.md +12 -13
- data/Steepfile +1 -0
- data/examples/README.md +3 -3
- data/examples/data_pipeline_demo.rb +3 -3
- data/examples/nested_section_demo.rb +161 -0
- data/examples/parallel_progress_demo.rb +1 -1
- data/examples/section_progress_demo.rb +78 -0
- data/examples/tree_progress_demo.rb +164 -0
- data/lib/taski/execution/executor.rb +247 -0
- data/lib/taski/execution/registry.rb +9 -1
- data/lib/taski/execution/task_wrapper.rb +126 -147
- data/lib/taski/execution/tree_progress_display.rb +506 -0
- data/lib/taski/section.rb +10 -0
- data/lib/taski/static_analysis/analyzer.rb +4 -2
- data/lib/taski/static_analysis/visitor.rb +86 -5
- data/lib/taski/task.rb +11 -94
- data/lib/taski/version.rb +1 -1
- data/lib/taski.rb +10 -6
- data/sig/taski.rbs +127 -64
- metadata +6 -3
- data/lib/taski/execution/coordinator.rb +0 -63
- data/lib/taski/execution/parallel_progress_display.rb +0 -201
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: afd6114f6d0814be687181ddd8e0acfa45af1d1064f14247e2864be53c3103f0
|
|
4
|
+
data.tar.gz: 5b76552b037943f8b9555f01eb6b98d5a515be95b8f75e63f6f42314cf388294
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c37d3650e3a1af652e469bad4627964fa62763ad7acc93e54b07bdaa577777dda65f0e34265d7974209ab3b3ab5f5ef5299d4675f6a8810fcdcd5dcbad19306
|
|
7
|
+
data.tar.gz: f2d5295608ee67c5a2ecebdfb0416f73fe16569534a4f798252cf5bd101bec3c43507e1c0560be102cfb37c44fcdf603ff2a7cf9a6b0afdfb9b74c3624ff7553
|
data/README.md
CHANGED
|
@@ -162,27 +162,26 @@ RandomTask.reset!
|
|
|
162
162
|
|
|
163
163
|
### Progress Display
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
TASKI_FORCE_PROGRESS=1 ruby your_script.rb
|
|
169
|
-
```
|
|
165
|
+
Tree-based progress visualization is enabled by default:
|
|
170
166
|
|
|
171
167
|
```
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
✅
|
|
175
|
-
|
|
168
|
+
WebServer (Task)
|
|
169
|
+
├── ⠋ Config (Task) ...
|
|
170
|
+
│ ├── ✅ Database (Task) 45.2ms
|
|
171
|
+
│ └── ⠙ Cache (Task) ...
|
|
172
|
+
└── ◻ Server (Task)
|
|
176
173
|
```
|
|
177
174
|
|
|
175
|
+
To disable: `TASKI_PROGRESS_DISABLE=1 ruby your_script.rb`
|
|
176
|
+
|
|
178
177
|
### Tree Visualization
|
|
179
178
|
|
|
180
179
|
```ruby
|
|
181
180
|
puts WebServer.tree
|
|
182
|
-
#
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
181
|
+
# WebServer (Task)
|
|
182
|
+
# └── Config (Task)
|
|
183
|
+
# ├── Database (Task)
|
|
184
|
+
# └── Cache (Task)
|
|
186
185
|
```
|
|
187
186
|
|
|
188
187
|
## Development
|
data/Steepfile
CHANGED
data/examples/README.md
CHANGED
|
@@ -87,7 +87,7 @@ ruby examples/data_pipeline_demo.rb
|
|
|
87
87
|
Real-time progress visualization during parallel execution.
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
|
-
|
|
90
|
+
ruby examples/parallel_progress_demo.rb
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
**Covers:**
|
|
@@ -114,8 +114,8 @@ TASKI_FORCE_PROGRESS=1 ruby examples/parallel_progress_demo.rb
|
|
|
114
114
|
# Run each example
|
|
115
115
|
for f in examples/*.rb; do echo "=== $f ===" && ruby "$f" && echo; done
|
|
116
116
|
|
|
117
|
-
#
|
|
118
|
-
|
|
117
|
+
# Disable progress display if needed
|
|
118
|
+
TASKI_PROGRESS_DISABLE=1 ruby examples/parallel_progress_demo.rb
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
## Next Steps
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# - Data transformation and aggregation
|
|
10
10
|
#
|
|
11
11
|
# Run: ruby examples/data_pipeline_demo.rb
|
|
12
|
-
#
|
|
12
|
+
# Disable progress: TASKI_PROGRESS_DISABLE=1 ruby examples/data_pipeline_demo.rb
|
|
13
13
|
|
|
14
14
|
require_relative "../lib/taski"
|
|
15
15
|
|
|
@@ -227,5 +227,5 @@ puts "\nKey concepts demonstrated:"
|
|
|
227
227
|
puts " - DataSourceSection: Switch between production/test data"
|
|
228
228
|
puts " - ReportFormatSection: Switch output format (text/JSON)"
|
|
229
229
|
puts " - Parallel execution of independent transforms"
|
|
230
|
-
puts "\
|
|
231
|
-
puts "
|
|
230
|
+
puts "\nTo disable progress display:"
|
|
231
|
+
puts " TASKI_PROGRESS_DISABLE=1 ruby examples/data_pipeline_demo.rb"
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/taski"
|
|
5
|
+
|
|
6
|
+
# Demo for nested Sections (Section inside Section)
|
|
7
|
+
# Run with: ruby examples/nested_section_demo.rb
|
|
8
|
+
|
|
9
|
+
# Configuration loader task - determines which storage to use
|
|
10
|
+
class StorageConfig < Taski::Task
|
|
11
|
+
exports :use_s3
|
|
12
|
+
|
|
13
|
+
def run
|
|
14
|
+
puts "Loading storage configuration..."
|
|
15
|
+
sleep(0.4)
|
|
16
|
+
puts "Checking cloud credentials..."
|
|
17
|
+
sleep(0.3)
|
|
18
|
+
puts "Validating storage policies..."
|
|
19
|
+
sleep(0.3)
|
|
20
|
+
# Simulate config loading - use local storage by default
|
|
21
|
+
@use_s3 = ENV["USE_S3"] == "1"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Inner Section: Storage backend selection (depends on StorageConfig)
|
|
26
|
+
class StorageSection < Taski::Section
|
|
27
|
+
interfaces :storage_client
|
|
28
|
+
|
|
29
|
+
def impl
|
|
30
|
+
# Use config task result to decide implementation
|
|
31
|
+
if StorageConfig.use_s3
|
|
32
|
+
S3Storage
|
|
33
|
+
else
|
|
34
|
+
LocalStorage
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class S3Storage < Taski::Task
|
|
39
|
+
def run
|
|
40
|
+
puts "Connecting to S3..."
|
|
41
|
+
sleep(1.0)
|
|
42
|
+
@storage_client = "s3://bucket/data"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class LocalStorage < Taski::Task
|
|
47
|
+
def run
|
|
48
|
+
puts "Initializing local filesystem..."
|
|
49
|
+
sleep(0.5)
|
|
50
|
+
puts "Mounting volumes..."
|
|
51
|
+
sleep(0.5)
|
|
52
|
+
puts "Local storage ready"
|
|
53
|
+
sleep(0.3)
|
|
54
|
+
@storage_client = "/var/data"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Database configuration loader - determines which database to use
|
|
60
|
+
class DatabaseConfig < Taski::Task
|
|
61
|
+
exports :use_prod
|
|
62
|
+
|
|
63
|
+
def run
|
|
64
|
+
puts "Loading database configuration..."
|
|
65
|
+
sleep(0.3)
|
|
66
|
+
puts "Checking environment variables..."
|
|
67
|
+
sleep(0.3)
|
|
68
|
+
puts "Resolving database endpoints..."
|
|
69
|
+
sleep(0.4)
|
|
70
|
+
# Simulate config loading - use dev database by default
|
|
71
|
+
@use_prod = ENV["USE_PROD_DB"] == "1"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Outer Section: Database selection (depends on Storage and DatabaseConfig)
|
|
76
|
+
class DatabaseSection < Taski::Section
|
|
77
|
+
interfaces :connection_string
|
|
78
|
+
|
|
79
|
+
def impl
|
|
80
|
+
# Use config task result to decide implementation
|
|
81
|
+
if DatabaseConfig.use_prod
|
|
82
|
+
ProductionDB
|
|
83
|
+
else
|
|
84
|
+
DevelopmentDB
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class ProductionDB < Taski::Task
|
|
89
|
+
def run
|
|
90
|
+
# Production DB also needs storage for backups
|
|
91
|
+
storage = StorageSection.storage_client
|
|
92
|
+
puts "Connecting to production database (backup: #{storage})..."
|
|
93
|
+
sleep(0.8)
|
|
94
|
+
@connection_string = "postgresql://prod-server:5432/myapp"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class DevelopmentDB < Taski::Task
|
|
99
|
+
def run
|
|
100
|
+
# Dev DB uses storage for test data
|
|
101
|
+
storage = StorageSection.storage_client
|
|
102
|
+
puts "Initializing dev database connection..."
|
|
103
|
+
sleep(0.4)
|
|
104
|
+
puts "Loading test fixtures from #{storage}..."
|
|
105
|
+
sleep(0.5)
|
|
106
|
+
puts "Dev database ready"
|
|
107
|
+
sleep(0.3)
|
|
108
|
+
@connection_string = "postgresql://localhost:5432/myapp_dev"
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Task that uses the database
|
|
114
|
+
class FetchData < Taski::Task
|
|
115
|
+
exports :data
|
|
116
|
+
|
|
117
|
+
def run
|
|
118
|
+
db = DatabaseSection.connection_string
|
|
119
|
+
puts "Connecting to #{db}..."
|
|
120
|
+
sleep(0.3)
|
|
121
|
+
puts "Querying records..."
|
|
122
|
+
sleep(0.4)
|
|
123
|
+
puts "Processing results..."
|
|
124
|
+
sleep(0.3)
|
|
125
|
+
@data = ["item1", "item2", "item3"]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Main application task
|
|
130
|
+
class Application < Taski::Task
|
|
131
|
+
exports :result
|
|
132
|
+
|
|
133
|
+
def run
|
|
134
|
+
data = FetchData.data
|
|
135
|
+
puts "Validating #{data.size} items..."
|
|
136
|
+
sleep(0.3)
|
|
137
|
+
puts "Transforming data..."
|
|
138
|
+
sleep(0.4)
|
|
139
|
+
puts "Finalizing results..."
|
|
140
|
+
sleep(0.3)
|
|
141
|
+
@result = "Processed: #{data.join(", ")}"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Show tree structure before execution
|
|
146
|
+
puts "Nested Section Tree Structure:"
|
|
147
|
+
puts "=" * 70
|
|
148
|
+
puts Application.tree
|
|
149
|
+
puts "=" * 70
|
|
150
|
+
puts
|
|
151
|
+
|
|
152
|
+
# Reset for execution
|
|
153
|
+
Application.reset!
|
|
154
|
+
|
|
155
|
+
# Execute
|
|
156
|
+
result = Application.result
|
|
157
|
+
|
|
158
|
+
puts "\n"
|
|
159
|
+
puts "=" * 70
|
|
160
|
+
puts "Execution completed!"
|
|
161
|
+
puts "Result: #{result}"
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
require_relative "../lib/taski"
|
|
5
5
|
|
|
6
6
|
# Demo tasks that simulate parallel execution with progress display
|
|
7
|
-
# Run with:
|
|
7
|
+
# Run with: ruby examples/parallel_progress_demo.rb
|
|
8
8
|
|
|
9
9
|
class DownloadLayer1 < Taski::Task
|
|
10
10
|
exports :layer1_data
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/taski"
|
|
5
|
+
|
|
6
|
+
# Demo for tree-based progress display with Section
|
|
7
|
+
# Run with: ruby examples/section_progress_demo.rb
|
|
8
|
+
|
|
9
|
+
# Database Section with multiple impl candidates
|
|
10
|
+
class DatabaseSection < Taski::Section
|
|
11
|
+
interfaces :connection_string
|
|
12
|
+
|
|
13
|
+
def impl
|
|
14
|
+
if ENV["USE_PROD_DB"] == "1"
|
|
15
|
+
ProductionDB
|
|
16
|
+
else
|
|
17
|
+
DevelopmentDB
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ProductionDB < Taski::Task
|
|
22
|
+
def run
|
|
23
|
+
puts "Connecting to production database..."
|
|
24
|
+
sleep(0.3)
|
|
25
|
+
@connection_string = "postgresql://prod-server:5432/myapp"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class DevelopmentDB < Taski::Task
|
|
30
|
+
def run
|
|
31
|
+
puts "Connecting to development database..."
|
|
32
|
+
sleep(0.2)
|
|
33
|
+
@connection_string = "postgresql://localhost:5432/myapp_dev"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Simple task that uses the database
|
|
39
|
+
class FetchData < Taski::Task
|
|
40
|
+
exports :data
|
|
41
|
+
|
|
42
|
+
def run
|
|
43
|
+
db = DatabaseSection.connection_string
|
|
44
|
+
puts "Fetching data from #{db}..."
|
|
45
|
+
sleep(0.3)
|
|
46
|
+
@data = ["item1", "item2", "item3"]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Main application task
|
|
51
|
+
class Application < Taski::Task
|
|
52
|
+
exports :result
|
|
53
|
+
|
|
54
|
+
def run
|
|
55
|
+
data = FetchData.data
|
|
56
|
+
puts "Processing #{data.size} items..."
|
|
57
|
+
sleep(0.2)
|
|
58
|
+
@result = "Processed: #{data.join(", ")}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Show tree structure before execution
|
|
63
|
+
puts "Task Tree Structure:"
|
|
64
|
+
puts "=" * 60
|
|
65
|
+
puts Application.tree
|
|
66
|
+
puts "=" * 60
|
|
67
|
+
puts
|
|
68
|
+
|
|
69
|
+
# Reset for execution
|
|
70
|
+
Application.reset!
|
|
71
|
+
|
|
72
|
+
# Execute
|
|
73
|
+
result = Application.result
|
|
74
|
+
|
|
75
|
+
puts "\n"
|
|
76
|
+
puts "=" * 60
|
|
77
|
+
puts "Execution completed!"
|
|
78
|
+
puts "Result: #{result}"
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/taski"
|
|
5
|
+
|
|
6
|
+
# Demo for tree-based progress display
|
|
7
|
+
# Run with: ruby examples/tree_progress_demo.rb
|
|
8
|
+
|
|
9
|
+
# Database configuration section with multiple impl candidates
|
|
10
|
+
class DatabaseSection < Taski::Section
|
|
11
|
+
interfaces :connection_string
|
|
12
|
+
|
|
13
|
+
def impl
|
|
14
|
+
if ENV["USE_PROD_DB"] == "1"
|
|
15
|
+
ProductionDB
|
|
16
|
+
else
|
|
17
|
+
DevelopmentDB
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ProductionDB < Taski::Task
|
|
22
|
+
def run
|
|
23
|
+
puts "Connecting to production database..."
|
|
24
|
+
sleep(0.5)
|
|
25
|
+
puts "Production DB connected"
|
|
26
|
+
@connection_string = "postgresql://prod-server:5432/myapp"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class DevelopmentDB < Taski::Task
|
|
31
|
+
def run
|
|
32
|
+
puts "Connecting to development database..."
|
|
33
|
+
sleep(0.3)
|
|
34
|
+
puts "Development DB connected"
|
|
35
|
+
@connection_string = "postgresql://localhost:5432/myapp_dev"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# API section with multiple impl candidates
|
|
41
|
+
class ApiSection < Taski::Section
|
|
42
|
+
interfaces :base_url
|
|
43
|
+
|
|
44
|
+
def impl
|
|
45
|
+
if ENV["USE_STAGING_API"] == "1"
|
|
46
|
+
StagingApi
|
|
47
|
+
else
|
|
48
|
+
ProductionApi
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class ProductionApi < Taski::Task
|
|
53
|
+
def run
|
|
54
|
+
puts "Initializing production API..."
|
|
55
|
+
sleep(0.4)
|
|
56
|
+
@base_url = "https://api.example.com"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class StagingApi < Taski::Task
|
|
61
|
+
def run
|
|
62
|
+
puts "Initializing staging API..."
|
|
63
|
+
sleep(0.2)
|
|
64
|
+
@base_url = "https://staging.api.example.com"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Task with stdout output
|
|
70
|
+
class FetchUserData < Taski::Task
|
|
71
|
+
exports :users
|
|
72
|
+
|
|
73
|
+
def run
|
|
74
|
+
puts "Fetching users from database..."
|
|
75
|
+
sleep(0.3)
|
|
76
|
+
puts "Found 100 users"
|
|
77
|
+
sleep(0.2)
|
|
78
|
+
puts "Processing user records..."
|
|
79
|
+
sleep(0.3)
|
|
80
|
+
puts "User data ready"
|
|
81
|
+
@users = ["Alice", "Bob", "Charlie"]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class FetchProductData < Taski::Task
|
|
86
|
+
exports :products
|
|
87
|
+
|
|
88
|
+
def run
|
|
89
|
+
puts "Loading product catalog..."
|
|
90
|
+
sleep(0.4)
|
|
91
|
+
puts "Fetched 50 products"
|
|
92
|
+
sleep(0.2)
|
|
93
|
+
puts "Indexing products..."
|
|
94
|
+
sleep(0.3)
|
|
95
|
+
@products = ["Widget", "Gadget", "Thing"]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class BuildReport < Taski::Task
|
|
100
|
+
exports :report
|
|
101
|
+
|
|
102
|
+
def run
|
|
103
|
+
db = DatabaseSection.connection_string
|
|
104
|
+
api = ApiSection.base_url
|
|
105
|
+
users = FetchUserData.users
|
|
106
|
+
products = FetchProductData.products
|
|
107
|
+
|
|
108
|
+
puts "Building report..."
|
|
109
|
+
sleep(0.2)
|
|
110
|
+
puts "Aggregating data from #{users.size} users..."
|
|
111
|
+
sleep(0.3)
|
|
112
|
+
puts "Processing #{products.size} products..."
|
|
113
|
+
sleep(0.2)
|
|
114
|
+
puts "Report generated successfully"
|
|
115
|
+
|
|
116
|
+
@report = {
|
|
117
|
+
database: db,
|
|
118
|
+
api: api,
|
|
119
|
+
user_count: users.size,
|
|
120
|
+
product_count: products.size
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
class SendNotification < Taski::Task
|
|
126
|
+
exports :notification_sent
|
|
127
|
+
|
|
128
|
+
def run
|
|
129
|
+
BuildReport.report
|
|
130
|
+
puts "Sending notification..."
|
|
131
|
+
sleep(0.2)
|
|
132
|
+
puts "Email sent to admin@example.com"
|
|
133
|
+
@notification_sent = true
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
class Application < Taski::Task
|
|
138
|
+
exports :status
|
|
139
|
+
|
|
140
|
+
def run
|
|
141
|
+
notification = SendNotification.notification_sent
|
|
142
|
+
puts "Application startup complete"
|
|
143
|
+
@status = notification ? "success" : "failed"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Show tree structure before execution
|
|
148
|
+
puts "Task Tree Structure:"
|
|
149
|
+
puts "=" * 60
|
|
150
|
+
puts Application.tree
|
|
151
|
+
puts "=" * 60
|
|
152
|
+
puts
|
|
153
|
+
|
|
154
|
+
# Reset for execution
|
|
155
|
+
Application.reset!
|
|
156
|
+
|
|
157
|
+
# Execute with tree progress display (start/stop handled automatically by Executor)
|
|
158
|
+
result = Application.status
|
|
159
|
+
|
|
160
|
+
puts "\n"
|
|
161
|
+
puts "=" * 60
|
|
162
|
+
puts "Execution completed!"
|
|
163
|
+
puts "Status: #{result}"
|
|
164
|
+
puts "Report: #{BuildReport.report.inspect}"
|