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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gem_rbs_collection/ast/2.4/.rbs_meta.yaml +9 -0
  3. data/.gem_rbs_collection/ast/2.4/ast.rbs +73 -0
  4. data/.gem_rbs_collection/minitest/5.25/.rbs_meta.yaml +9 -0
  5. data/.gem_rbs_collection/minitest/5.25/minitest/abstract_reporter.rbs +52 -0
  6. data/.gem_rbs_collection/minitest/5.25/minitest/assertion.rbs +17 -0
  7. data/.gem_rbs_collection/minitest/5.25/minitest/assertions.rbs +590 -0
  8. data/.gem_rbs_collection/minitest/5.25/minitest/backtrace_filter.rbs +23 -0
  9. data/.gem_rbs_collection/minitest/5.25/minitest/bench_spec.rbs +102 -0
  10. data/.gem_rbs_collection/minitest/5.25/minitest/benchmark.rbs +259 -0
  11. data/.gem_rbs_collection/minitest/5.25/minitest/composite_reporter.rbs +25 -0
  12. data/.gem_rbs_collection/minitest/5.25/minitest/compress.rbs +13 -0
  13. data/.gem_rbs_collection/minitest/5.25/minitest/error_on_warning.rbs +3 -0
  14. data/.gem_rbs_collection/minitest/5.25/minitest/expectation.rbs +2 -0
  15. data/.gem_rbs_collection/minitest/5.25/minitest/expectations.rbs +21 -0
  16. data/.gem_rbs_collection/minitest/5.25/minitest/guard.rbs +64 -0
  17. data/.gem_rbs_collection/minitest/5.25/minitest/mock.rbs +64 -0
  18. data/.gem_rbs_collection/minitest/5.25/minitest/parallel/executor.rbs +46 -0
  19. data/.gem_rbs_collection/minitest/5.25/minitest/parallel/test/class_methods.rbs +5 -0
  20. data/.gem_rbs_collection/minitest/5.25/minitest/parallel/test.rbs +3 -0
  21. data/.gem_rbs_collection/minitest/5.25/minitest/parallel.rbs +2 -0
  22. data/.gem_rbs_collection/minitest/5.25/minitest/pride_io.rbs +62 -0
  23. data/.gem_rbs_collection/minitest/5.25/minitest/pride_lol.rbs +19 -0
  24. data/.gem_rbs_collection/minitest/5.25/minitest/progress_reporter.rbs +11 -0
  25. data/.gem_rbs_collection/minitest/5.25/minitest/reportable.rbs +53 -0
  26. data/.gem_rbs_collection/minitest/5.25/minitest/reporter.rbs +5 -0
  27. data/.gem_rbs_collection/minitest/5.25/minitest/result.rbs +28 -0
  28. data/.gem_rbs_collection/minitest/5.25/minitest/runnable.rbs +163 -0
  29. data/.gem_rbs_collection/minitest/5.25/minitest/skip.rbs +6 -0
  30. data/.gem_rbs_collection/minitest/5.25/minitest/spec/dsl/instance_methods.rbs +48 -0
  31. data/.gem_rbs_collection/minitest/5.25/minitest/spec/dsl.rbs +129 -0
  32. data/.gem_rbs_collection/minitest/5.25/minitest/spec.rbs +11 -0
  33. data/.gem_rbs_collection/minitest/5.25/minitest/statistics_reporter.rbs +81 -0
  34. data/.gem_rbs_collection/minitest/5.25/minitest/summary_reporter.rbs +18 -0
  35. data/.gem_rbs_collection/minitest/5.25/minitest/test/lifecycle_hooks.rbs +92 -0
  36. data/.gem_rbs_collection/minitest/5.25/minitest/test.rbs +69 -0
  37. data/.gem_rbs_collection/minitest/5.25/minitest/unexpected_error.rbs +12 -0
  38. data/.gem_rbs_collection/minitest/5.25/minitest/unexpected_warning.rbs +6 -0
  39. data/.gem_rbs_collection/minitest/5.25/minitest/unit/test_case.rbs +3 -0
  40. data/.gem_rbs_collection/minitest/5.25/minitest/unit.rbs +4 -0
  41. data/.gem_rbs_collection/minitest/5.25/minitest.rbs +115 -0
  42. data/.gem_rbs_collection/parallel/1.20/.rbs_meta.yaml +9 -0
  43. data/.gem_rbs_collection/parallel/1.20/parallel.rbs +86 -0
  44. data/.gem_rbs_collection/parser/3.2/.rbs_meta.yaml +9 -0
  45. data/.gem_rbs_collection/parser/3.2/manifest.yaml +7 -0
  46. data/.gem_rbs_collection/parser/3.2/parser.rbs +193 -0
  47. data/.gem_rbs_collection/parser/3.2/polyfill.rbs +4 -0
  48. data/.gem_rbs_collection/rainbow/3.0/.rbs_meta.yaml +9 -0
  49. data/.gem_rbs_collection/rainbow/3.0/global.rbs +7 -0
  50. data/.gem_rbs_collection/rainbow/3.0/presenter.rbs +209 -0
  51. data/.gem_rbs_collection/rainbow/3.0/rainbow.rbs +5 -0
  52. data/.gem_rbs_collection/rake/13.0/.rbs_meta.yaml +9 -0
  53. data/.gem_rbs_collection/rake/13.0/manifest.yaml +2 -0
  54. data/.gem_rbs_collection/rake/13.0/rake.rbs +39 -0
  55. data/.gem_rbs_collection/regexp_parser/2.8/.rbs_meta.yaml +9 -0
  56. data/.gem_rbs_collection/regexp_parser/2.8/regexp_parser.rbs +17 -0
  57. data/.gem_rbs_collection/rubocop/1.57/.rbs_meta.yaml +9 -0
  58. data/.gem_rbs_collection/rubocop/1.57/rubocop.rbs +129 -0
  59. data/.gem_rbs_collection/rubocop-ast/1.30/.rbs_meta.yaml +9 -0
  60. data/.gem_rbs_collection/rubocop-ast/1.30/rubocop-ast.rbs +771 -0
  61. data/.gem_rbs_collection/simplecov/0.22/.rbs_meta.yaml +9 -0
  62. data/.gem_rbs_collection/simplecov/0.22/simplecov.rbs +54 -0
  63. data/README.md +137 -248
  64. data/Steepfile +19 -0
  65. data/docs/advanced-features.md +625 -0
  66. data/docs/api-guide.md +509 -0
  67. data/docs/error-handling.md +684 -0
  68. data/examples/README.md +95 -42
  69. data/examples/context_demo.rb +112 -0
  70. data/examples/data_pipeline_demo.rb +231 -0
  71. data/examples/parallel_progress_demo.rb +72 -0
  72. data/examples/quick_start.rb +4 -4
  73. data/examples/reexecution_demo.rb +127 -0
  74. data/examples/{section_configuration.rb → section_demo.rb} +49 -66
  75. data/lib/taski/context.rb +52 -0
  76. data/lib/taski/execution/coordinator.rb +63 -0
  77. data/lib/taski/execution/parallel_progress_display.rb +201 -0
  78. data/lib/taski/execution/registry.rb +72 -0
  79. data/lib/taski/execution/task_wrapper.rb +255 -0
  80. data/lib/taski/section.rb +26 -250
  81. data/lib/taski/static_analysis/analyzer.rb +34 -0
  82. data/lib/taski/static_analysis/dependency_graph.rb +90 -0
  83. data/lib/taski/static_analysis/visitor.rb +114 -0
  84. data/lib/taski/task.rb +173 -0
  85. data/lib/taski/version.rb +1 -1
  86. data/lib/taski.rb +45 -39
  87. data/rbs_collection.lock.yaml +116 -0
  88. data/rbs_collection.yaml +19 -0
  89. data/sig/taski.rbs +269 -62
  90. metadata +97 -32
  91. data/examples/advanced_patterns.rb +0 -119
  92. data/examples/progress_demo.rb +0 -166
  93. data/examples/tree_demo.rb +0 -205
  94. data/lib/taski/dependency_analyzer.rb +0 -231
  95. data/lib/taski/exceptions.rb +0 -17
  96. data/lib/taski/logger.rb +0 -158
  97. data/lib/taski/logging/formatter_factory.rb +0 -34
  98. data/lib/taski/logging/formatter_interface.rb +0 -19
  99. data/lib/taski/logging/json_formatter.rb +0 -26
  100. data/lib/taski/logging/simple_formatter.rb +0 -16
  101. data/lib/taski/logging/structured_formatter.rb +0 -44
  102. data/lib/taski/progress/display_colors.rb +0 -17
  103. data/lib/taski/progress/display_manager.rb +0 -115
  104. data/lib/taski/progress/output_capture.rb +0 -105
  105. data/lib/taski/progress/spinner_animation.rb +0 -46
  106. data/lib/taski/progress/task_formatter.rb +0 -25
  107. data/lib/taski/progress/task_status.rb +0 -38
  108. data/lib/taski/progress/terminal_controller.rb +0 -35
  109. data/lib/taski/progress_display.rb +0 -59
  110. data/lib/taski/reference.rb +0 -40
  111. data/lib/taski/task/base.rb +0 -90
  112. data/lib/taski/task/define_api.rb +0 -154
  113. data/lib/taski/task/dependency_resolver.rb +0 -73
  114. data/lib/taski/task/exports_api.rb +0 -31
  115. data/lib/taski/task/instance_management.rb +0 -203
  116. data/lib/taski/tree_colors.rb +0 -91
  117. data/lib/taski/utils/dependency_resolver_helper.rb +0 -85
  118. data/lib/taski/utils/tree_display_helper.rb +0 -71
  119. data/lib/taski/utils.rb +0 -107
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: simplecov
3
+ version: '0.22'
4
+ source:
5
+ type: git
6
+ name: ruby/gem_rbs_collection
7
+ revision: 3a33fa6f8e486f880c80ca401f2be1c1f621cf11
8
+ remote: https://github.com/ruby/gem_rbs_collection.git
9
+ repo_dir: gems
@@ -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 execution. It provides three APIs: static dependencies through **Exports**, dynamic dependencies through **Define**, and abstraction layers through **Section**.
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
- # Static dependency using Exports API
28
+ # Define tasks with dependencies
19
29
  class DatabaseSetup < Taski::Task
