taski 0.2.0 → 0.2.1
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/.standard.yml +9 -0
- data/README.md +93 -201
- data/Rakefile +7 -1
- data/examples/complex_example.rb +16 -18
- data/examples/readme_example.rb +2 -2
- data/lib/taski/dependency_analyzer.rb +18 -8
- data/lib/taski/exceptions.rb +4 -4
- data/lib/taski/logger.rb +202 -0
- data/lib/taski/reference.rb +3 -3
- data/lib/taski/task/base.rb +3 -3
- data/lib/taski/task/define_api.rb +19 -6
- data/lib/taski/task/dependency_resolver.rb +44 -11
- data/lib/taski/task/exports_api.rb +1 -1
- data/lib/taski/task/instance_management.rb +51 -10
- data/lib/taski/version.rb +1 -1
- data/lib/taski.rb +5 -5
- data/sig/taski.rbs +39 -2
- metadata +5 -4
- data/Steepfile +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e44ea93464ceaf8994d761cec75cf4d32df7cdb8f90d25b4cfcae5be7f8a586
|
4
|
+
data.tar.gz: 8a1b5fae85bbffb28756f2e13b3f98c2cb8023c76346b5da722ac55e87ef3cc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '037285b1bc19edd6d674f6748674fa8443c0cb40d5199de86bdfa3696c1597308d69ff5236a7114c43cf666a27e62f5c4111c5a36301736c4fdac98cdd65b4c4'
|
7
|
+
data.tar.gz: afa967d630b56f9de1f4974879533572d06c42d574dce6bea69da9635ce69e06251af555168ff0b3475e95d5a1d6d07e8951e6052f0f6e04291d07b15d23239b
|
data/.standard.yml
ADDED
data/README.md
CHANGED
@@ -1,27 +1,21 @@
|
|
1
1
|
# Taski
|
2
2
|
|
3
|
-
|
3
|
+
[](https://github.com/ahogappa/taski/actions/workflows/ci.yml)
|
4
|
+
[](https://codecov.io/gh/ahogappa/taski)
|
5
|
+
[](https://badge.fury.io/rb/taski)
|
4
6
|
|
5
|
-
|
7
|
+
> **🚧 Development Status:** Taski is currently under active development. Not yet recommended for production use.
|
6
8
|
|
7
|
-
|
9
|
+
**Taski** is a Ruby framework for building task dependency graphs with automatic resolution and execution. It provides two APIs: static dependencies through **Exports** and dynamic dependencies through **Define**.
|
8
10
|
|
9
|
-
|
10
|
-
- **Two Complementary APIs**: Choose the right approach for your use case
|
11
|
-
- **Exports API**: For simple, static dependencies
|
12
|
-
- **Define API**: For complex, dynamic dependencies based on runtime conditions
|
13
|
-
- **Thread-Safe Execution**: Safe for concurrent access with Monitor-based synchronization
|
14
|
-
- **Circular Dependency Detection**: Prevents infinite loops with clear error messages
|
15
|
-
- **Memory Leak Prevention**: Built-in reset mechanisms for long-running applications
|
16
|
-
- **Topological Execution**: Tasks execute in correct dependency order automatically
|
17
|
-
- **Reverse Cleanup**: Clean operations run in reverse dependency order
|
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.
|
18
12
|
|
19
13
|
## 🚀 Quick Start
|
20
14
|
|
21
15
|
```ruby
|
22
16
|
require 'taski'
|
23
17
|
|
24
|
-
#
|
18
|
+
# Static dependency using Exports API
|
25
19
|
class DatabaseSetup < Taski::Task
|
26
20
|
exports :connection_string
|
27
21
|
|
@@ -32,16 +26,11 @@ class DatabaseSetup < Taski::Task
|
|
32
26
|
end
|
33
27
|
|
34
28
|
class APIServer < Taski::Task
|
35
|
-
exports :port
|
36
|
-
|
37
29
|
def build
|
38
|
-
# Automatic dependency: DatabaseSetup will be built first
|
39
30
|
puts "Starting API with #{DatabaseSetup.connection_string}"
|
40
|
-
@port = 3000
|
41
31
|
end
|
42
32
|
end
|
43
33
|
|
44
|
-
# Execute - dependencies are resolved automatically
|
45
34
|
APIServer.build
|
46
35
|
# => Database configured
|
47
36
|
# => Starting API with postgresql://localhost/myapp
|
@@ -51,7 +40,7 @@ APIServer.build
|
|
51
40
|
|
52
41
|
### Exports API - Static Dependencies
|
53
42
|
|
54
|
-
|
43
|
+
For simple, predictable dependencies:
|
55
44
|
|
56
45
|
```ruby
|
57
46
|
class ConfigLoader < Taski::Task
|
@@ -60,274 +49,177 @@ class ConfigLoader < Taski::Task
|
|
60
49
|
def build
|
61
50
|
@app_name = "MyApp"
|
62
51
|
@version = "1.0.0"
|
52
|
+
puts "Config loaded: #{@app_name} v#{@version}"
|
63
53
|
end
|
64
54
|
end
|
65
55
|
|
66
56
|
class Deployment < Taski::Task
|
67
|
-
exports :deploy_url
|
68
|
-
|
69
57
|
def build
|
70
|
-
# Static dependency - always uses ConfigLoader
|
71
58
|
@deploy_url = "https://#{ConfigLoader.app_name}.example.com"
|
59
|
+
puts "Deploying to #{@deploy_url}"
|
72
60
|
end
|
73
61
|
end
|
62
|
+
|
63
|
+
Deployment.build
|
64
|
+
# => Config loaded: MyApp v1.0.0
|
65
|
+
# => Deploying to https://MyApp.example.com
|
74
66
|
```
|
75
67
|
|
76
68
|
### Define API - Dynamic Dependencies
|
77
69
|
|
78
|
-
|
70
|
+
For dependencies that change based on runtime conditions:
|
79
71
|
|
80
72
|
```ruby
|
81
73
|
class EnvironmentConfig < Taski::Task
|
82
74
|
define :database_service, -> {
|
83
|
-
# Dynamic dependency based on environment
|
84
75
|
case ENV['RAILS_ENV']
|
85
76
|
when 'production'
|
86
|
-
|
87
|
-
when 'staging'
|
88
|
-
StagingDatabase.setup
|
89
|
-
else
|
90
|
-
DevelopmentDatabase.setup
|
91
|
-
end
|
92
|
-
}
|
93
|
-
|
94
|
-
define :cache_strategy, -> {
|
95
|
-
# Dynamic dependency based on feature flags
|
96
|
-
if FeatureFlag.enabled?(:redis_cache)
|
97
|
-
RedisCache.configure
|
77
|
+
"production-db.example.com"
|
98
78
|
else
|
99
|
-
|
79
|
+
"localhost:5432"
|
100
80
|
end
|
101
81
|
}
|
102
82
|
|
103
83
|
def build
|
104
|
-
puts "Using #{database_service}"
|
105
|
-
puts "
|
84
|
+
puts "Using database: #{database_service}"
|
85
|
+
puts "Environment: #{ENV['RAILS_ENV'] || 'development'}"
|
106
86
|
end
|
107
87
|
end
|
108
|
-
```
|
109
88
|
|
110
|
-
|
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
|
+
```
|
111
99
|
|
112
100
|
### When to Use Each API
|
113
101
|
|
114
|
-
|
115
|
-
|
116
|
-
| Simple value exports | Exports API | Configuration values, file paths |
|
117
|
-
| Environment-specific logic | Define API | Different services per environment |
|
118
|
-
| Feature flag dependencies | Define API | Optional components based on flags |
|
119
|
-
| Conditional processing | Define API | Different algorithms based on input |
|
120
|
-
| Static file dependencies | Exports API | Build artifacts, compiled assets |
|
102
|
+
- **Define API**: Best for dynamic runtime dependencies. Cannot contain side effects in definition blocks.
|
103
|
+
- **Exports API**: Ideal for static dependencies. Supports side effects in build methods.
|
121
104
|
|
122
|
-
|
105
|
+
| Use Case | API | Example |
|
106
|
+
|----------|-----|---------|
|
107
|
+
| Configuration values | Exports | File paths, settings |
|
108
|
+
| Environment-specific logic | Define | Different services per env |
|
109
|
+
| Side effects | Exports | Database connections, I/O |
|
110
|
+
| Conditional processing | Define | Algorithm selection |
|
123
111
|
|
124
|
-
|
112
|
+
## ✨ Key Features
|
125
113
|
|
126
|
-
|
114
|
+
- **Automatic Dependency Resolution**: Dependencies detected through static analysis
|
115
|
+
- **Thread-Safe**: Safe for concurrent access
|
116
|
+
- **Circular Dependency Detection**: Clear error messages with detailed paths
|
117
|
+
- **Granular Execution**: Build individual tasks or complete graphs
|
118
|
+
- **Memory Management**: Built-in reset mechanisms
|
127
119
|
|
128
|
-
|
129
|
-
# Multiple threads can safely access the same task
|
130
|
-
threads = 5.times.map do
|
131
|
-
Thread.new { MyTask.some_value }
|
132
|
-
end
|
120
|
+
### Granular Task Execution
|
133
121
|
|
134
|
-
|
135
|
-
results = threads.map(&:value)
|
136
|
-
```
|
122
|
+
Execute any task individually - Taski builds only required dependencies:
|
137
123
|
|
138
|
-
|
124
|
+
```ruby
|
125
|
+
# Build specific components
|
126
|
+
ConfigLoader.build # Builds only ConfigLoader
|
127
|
+
# => Config loaded: MyApp v1.0.0
|
139
128
|
|
140
|
-
|
129
|
+
EnvironmentConfig.build # Builds EnvironmentConfig and its dependencies
|
130
|
+
# => Using database: localhost:5432
|
131
|
+
# => Environment: development
|
141
132
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
rescue Taski::CircularDependencyError => e
|
146
|
-
puts "Circular dependency detected: #{e.message}"
|
147
|
-
rescue Taski::TaskBuildError => e
|
148
|
-
puts "Build failed: #{e.message}"
|
149
|
-
end
|
133
|
+
# Access values (triggers build if needed)
|
134
|
+
puts ConfigLoader.version # Builds ConfigLoader if not built
|
135
|
+
# => 1.0.0
|
150
136
|
```
|
151
137
|
|
152
138
|
### Lifecycle Management
|
153
139
|
|
154
|
-
|
140
|
+
Tasks can define both build and clean methods. Clean operations run in reverse dependency order:
|
155
141
|
|
156
142
|
```ruby
|
157
|
-
class
|
143
|
+
class DatabaseSetup < Taski::Task
|
144
|
+
exports :connection
|
145
|
+
|
158
146
|
def build
|
159
|
-
|
160
|
-
puts "
|
147
|
+
@connection = "db-connection"
|
148
|
+
puts "Database connected"
|
161
149
|
end
|
162
150
|
|
163
151
|
def clean
|
164
|
-
|
165
|
-
puts "Cleaning up temporary files..."
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
# Build dependencies in correct order
|
170
|
-
ProcessingTask.build
|
171
|
-
|
172
|
-
# Clean in reverse order
|
173
|
-
ProcessingTask.clean
|
174
|
-
```
|
175
|
-
|
176
|
-
## 🏗️ Complex Example
|
177
|
-
|
178
|
-
Here's a realistic example showing both APIs working together:
|
179
|
-
|
180
|
-
```ruby
|
181
|
-
# Environment configuration using Define API
|
182
|
-
class Environment < Taski::Task
|
183
|
-
define :database_url, -> {
|
184
|
-
case ENV['RAILS_ENV']
|
185
|
-
when 'production'
|
186
|
-
ProductionDB.connection_string
|
187
|
-
when 'test'
|
188
|
-
TestDB.connection_string
|
189
|
-
else
|
190
|
-
"sqlite3://development.db"
|
191
|
-
end
|
192
|
-
}
|
193
|
-
|
194
|
-
define :redis_config, -> {
|
195
|
-
if FeatureFlag.enabled?(:redis_cache)
|
196
|
-
RedisService.configuration
|
197
|
-
else
|
198
|
-
nil
|
199
|
-
end
|
200
|
-
}
|
201
|
-
end
|
202
|
-
|
203
|
-
# Static configuration using Exports API
|
204
|
-
class AppConfig < Taski::Task
|
205
|
-
exports :app_name, :version, :port
|
206
|
-
|
207
|
-
def build
|
208
|
-
@app_name = "MyWebApp"
|
209
|
-
@version = "2.1.0"
|
210
|
-
@port = ENV.fetch('PORT', 3000).to_i
|
152
|
+
puts "Database disconnected"
|
211
153
|
end
|
212
154
|
end
|
213
155
|
|
214
|
-
|
215
|
-
class Application < Taski::Task
|
156
|
+
class WebServer < Taski::Task
|
216
157
|
def build
|
217
|
-
puts "
|
218
|
-
puts "Database: #{Environment.database_url}"
|
219
|
-
puts "Redis: #{Environment.redis_config || 'disabled'}"
|
220
|
-
puts "Port: #{AppConfig.port}"
|
221
|
-
|
222
|
-
# Start the application...
|
158
|
+
puts "Web server started with #{DatabaseSetup.connection}"
|
223
159
|
end
|
224
160
|
|
225
161
|
def clean
|
226
|
-
puts "
|
227
|
-
# Cleanup logic...
|
162
|
+
puts "Web server stopped"
|
228
163
|
end
|
229
164
|
end
|
230
165
|
|
231
|
-
|
232
|
-
|
166
|
+
WebServer.build
|
167
|
+
# => Database connected
|
168
|
+
# => Web server started with db-connection
|
169
|
+
|
170
|
+
WebServer.clean
|
171
|
+
# => Web server stopped
|
172
|
+
# => Database disconnected
|
233
173
|
```
|
234
174
|
|
235
|
-
|
175
|
+
### Error Handling
|
236
176
|
|
237
|
-
|
177
|
+
```ruby
|
178
|
+
begin
|
179
|
+
TaskWithCircularDep.build
|
180
|
+
rescue Taski::CircularDependencyError => e
|
181
|
+
puts "Circular dependency: #{e.message}"
|
182
|
+
end
|
183
|
+
# => Circular dependency: Circular dependency detected!
|
184
|
+
# => Cycle: TaskA → TaskB → TaskA
|
185
|
+
# =>
|
186
|
+
# => The dependency chain is:
|
187
|
+
# => 1. TaskA is trying to build → TaskB
|
188
|
+
# => 2. TaskB is trying to build → TaskA
|
189
|
+
```
|
238
190
|
|
239
|
-
|
191
|
+
## 📦 Installation
|
240
192
|
|
241
193
|
```ruby
|
242
194
|
gem 'taski'
|
243
195
|
```
|
244
196
|
|
245
|
-
And then execute:
|
246
|
-
|
247
197
|
```bash
|
248
198
|
bundle install
|
249
199
|
```
|
250
200
|
|
251
|
-
Or install it yourself as:
|
252
|
-
|
253
|
-
```bash
|
254
|
-
gem install taski
|
255
|
-
```
|
256
|
-
|
257
|
-
For development and testing purposes, you can also install directly from the repository:
|
258
|
-
|
259
|
-
```ruby
|
260
|
-
# In your Gemfile
|
261
|
-
gem 'taski', git: 'https://github.com/[USERNAME]/taski.git'
|
262
|
-
```
|
263
|
-
|
264
201
|
## 🧪 Testing
|
265
202
|
|
266
|
-
Taski includes comprehensive test coverage. Run the test suite:
|
267
|
-
|
268
203
|
```bash
|
269
204
|
bundle exec rake test
|
270
205
|
```
|
271
206
|
|
272
|
-
> **ℹ️ Note:** Test output may include warnings about method redefinition from the `define` API. These warnings are expected and can be safely ignored.
|
273
|
-
|
274
|
-
|
275
207
|
## 🏛️ Architecture
|
276
208
|
|
277
|
-
|
278
|
-
|
279
|
-
- **Task Base**: Core framework and constants
|
209
|
+
- **Task Base**: Core framework
|
280
210
|
- **Exports API**: Static dependency resolution
|
281
211
|
- **Define API**: Dynamic dependency resolution
|
282
|
-
- **Instance Management**: Thread-safe lifecycle
|
283
|
-
- **Dependency Resolver**: Topological sorting
|
284
|
-
- **Static Analyzer**: AST-based dependency detection
|
285
|
-
|
286
|
-
## 🚧 Development Status
|
287
|
-
|
288
|
-
**Taski is currently in active development and should be considered experimental.** While the core functionality is working and well-tested, the API may undergo changes as we refine the framework based on feedback and real-world usage.
|
289
|
-
|
290
|
-
### Current Development Phase
|
291
|
-
|
292
|
-
- ✅ **Core Framework**: Dependency resolution, both APIs, thread safety
|
293
|
-
- ✅ **Testing**: Comprehensive test suite with 38+ tests
|
294
|
-
- ✅ **Type Safety**: RBS definitions and Steep integration
|
295
|
-
- 🚧 **API Stability**: Some breaking changes may occur
|
296
|
-
- 🚧 **Performance**: Optimizations for large dependency graphs
|
297
|
-
- 🚧 **Documentation**: Examples and best practices
|
298
|
-
|
299
|
-
### Known Limitations
|
300
|
-
|
301
|
-
- **API Changes**: Breaking changes may occur in minor version updates
|
302
|
-
- **Production Readiness**: Not yet recommended for production environments
|
303
|
-
- **Static Analysis**: Works best with straightforward Ruby code patterns
|
304
|
-
- **Metaprogramming**: Complex metaprogramming may require manual dependency specification
|
305
|
-
- **Performance**: Not yet optimized for very large dependency graphs (1000+ tasks)
|
306
|
-
- **Method Redefinition Warnings**: Using `define` API may generate Ruby warnings about method redefinition (this is expected behavior)
|
307
|
-
|
308
|
-
### Future Development
|
309
|
-
|
310
|
-
The future direction of Taski will be determined based on community feedback, real-world usage, and identified needs. Development priorities may include areas such as performance optimization, enhanced static analysis, and improved documentation, but specific roadmap items have not yet been finalized.
|
311
|
-
|
312
|
-
### Contributing to Development
|
313
|
-
|
314
|
-
We welcome contributions during this development phase! Areas where help is especially appreciated:
|
315
|
-
|
316
|
-
- **Real-world Testing**: Try Taski in your projects and report issues
|
317
|
-
- **Performance Testing**: Test with large dependency graphs
|
318
|
-
- **API Feedback**: Suggest improvements to the developer experience
|
319
|
-
- **Documentation**: Help improve examples and guides
|
212
|
+
- **Instance Management**: Thread-safe lifecycle
|
213
|
+
- **Dependency Resolver**: Topological sorting
|
320
214
|
|
321
215
|
## Contributing
|
322
216
|
|
323
|
-
Bug reports and pull requests
|
217
|
+
Bug reports and pull requests welcome at https://github.com/ahogappa/taski.
|
324
218
|
|
325
219
|
## License
|
326
220
|
|
327
|
-
|
221
|
+
MIT License
|
328
222
|
|
329
223
|
---
|
330
224
|
|
331
|
-
**Taski** - Build
|
332
|
-
|
333
|
-
> **Experimental Software**: Please use responsibly and provide feedback to help us reach v1.0!
|
225
|
+
**Taski** - Build dependency graphs with elegant Ruby code. 🚀
|
data/Rakefile
CHANGED
data/examples/complex_example.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# Complex example from README showing both APIs
|
3
3
|
|
4
|
-
require_relative
|
4
|
+
require_relative "../lib/taski"
|
5
5
|
|
6
6
|
# Mock classes for the example
|
7
7
|
class ProductionDB < Taski::Task
|
@@ -11,7 +11,7 @@ class ProductionDB < Taski::Task
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
class TestDB < Taski::Task
|
14
|
+
class TestDB < Taski::Task
|
15
15
|
exports :connection_string
|
16
16
|
def build
|
17
17
|
@connection_string = "postgres://test-server/app_test"
|
@@ -20,7 +20,7 @@ end
|
|
20
20
|
|
21
21
|
module FeatureFlag
|
22
22
|
def self.enabled?(flag)
|
23
|
-
ENV["FEATURE_#{flag.to_s.upcase}"] ==
|
23
|
+
ENV["FEATURE_#{flag.to_s.upcase}"] == "true"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -34,11 +34,11 @@ end
|
|
34
34
|
# Environment configuration using Define API
|
35
35
|
class Environment < Taski::Task
|
36
36
|
define :database_url, -> {
|
37
|
-
case ENV[
|
38
|
-
when
|
37
|
+
case ENV["RAILS_ENV"]
|
38
|
+
when "production"
|
39
39
|
ProductionDB.connection_string
|
40
|
-
when
|
41
|
-
TestDB.connection_string
|
40
|
+
when "test"
|
41
|
+
TestDB.connection_string
|
42
42
|
else
|
43
43
|
"sqlite3://development.db"
|
44
44
|
end
|
@@ -47,8 +47,6 @@ class Environment < Taski::Task
|
|
47
47
|
define :redis_config, -> {
|
48
48
|
if FeatureFlag.enabled?(:redis_cache)
|
49
49
|
RedisService.configuration
|
50
|
-
else
|
51
|
-
nil
|
52
50
|
end
|
53
51
|
}
|
54
52
|
|
@@ -57,14 +55,14 @@ class Environment < Taski::Task
|
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
|
-
# Static configuration using Exports API
|
58
|
+
# Static configuration using Exports API
|
61
59
|
class AppConfig < Taski::Task
|
62
60
|
exports :app_name, :version, :port
|
63
61
|
|
64
62
|
def build
|
65
63
|
@app_name = "MyWebApp"
|
66
64
|
@version = "2.1.0"
|
67
|
-
@port = ENV.fetch(
|
65
|
+
@port = ENV.fetch("PORT", 3000).to_i
|
68
66
|
end
|
69
67
|
end
|
70
68
|
|
@@ -73,7 +71,7 @@ class Application < Taski::Task
|
|
73
71
|
def build
|
74
72
|
puts "Starting #{AppConfig.app_name} v#{AppConfig.version}"
|
75
73
|
puts "Database: #{Environment.database_url}"
|
76
|
-
puts "Redis: #{Environment.redis_config ||
|
74
|
+
puts "Redis: #{Environment.redis_config || "disabled"}"
|
77
75
|
puts "Port: #{AppConfig.port}"
|
78
76
|
end
|
79
77
|
|
@@ -86,24 +84,24 @@ end
|
|
86
84
|
puts "=== Complex Example ==="
|
87
85
|
|
88
86
|
puts "\n1. Development Environment (default):"
|
89
|
-
ENV.delete(
|
90
|
-
ENV.delete(
|
87
|
+
ENV.delete("RAILS_ENV")
|
88
|
+
ENV.delete("FEATURE_REDIS_CACHE")
|
91
89
|
Application.build
|
92
90
|
Application.reset!
|
93
91
|
|
94
92
|
puts "\n2. Test Environment:"
|
95
|
-
ENV[
|
93
|
+
ENV["RAILS_ENV"] = "test"
|
96
94
|
# Reset Environment to re-evaluate define blocks
|
97
95
|
Environment.reset!
|
98
96
|
Application.build
|
99
97
|
Application.reset!
|
100
98
|
|
101
99
|
puts "\n3. Production with Redis:"
|
102
|
-
ENV[
|
103
|
-
ENV[
|
100
|
+
ENV["RAILS_ENV"] = "production"
|
101
|
+
ENV["FEATURE_REDIS_CACHE"] = "true"
|
104
102
|
# Reset Environment to re-evaluate define blocks
|
105
103
|
Environment.reset!
|
106
104
|
Application.build
|
107
105
|
|
108
106
|
puts "\n4. Cleanup:"
|
109
|
-
Application.clean
|
107
|
+
Application.clean
|
data/examples/readme_example.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# Quick Start example from README
|
3
3
|
|
4
|
-
require_relative
|
4
|
+
require_relative "../lib/taski"
|
5
5
|
|
6
6
|
# Simple static dependency using Exports API
|
7
7
|
class DatabaseSetup < Taski::Task
|
@@ -27,4 +27,4 @@ end
|
|
27
27
|
puts "=== Quick Start Example ==="
|
28
28
|
APIServer.build
|
29
29
|
|
30
|
-
puts "\nResult: APIServer running on port #{APIServer.port}"
|
30
|
+
puts "\nResult: APIServer running on port #{APIServer.port}"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "prism"
|
4
4
|
|
5
5
|
module Taski
|
6
6
|
module DependencyAnalyzer
|
@@ -19,13 +19,19 @@ module Taski
|
|
19
19
|
result = Prism.parse_file(file_path)
|
20
20
|
|
21
21
|
unless result.success?
|
22
|
-
|
22
|
+
Taski.logger.error("Parse errors in source file",
|
23
|
+
file: file_path,
|
24
|
+
errors: result.errors.map(&:message),
|
25
|
+
method: "#{klass}##{method_name}")
|
23
26
|
return []
|
24
27
|
end
|
25
28
|
|
26
29
|
# Handle warnings if present
|
27
30
|
if result.warnings.any?
|
28
|
-
warn
|
31
|
+
Taski.logger.warn("Parse warnings in source file",
|
32
|
+
file: file_path,
|
33
|
+
warnings: result.warnings.map(&:message),
|
34
|
+
method: "#{klass}##{method_name}")
|
29
35
|
end
|
30
36
|
|
31
37
|
dependencies = []
|
@@ -39,10 +45,17 @@ module Taski
|
|
39
45
|
|
40
46
|
dependencies.uniq
|
41
47
|
rescue IOError, SystemCallError => e
|
42
|
-
|
48
|
+
Taski.logger.error("Failed to read source file",
|
49
|
+
file: file_path,
|
50
|
+
error: e.message,
|
51
|
+
method: "#{klass}##{method_name}")
|
43
52
|
[]
|
44
53
|
rescue => e
|
45
|
-
|
54
|
+
Taski.logger.error("Failed to analyze method dependencies",
|
55
|
+
class: klass.name,
|
56
|
+
method: method_name,
|
57
|
+
error: e.message,
|
58
|
+
error_class: e.class.name)
|
46
59
|
[]
|
47
60
|
end
|
48
61
|
end
|
@@ -151,12 +164,9 @@ module Taski
|
|
151
164
|
else
|
152
165
|
child_name
|
153
166
|
end
|
154
|
-
else
|
155
|
-
nil
|
156
167
|
end
|
157
168
|
end
|
158
169
|
end
|
159
|
-
|
160
170
|
end
|
161
171
|
end
|
162
172
|
end
|
data/lib/taski/exceptions.rb
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module Taski
|
4
4
|
# Custom exceptions for Taski framework
|
5
|
-
|
5
|
+
|
6
6
|
# Raised when circular dependencies are detected between tasks
|
7
7
|
class CircularDependencyError < StandardError; end
|
8
|
-
|
8
|
+
|
9
9
|
# Raised when task analysis fails (e.g., constant resolution errors)
|
10
10
|
class TaskAnalysisError < StandardError; end
|
11
|
-
|
11
|
+
|
12
12
|
# Raised when task building fails during execution
|
13
13
|
class TaskBuildError < StandardError; end
|
14
|
-
end
|
14
|
+
end
|