taski 0.3.0 → 0.4.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/.gem_rbs_collection/ast/2.4/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/ast/2.4/ast.rbs +73 -0
- data/.gem_rbs_collection/minitest/5.25/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/abstract_reporter.rbs +52 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/assertion.rbs +17 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/assertions.rbs +590 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/backtrace_filter.rbs +23 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/bench_spec.rbs +102 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/benchmark.rbs +259 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/composite_reporter.rbs +25 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/compress.rbs +13 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/error_on_warning.rbs +3 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/expectation.rbs +2 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/expectations.rbs +21 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/guard.rbs +64 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/mock.rbs +64 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/parallel/executor.rbs +46 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/parallel/test/class_methods.rbs +5 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/parallel/test.rbs +3 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/parallel.rbs +2 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/pride_io.rbs +62 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/pride_lol.rbs +19 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/progress_reporter.rbs +11 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/reportable.rbs +53 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/reporter.rbs +5 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/result.rbs +28 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/runnable.rbs +163 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/skip.rbs +6 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/spec/dsl/instance_methods.rbs +48 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/spec/dsl.rbs +129 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/spec.rbs +11 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/statistics_reporter.rbs +81 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/summary_reporter.rbs +18 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/test/lifecycle_hooks.rbs +92 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/test.rbs +69 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/unexpected_error.rbs +12 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/unexpected_warning.rbs +6 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/unit/test_case.rbs +3 -0
- data/.gem_rbs_collection/minitest/5.25/minitest/unit.rbs +4 -0
- data/.gem_rbs_collection/minitest/5.25/minitest.rbs +115 -0
- data/.gem_rbs_collection/parallel/1.20/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/parallel/1.20/parallel.rbs +86 -0
- data/.gem_rbs_collection/parser/3.2/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/parser/3.2/manifest.yaml +7 -0
- data/.gem_rbs_collection/parser/3.2/parser.rbs +193 -0
- data/.gem_rbs_collection/parser/3.2/polyfill.rbs +4 -0
- data/.gem_rbs_collection/rainbow/3.0/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/rainbow/3.0/global.rbs +7 -0
- data/.gem_rbs_collection/rainbow/3.0/presenter.rbs +209 -0
- data/.gem_rbs_collection/rainbow/3.0/rainbow.rbs +5 -0
- data/.gem_rbs_collection/rake/13.0/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/rake/13.0/manifest.yaml +2 -0
- data/.gem_rbs_collection/rake/13.0/rake.rbs +39 -0
- data/.gem_rbs_collection/regexp_parser/2.8/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/regexp_parser/2.8/regexp_parser.rbs +17 -0
- data/.gem_rbs_collection/rubocop/1.57/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/rubocop/1.57/rubocop.rbs +129 -0
- data/.gem_rbs_collection/rubocop-ast/1.30/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/rubocop-ast/1.30/rubocop-ast.rbs +771 -0
- data/.gem_rbs_collection/simplecov/0.22/.rbs_meta.yaml +9 -0
- data/.gem_rbs_collection/simplecov/0.22/simplecov.rbs +54 -0
- data/README.md +137 -248
- data/Steepfile +19 -0
- data/docs/advanced-features.md +625 -0
- data/docs/api-guide.md +509 -0
- data/docs/error-handling.md +684 -0
- data/examples/README.md +95 -42
- data/examples/context_demo.rb +112 -0
- data/examples/data_pipeline_demo.rb +231 -0
- data/examples/parallel_progress_demo.rb +72 -0
- data/examples/quick_start.rb +4 -4
- data/examples/reexecution_demo.rb +127 -0
- data/examples/{section_configuration.rb → section_demo.rb} +49 -66
- data/lib/taski/context.rb +52 -0
- data/lib/taski/execution/coordinator.rb +63 -0
- data/lib/taski/execution/parallel_progress_display.rb +201 -0
- data/lib/taski/execution/registry.rb +72 -0
- data/lib/taski/execution/task_wrapper.rb +255 -0
- data/lib/taski/section.rb +26 -250
- data/lib/taski/static_analysis/analyzer.rb +34 -0
- data/lib/taski/static_analysis/dependency_graph.rb +90 -0
- data/lib/taski/static_analysis/visitor.rb +114 -0
- data/lib/taski/task.rb +173 -0
- data/lib/taski/version.rb +1 -1
- data/lib/taski.rb +45 -39
- data/rbs_collection.lock.yaml +116 -0
- data/rbs_collection.yaml +19 -0
- data/sig/taski.rbs +269 -62
- metadata +97 -32
- data/examples/advanced_patterns.rb +0 -119
- data/examples/progress_demo.rb +0 -166
- data/examples/tree_demo.rb +0 -205
- data/lib/taski/dependency_analyzer.rb +0 -231
- data/lib/taski/exceptions.rb +0 -17
- data/lib/taski/logger.rb +0 -158
- data/lib/taski/logging/formatter_factory.rb +0 -34
- data/lib/taski/logging/formatter_interface.rb +0 -19
- data/lib/taski/logging/json_formatter.rb +0 -26
- data/lib/taski/logging/simple_formatter.rb +0 -16
- data/lib/taski/logging/structured_formatter.rb +0 -44
- data/lib/taski/progress/display_colors.rb +0 -17
- data/lib/taski/progress/display_manager.rb +0 -115
- data/lib/taski/progress/output_capture.rb +0 -105
- data/lib/taski/progress/spinner_animation.rb +0 -46
- data/lib/taski/progress/task_formatter.rb +0 -25
- data/lib/taski/progress/task_status.rb +0 -38
- data/lib/taski/progress/terminal_controller.rb +0 -35
- data/lib/taski/progress_display.rb +0 -59
- data/lib/taski/reference.rb +0 -40
- data/lib/taski/task/base.rb +0 -90
- data/lib/taski/task/define_api.rb +0 -154
- data/lib/taski/task/dependency_resolver.rb +0 -73
- data/lib/taski/task/exports_api.rb +0 -31
- data/lib/taski/task/instance_management.rb +0 -203
- data/lib/taski/tree_colors.rb +0 -91
- data/lib/taski/utils/dependency_resolver_helper.rb +0 -85
- data/lib/taski/utils/tree_display_helper.rb +0 -71
- data/lib/taski/utils.rb +0 -107
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module SimpleCov
|
|
2
|
+
extend Configuration
|
|
3
|
+
|
|
4
|
+
VERSION: String
|
|
5
|
+
|
|
6
|
+
def self.collate: (Array[String] result_filenames) -> void
|
|
7
|
+
|
|
8
|
+
def self.start: (?(String | Symbol | nil) profile) ?{ [self: Configuration] -> void } -> void
|
|
9
|
+
|
|
10
|
+
module Configuration
|
|
11
|
+
type filter = String
|
|
12
|
+
| Regexp
|
|
13
|
+
| Filter[untyped]
|
|
14
|
+
| ^(SourceFile source_file) -> boolish
|
|
15
|
+
| Array[filter]
|
|
16
|
+
|
|
17
|
+
type criterion = :line | :branch
|
|
18
|
+
|
|
19
|
+
def add_filter: (filter filter_argument) -> void
|
|
20
|
+
| { (SourceFile source_file) -> boolish } -> void
|
|
21
|
+
|
|
22
|
+
def add_group: (String group_name, filter filter_argument) -> untyped
|
|
23
|
+
| (String group_name) { (SourceFile source_file) -> boolish } -> void
|
|
24
|
+
|
|
25
|
+
def command_name: (String name) -> void
|
|
26
|
+
|
|
27
|
+
def enable_coverage: (criterion criterion) -> void
|
|
28
|
+
|
|
29
|
+
def enable_coverage_for_eval: () -> void
|
|
30
|
+
|
|
31
|
+
def filters: () -> Array[Filter[untyped]]
|
|
32
|
+
|
|
33
|
+
def primary_coverage: (criterion criterion) -> void
|
|
34
|
+
|
|
35
|
+
def root: (?String? root) -> String?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class SourceFile
|
|
39
|
+
attr_reader filename: String?
|
|
40
|
+
|
|
41
|
+
def lines: () -> Array[Line]
|
|
42
|
+
|
|
43
|
+
class Line
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class Filter[T]
|
|
48
|
+
attr_reader filter_argument: T
|
|
49
|
+
|
|
50
|
+
def initialize: (T filter_argument) -> void
|
|
51
|
+
|
|
52
|
+
def matches?: (SourceFile source_file) -> boolish
|
|
53
|
+
end
|
|
54
|
+
end
|
data/README.md
CHANGED
|
@@ -6,333 +6,220 @@
|
|
|
6
6
|
|
|
7
7
|
> **🚧 Development Status:** Taski is currently under active development. Not yet recommended for production use.
|
|
8
8
|
|
|
9
|
-
**Taski** is a Ruby framework for building task dependency graphs with automatic resolution and
|
|
9
|
+
**Taski** is a Ruby framework for building task dependency graphs with automatic resolution and **parallel execution**.
|
|
10
10
|
|
|
11
11
|
> **Name Origin**: "Taski" comes from the Japanese word "襷" (tasuki), a sash used in relay races. Just like how runners pass the sash to the next teammate, tasks in Taski pass dependencies to one another in a continuous chain.
|
|
12
12
|
|
|
13
|
+
## Why Taski?
|
|
14
|
+
|
|
15
|
+
Build complex workflows by defining tasks and their dependencies - Taski automatically resolves execution order and executes them in parallel.
|
|
16
|
+
|
|
17
|
+
- **Automatic Dependency Resolution**: Dependencies detected via static analysis
|
|
18
|
+
- **Parallel Execution**: Independent tasks run concurrently for maximum performance
|
|
19
|
+
- **Two Simple APIs**: Exports (value sharing) and Section (runtime selection)
|
|
20
|
+
- **Real-time Progress**: Visual feedback with parallel task progress display
|
|
21
|
+
- **Thread-Safe**: Built on Monitor-based synchronization for reliable concurrent execution
|
|
22
|
+
|
|
13
23
|
## 🚀 Quick Start
|
|
14
24
|
|
|
15
25
|
```ruby
|
|
16
26
|
require 'taski'
|
|
17
27
|
|
|
18
|
-
#
|
|
28
|
+
# Define tasks with dependencies
|
|
19
29
|
class DatabaseSetup < Taski::Task
|
|
20
30
|
exports :connection_string
|
|
21
31
|
|
|
22
|
-
def
|
|
32
|
+
def run
|
|
23
33
|
@connection_string = "postgresql://localhost/myapp"
|
|
24
34
|
puts "Database configured"
|
|
25
35
|
end
|
|
26
36
|
end
|
|
27
37
|
|
|
38
|
+
class CacheSetup < Taski::Task
|
|
39
|
+
exports :cache_url
|
|
40
|
+
|
|
41
|
+
def run
|
|
42
|
+
@cache_url = "redis://localhost:6379"
|
|
43
|
+
puts "Cache configured"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
28
47
|
class APIServer < Taski::Task
|
|
29
|
-
def
|
|
48
|
+
def run
|
|
49
|
+
# Dependencies execute automatically and in parallel
|
|
30
50
|
puts "Starting API with #{DatabaseSetup.connection_string}"
|
|
51
|
+
puts "Using cache at #{CacheSetup.cache_url}"
|
|
31
52
|
end
|
|
32
53
|
end
|
|
33
54
|
|
|
34
|
-
|
|
55
|
+
# Run any task - dependencies resolve and execute in parallel
|
|
56
|
+
APIServer.run
|
|
35
57
|
# => Database configured
|
|
58
|
+
# => Cache configured
|
|
36
59
|
# => Starting API with postgresql://localhost/myapp
|
|
60
|
+
# => Using cache at redis://localhost:6379
|
|
37
61
|
```
|
|
38
62
|
|
|
39
|
-
##
|
|
40
|
-
|
|
41
|
-
### Exports API - Static Dependencies
|
|
63
|
+
## Core Concepts
|
|
42
64
|
|
|
43
|
-
|
|
65
|
+
Taski provides two complementary APIs:
|
|
44
66
|
|
|
67
|
+
### 1. Exports API - Value Sharing Between Tasks
|
|
45
68
|
```ruby
|
|
46
|
-
class
|
|
47
|
-
exports :app_name, :
|
|
69
|
+
class Config < Taski::Task
|
|
70
|
+
exports :app_name, :port
|
|
48
71
|
|
|
49
|
-
def
|
|
72
|
+
def run
|
|
50
73
|
@app_name = "MyApp"
|
|
51
|
-
@
|
|
52
|
-
puts "Config loaded: #{@app_name} v#{@version}"
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
class Deployment < Taski::Task
|
|
57
|
-
def build
|
|
58
|
-
@deploy_url = "https://#{ConfigLoader.app_name}.example.com"
|
|
59
|
-
puts "Deploying to #{@deploy_url}"
|
|
74
|
+
@port = 3000
|
|
60
75
|
end
|
|
61
76
|
end
|
|
62
77
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
### Define API - Dynamic Dependencies
|
|
69
|
-
|
|
70
|
-
For dependencies that change based on runtime conditions:
|
|
71
|
-
|
|
72
|
-
```ruby
|
|
73
|
-
class EnvironmentConfig < Taski::Task
|
|
74
|
-
define :database_service, -> {
|
|
75
|
-
case ENV['RAILS_ENV']
|
|
76
|
-
when 'production'
|
|
77
|
-
"production-db.example.com"
|
|
78
|
-
else
|
|
79
|
-
"localhost:5432"
|
|
80
|
-
end
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
def build
|
|
84
|
-
puts "Using database: #{database_service}"
|
|
85
|
-
puts "Environment: #{ENV['RAILS_ENV'] || 'development'}"
|
|
78
|
+
class Server < Taski::Task
|
|
79
|
+
def run
|
|
80
|
+
# Automatically depends on Config task
|
|
81
|
+
puts "Starting #{Config.app_name} on port #{Config.port}"
|
|
86
82
|
end
|
|
87
83
|
end
|
|
88
|
-
|
|
89
|
-
EnvironmentConfig.build
|
|
90
|
-
# => Using database: localhost:5432
|
|
91
|
-
# => Environment: development
|
|
92
|
-
|
|
93
|
-
ENV['RAILS_ENV'] = 'production'
|
|
94
|
-
EnvironmentConfig.reset!
|
|
95
|
-
EnvironmentConfig.build
|
|
96
|
-
# => Using database: production-db.example.com
|
|
97
|
-
# => Environment: production
|
|
98
84
|
```
|
|
99
85
|
|
|
100
|
-
### Section API -
|
|
101
|
-
|
|
102
|
-
For environment-specific implementations with clean interfaces:
|
|
103
|
-
|
|
86
|
+
### 2. Section API - Runtime Implementation Selection
|
|
104
87
|
```ruby
|
|
105
88
|
class DatabaseSection < Taski::Section
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def impl # No 'self' needed!
|
|
109
|
-
ENV['RAILS_ENV'] == 'production' ? Production : Development
|
|
110
|
-
end
|
|
89
|
+
interfaces :host, :port
|
|
111
90
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
91
|
+
# Nested classes automatically inherit interfaces - no exports needed
|
|
92
|
+
class ProductionDB < Taski::Task
|
|
93
|
+
def run
|
|
94
|
+
@host = "prod.example.com"
|
|
115
95
|
@port = 5432
|
|
116
96
|
end
|
|
117
97
|
end
|
|
118
98
|
|
|
119
|
-
class
|
|
120
|
-
def
|
|
99
|
+
class LocalDB < Taski::Task
|
|
100
|
+
def run
|
|
121
101
|
@host = "localhost"
|
|
122
102
|
@port = 5432
|
|
123
103
|
end
|
|
124
104
|
end
|
|
125
105
|
|
|
126
|
-
|
|
106
|
+
def impl
|
|
107
|
+
# Select implementation at runtime
|
|
108
|
+
ENV['RAILS_ENV'] == 'production' ? ProductionDB : LocalDB
|
|
109
|
+
end
|
|
127
110
|
end
|
|
128
111
|
|
|
129
|
-
# Usage is simple - Section works like any Task
|
|
130
112
|
class App < Taski::Task
|
|
131
|
-
def
|
|
132
|
-
|
|
113
|
+
def run
|
|
114
|
+
# Access through Section - implementation selected at runtime
|
|
115
|
+
puts "Connecting to #{DatabaseSection.host}:#{DatabaseSection.port}"
|
|
133
116
|
end
|
|
134
117
|
end
|
|
135
118
|
|
|
136
|
-
App.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
### When to Use Each API
|
|
140
|
-
|
|
141
|
-
- **Define API**: Best for dynamic runtime dependencies. Cannot contain side effects in definition blocks. Dependencies are analyzed at class definition time, not runtime.
|
|
142
|
-
- **Exports API**: Ideal for static dependencies. Supports side effects in build methods.
|
|
143
|
-
- **Section API**: Perfect for abstraction layers where you need different implementations based on runtime conditions while maintaining static analysis capabilities.
|
|
144
|
-
|
|
145
|
-
| Use Case | API | Example |
|
|
146
|
-
|----------|-----|---------|
|
|
147
|
-
| Configuration values | Exports | File paths, settings |
|
|
148
|
-
| Environment-specific logic | Define/Section | Different services per env |
|
|
149
|
-
| Side effects | Exports | Database connections, I/O |
|
|
150
|
-
| Conditional processing | Define | Algorithm selection |
|
|
151
|
-
| Implementation abstraction | Section | Database/API adapters |
|
|
152
|
-
| Multi-environment configs | Section | Dev/Test/Prod settings |
|
|
153
|
-
|
|
154
|
-
**Note**: Define API analyzes dependencies when the class is defined. Conditional dependencies like `ENV['USE_NEW'] ? TaskA : TaskB` will only include the task selected at class definition time, not runtime. Use Section API when you need true runtime selection.
|
|
155
|
-
|
|
156
|
-
## ✨ Key Features
|
|
157
|
-
|
|
158
|
-
- **Automatic Dependency Resolution**: Dependencies detected through static analysis
|
|
159
|
-
- **Thread-Safe**: Safe for concurrent access
|
|
160
|
-
- **Circular Dependency Detection**: Clear error messages with detailed paths
|
|
161
|
-
- **Granular Execution**: Build individual tasks or complete graphs
|
|
162
|
-
- **Memory Management**: Built-in reset mechanisms
|
|
163
|
-
- **Progress Display**: Visual feedback with spinners and output capture
|
|
164
|
-
- **Dependency Tree Visualization**: Visual representation of task relationships
|
|
165
|
-
|
|
166
|
-
### Dependency Tree Visualization
|
|
167
|
-
|
|
168
|
-
Visualize task dependencies with the `tree` method:
|
|
169
|
-
|
|
170
|
-
```ruby
|
|
171
|
-
class Database < Taski::Task
|
|
172
|
-
exports :connection
|
|
173
|
-
def build; @connection = "db-conn"; end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
class Cache < Taski::Task
|
|
177
|
-
exports :redis_url
|
|
178
|
-
def build; @redis_url = "redis://localhost"; end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
class Config < Taski::Task
|
|
182
|
-
exports :settings
|
|
183
|
-
def build
|
|
184
|
-
@settings = {
|
|
185
|
-
database: Database.connection,
|
|
186
|
-
cache: Cache.redis_url
|
|
187
|
-
}
|
|
188
|
-
end
|
|
189
|
-
end
|
|
119
|
+
App.run
|
|
120
|
+
# In development (RAILS_ENV != 'production'):
|
|
121
|
+
# => Connecting to localhost:5432
|
|
190
122
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
end
|
|
195
|
-
end
|
|
123
|
+
# In production (RAILS_ENV == 'production'):
|
|
124
|
+
# => Connecting to prod.example.com:5432
|
|
125
|
+
```
|
|
196
126
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
# => ├── Database
|
|
201
|
-
# => └── Cache
|
|
127
|
+
**When to use each:**
|
|
128
|
+
- **Exports**: Share computed values or side effects between tasks
|
|
129
|
+
- **Section**: Switch implementations based on environment or conditions
|
|
202
130
|
|
|
203
|
-
|
|
204
|
-
puts AppServer.tree
|
|
205
|
-
# => AppServer
|
|
206
|
-
# => └── DatabaseSection
|
|
207
|
-
```
|
|
131
|
+
> **Note**: When implementation classes are nested inside a Section, they automatically inherit the Section's `interfaces` as `exports`. External implementations must declare `exports` explicitly.
|
|
208
132
|
|
|
209
|
-
###
|
|
133
|
+
### 3. Context - Runtime Information Access
|
|
210
134
|
|
|
211
|
-
|
|
135
|
+
Access execution context information from any task:
|
|
212
136
|
|
|
213
137
|
```ruby
|
|
214
|
-
class
|
|
215
|
-
def
|
|
216
|
-
puts "
|
|
217
|
-
|
|
218
|
-
puts "
|
|
219
|
-
puts "Almost done..."
|
|
220
|
-
sleep(0.5)
|
|
221
|
-
puts "Completed!"
|
|
138
|
+
class DeployTask < Taski::Task
|
|
139
|
+
def run
|
|
140
|
+
puts "Working directory: #{Taski::Context.working_directory}"
|
|
141
|
+
puts "Started at: #{Taski::Context.started_at}"
|
|
142
|
+
puts "Root task: #{Taski::Context.root_task}"
|
|
222
143
|
end
|
|
223
144
|
end
|
|
224
|
-
|
|
225
|
-
LongRunningTask.build
|
|
226
|
-
# During execution shows:
|
|
227
|
-
# ⠧ LongRunningTask
|
|
228
|
-
# Starting process...
|
|
229
|
-
# Processing data...
|
|
230
|
-
# Almost done...
|
|
231
|
-
# Completed!
|
|
232
|
-
#
|
|
233
|
-
# After completion shows:
|
|
234
|
-
# ✅ LongRunningTask (1500ms)
|
|
235
145
|
```
|
|
236
146
|
|
|
237
|
-
**
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
- **Execution Time**: Shows task duration after completion
|
|
242
|
-
- **TTY Detection**: Clean output when redirected to files
|
|
243
|
-
|
|
244
|
-
### Granular Task Execution
|
|
147
|
+
**Available context:**
|
|
148
|
+
- `working_directory`: Directory where execution started
|
|
149
|
+
- `started_at`: Time when execution began
|
|
150
|
+
- `root_task`: The first task class that was called
|
|
245
151
|
|
|
246
|
-
|
|
152
|
+
> **Note**: Context is not included in dependency analysis - it provides runtime information only.
|
|
247
153
|
|
|
248
|
-
|
|
249
|
-
# Build specific components
|
|
250
|
-
ConfigLoader.build # Builds only ConfigLoader
|
|
251
|
-
# => Config loaded: MyApp v1.0.0
|
|
252
|
-
|
|
253
|
-
EnvironmentConfig.build # Builds EnvironmentConfig and its dependencies
|
|
254
|
-
# => Using database: localhost:5432
|
|
255
|
-
# => Environment: development
|
|
154
|
+
> **Important**: Tasks must be defined in source files, not dynamically with `Class.new`. Static analysis requires actual source files to detect dependencies.
|
|
256
155
|
|
|
257
|
-
|
|
258
|
-
puts ConfigLoader.version # Builds ConfigLoader if not built
|
|
259
|
-
# => 1.0.0
|
|
260
|
-
```
|
|
156
|
+
### 4. Re-execution with `new`
|
|
261
157
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
Tasks can define both build and clean methods. Clean operations run in reverse dependency order:
|
|
158
|
+
By default, task results are cached. Use `new` to create a fresh instance for re-execution:
|
|
265
159
|
|
|
266
160
|
```ruby
|
|
267
|
-
class
|
|
268
|
-
exports :
|
|
161
|
+
class RandomTask < Taski::Task
|
|
162
|
+
exports :value
|
|
269
163
|
|
|
270
|
-
def
|
|
271
|
-
@
|
|
272
|
-
puts "Database connected"
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
def clean
|
|
276
|
-
puts "Database disconnected"
|
|
164
|
+
def run
|
|
165
|
+
@value = rand(1000)
|
|
277
166
|
end
|
|
278
167
|
end
|
|
279
168
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
def clean
|
|
286
|
-
puts "Web server stopped"
|
|
287
|
-
end
|
|
288
|
-
end
|
|
169
|
+
# Cached execution (same result)
|
|
170
|
+
RandomTask.value # => 42
|
|
171
|
+
RandomTask.value # => 42 (cached)
|
|
289
172
|
|
|
290
|
-
|
|
291
|
-
# =>
|
|
292
|
-
# =>
|
|
173
|
+
# Fresh execution with new
|
|
174
|
+
RandomTask.new.run # => 123 (new instance)
|
|
175
|
+
RandomTask.new.run # => 456 (another new instance)
|
|
293
176
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
# =>
|
|
177
|
+
# Reset all caches
|
|
178
|
+
RandomTask.reset!
|
|
179
|
+
RandomTask.value # => 789 (fresh after reset)
|
|
297
180
|
```
|
|
298
181
|
|
|
299
|
-
|
|
182
|
+
**When to use:**
|
|
183
|
+
- `TaskClass.run` / `TaskClass.value`: Normal execution with caching (recommended for dependency graphs)
|
|
184
|
+
- `TaskClass.new.run`: Re-execute only this task (dependencies still use cache)
|
|
185
|
+
- `TaskClass.reset!`: Clear all caches and re-execute everything
|
|
300
186
|
|
|
301
|
-
|
|
187
|
+
## Key Features
|
|
302
188
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
189
|
+
- **Parallel Execution**: Independent tasks run concurrently using threads
|
|
190
|
+
- **Static Analysis**: Dependencies detected automatically via Prism AST parsing
|
|
191
|
+
- **Thread-Safe**: Monitor-based synchronization ensures safe concurrent access
|
|
192
|
+
- **Progress Display**: Real-time visual feedback with spinner animations and timing
|
|
193
|
+
- **Tree Visualization**: See your dependency graph structure
|
|
194
|
+
- **Graceful Abort**: Stop execution cleanly without starting new tasks (Ctrl+C)
|
|
195
|
+
- **Runtime Context**: Access execution information from any task
|
|
306
196
|
|
|
307
|
-
|
|
308
|
-
@output_file = '/tmp/data.csv'
|
|
309
|
-
File.write(@output_file, process_data)
|
|
310
|
-
end
|
|
197
|
+
### Parallel Progress Display
|
|
311
198
|
|
|
312
|
-
|
|
313
|
-
# ❌ Bad: Raises error if file doesn't exist
|
|
314
|
-
# File.delete(@output_file)
|
|
199
|
+
Enable real-time progress visualization:
|
|
315
200
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
end
|
|
319
|
-
end
|
|
201
|
+
```bash
|
|
202
|
+
TASKI_FORCE_PROGRESS=1 ruby your_script.rb
|
|
320
203
|
```
|
|
321
204
|
|
|
322
|
-
|
|
205
|
+
Output example:
|
|
206
|
+
```
|
|
207
|
+
⠋ DatabaseSetup (running)
|
|
208
|
+
⠙ CacheSetup (running)
|
|
209
|
+
✅ DatabaseSetup (123.4ms)
|
|
210
|
+
✅ CacheSetup (98.2ms)
|
|
211
|
+
⠸ WebServer (running)
|
|
212
|
+
✅ WebServer (45.1ms)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Tree Visualization
|
|
323
216
|
|
|
324
217
|
```ruby
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
# => Circular dependency: Circular dependency detected!
|
|
331
|
-
# => Cycle: TaskA → TaskB → TaskA
|
|
332
|
-
# =>
|
|
333
|
-
# => The dependency chain is:
|
|
334
|
-
# => 1. TaskA is trying to build → TaskB
|
|
335
|
-
# => 2. TaskB is trying to build → TaskA
|
|
218
|
+
puts WebServer.tree
|
|
219
|
+
# => WebServer
|
|
220
|
+
# => └── Config
|
|
221
|
+
# => ├── Database
|
|
222
|
+
# => └── Cache
|
|
336
223
|
```
|
|
337
224
|
|
|
338
225
|
## 📦 Installation
|
|
@@ -348,19 +235,21 @@ bundle install
|
|
|
348
235
|
## 🧪 Testing
|
|
349
236
|
|
|
350
237
|
```bash
|
|
351
|
-
|
|
238
|
+
rake test # Run all tests
|
|
239
|
+
rake standard # Check code style
|
|
352
240
|
```
|
|
353
241
|
|
|
354
|
-
##
|
|
242
|
+
## 📚 Learn More
|
|
355
243
|
|
|
356
|
-
- **
|
|
357
|
-
- **
|
|
358
|
-
- **
|
|
359
|
-
-
|
|
360
|
-
-
|
|
361
|
-
-
|
|
244
|
+
- **[Examples](examples/)**: Practical examples from basic to advanced patterns
|
|
245
|
+
- **[Tests](test/)**: Comprehensive test suite showing real-world usage
|
|
246
|
+
- **[Source Code](lib/taski/)**: Clean, well-documented implementation
|
|
247
|
+
- `lib/taski/task.rb` - Core Task implementation with exports API
|
|
248
|
+
- `lib/taski/section.rb` - Section API for runtime selection
|
|
249
|
+
- `lib/taski/execution/` - Parallel execution engine
|
|
250
|
+
- `lib/taski/static_analysis/` - Prism-based dependency analyzer
|
|
362
251
|
|
|
363
|
-
##
|
|
252
|
+
## Support
|
|
364
253
|
|
|
365
254
|
Bug reports and pull requests welcome at https://github.com/ahogappa/taski.
|
|
366
255
|
|
|
@@ -370,4 +259,4 @@ MIT License
|
|
|
370
259
|
|
|
371
260
|
---
|
|
372
261
|
|
|
373
|
-
**Taski** -
|
|
262
|
+
**Taski** - Parallel task execution with automatic dependency resolution. 🚀
|
data/Steepfile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Steepfile for Taski gem
|
|
2
|
+
|
|
3
|
+
target :lib do
|
|
4
|
+
signature "sig"
|
|
5
|
+
|
|
6
|
+
check "lib"
|
|
7
|
+
|
|
8
|
+
# Ignore test and temporary files
|
|
9
|
+
ignore "test"
|
|
10
|
+
ignore "tmp"
|
|
11
|
+
ignore "examples"
|
|
12
|
+
|
|
13
|
+
# Standard library dependencies
|
|
14
|
+
library "monitor"
|
|
15
|
+
library "tsort"
|
|
16
|
+
|
|
17
|
+
# Use gems from rbs_collection
|
|
18
|
+
collection_config "rbs_collection.yaml"
|
|
19
|
+
end
|