20
30
  exports :connection_string
21
31
 
22
- def build
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 build
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
- APIServer.build
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
- ## 📚 API Guide
40
-
41
- ### Exports API - Static Dependencies
63
+ ## Core Concepts
42
64
 
43
- For simple, predictable dependencies:
65
+ Taski provides two complementary APIs:
44
66
 
67
+ ### 1. Exports API - Value Sharing Between Tasks
45
68
  ```ruby
46
- class ConfigLoader < Taski::Task
47
- exports :app_name, :version
69
+ class Config < Taski::Task
70
+ exports :app_name, :port
48
71
 
49
- def build
72
+ def run
50
73
  @app_name = "MyApp"
51
- @version = "1.0.0"
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
- Deployment.build
64
- # => Config loaded: MyApp v1.0.0
65
- # => Deploying to https://MyApp.example.com
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 - Abstraction Layers
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
- interface :host, :port
107
-
108
- def impl # No 'self' needed!
109
- ENV['RAILS_ENV'] == 'production' ? Production : Development
110
- end
89
+ interfaces :host, :port
111
90
 
112
- class Production < Taski::Task
113
- def build
114
- @host = "prod-db.example.com"
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 Development < Taski::Task
120
- def build
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
- apply_auto_exports # DRY - auto-adds exports to nested tasks
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 build
132
- puts "DB: #{DatabaseSection.host}:#{DatabaseSection.port}"
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.build # => DB: localhost:5432
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
- class WebServer < Taski::Task
192
- def build
193
- puts "Starting with #{Config.settings}"
194
- end
195
- end
123
+ # In production (RAILS_ENV == 'production'):
124
+ # => Connecting to prod.example.com:5432
125
+ ```
196
126
 
197
- puts WebServer.tree
198
- # => WebServer
199
- # => └── Config
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
- # Sections also appear in dependency trees
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
- ### Progress Display
133
+ ### 3. Context - Runtime Information Access
210
134
 
211
- Taski provides visual feedback during task execution with animated spinners and real-time output capture:
135
+ Access execution context information from any task:
212
136
 
213
137
  ```ruby
214
- class LongRunningTask < Taski::Task
215
- def build
216
- puts "Starting process..."
217
- sleep(1.0)
218
- puts "Processing data..."
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
- **Progress Display Features:**
238
- - **Spinner Animation**: Dots-style spinner during task execution
239
- - **Output Capture**: Real-time display of task output (last 5 lines)
240
- - **Status Indicators**: for success, for failure
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
- Execute any task individually - Taski builds only required dependencies:
152
+ > **Note**: Context is not included in dependency analysis - it provides runtime information only.
247
153
 
248
- ```ruby
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
- # Access values (triggers build if needed)
258
- puts ConfigLoader.version # Builds ConfigLoader if not built
259
- # => 1.0.0
260
- ```
156
+ ### 4. Re-execution with `new`
261
157
 
262
- ### Lifecycle Management
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 DatabaseSetup < Taski::Task
268
- exports :connection
161
+ class RandomTask < Taski::Task
162
+ exports :value
269
163
 
270
- def build
271
- @connection = "db-connection"
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
- class WebServer < Taski::Task
281
- def build
282
- puts "Web server started with #{DatabaseSetup.connection}"
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
- WebServer.build
291
- # => Database connected
292
- # => Web server started with db-connection
173
+ # Fresh execution with new
174
+ RandomTask.new.run # => 123 (new instance)
175
+ RandomTask.new.run # => 456 (another new instance)
293
176
 
294
- WebServer.clean
295
- # => Web server stopped
296
- # => Database disconnected
177
+ # Reset all caches
178
+ RandomTask.reset!
179
+ RandomTask.value # => 789 (fresh after reset)
297
180
  ```
298
181
 
299
- ### Clean Method Idempotency
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
- **Important**: The `clean` method must be idempotent - safe to call multiple times without errors.
187
+ ## Key Features
302
188
 
303
- ```ruby
304
- class FileTask < Taski::Task
305
- exports :output_file
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
- def build
308
- @output_file = '/tmp/data.csv'
309
- File.write(@output_file, process_data)
310
- end
197
+ ### Parallel Progress Display
311
198
 
312
- def clean
313
- # ❌ Bad: Raises error if file doesn't exist
314
- # File.delete(@output_file)
199
+ Enable real-time progress visualization:
315
200
 
316
- # ✅ Good: Check before delete
317
- File.delete(@output_file) if File.exist?(@output_file)
318
- end
319
- end
201
+ ```bash
202
+ TASKI_FORCE_PROGRESS=1 ruby your_script.rb
320
203
  ```
321
204
 
322
- ### Error Handling
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
- begin
326
- TaskWithCircularDep.build
327
- rescue Taski::CircularDependencyError => e
328
- puts "Circular dependency: #{e.message}"
329
- end
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
- bundle exec rake test
238
+ rake test # Run all tests
239
+ rake standard # Check code style
352
240
  ```
353
241
 
354
- ## 🏛️ Architecture
242
+ ## 📚 Learn More
355
243
 
356
- - **Task Base**: Core framework
357
- - **Exports API**: Static dependency resolution
358
- - **Define API**: Dynamic dependency resolution
359
- - **Section API**: Abstraction layer with runtime implementation selection
360
- - **Instance Management**: Thread-safe lifecycle
361
- - **Dependency Resolver**: Topological sorting with Section support
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
- ## Contributing
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** - Build dependency graphs with elegant Ruby code. 🚀
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