Summary
Add timeout protection to dynamic preset imports in loadPreset to prevent the CLI from hanging indefinitely when a preset package has issues during module initialization.
Problem
Current implementation in packages/cli/src/loaders/presets.ts:
const module = yield* Effect.tryPromise({
try: () => import(name),
catch: error => new PresetLoadError({
preset: name,
message: `Failed to import: ${String(error)}`
})
})
Edge case: If a preset package:
- Has an infinite loop during initialization
- Makes a hanging network request
- Deadlocks on a resource
...the CLI will hang indefinitely with no feedback to the user.
Proposed Solution
Wrap the import with Effect.timeout:
const loadPreset = (name: string): Effect.Effect<Preset, PresetLoadError> =>
Effect.gen(function* () {
// Dynamically import preset module with timeout
const module = yield* Effect.tryPromise({
try: () => import(name),
catch: error =>
new PresetLoadError({
preset: name,
message: `Failed to import: ${String(error)}`
})
}).pipe(
Effect.timeout("5 seconds"), // Reasonable timeout for module loading
Effect.catchTag("TimeoutException", () =>
Effect.fail(
new PresetLoadError({
preset: name,
message: "Import timed out after 5 seconds (possible infinite loop or deadlock)"
})
)
)
)
// ... rest of validation
})
Configuration
Consider making timeout configurable:
// In config schema
presets: {
names: ReadonlyArray<string>
timeout?: number // milliseconds, default 5000
}
Benefits
- Prevents CLI from hanging indefinitely
- Provides clear error message to user
- Allows graceful fallback (warning + continue)
- Protects against malicious or buggy preset packages
Acceptance Criteria
Testing
it.effect("should timeout on slow preset import", () =>
Effect.gen(function* () {
// Mock preset that takes 10 seconds to load
const slowPreset = {
rules: [],
defaults: {}
}
// Should fail with timeout error
const result = yield* Effect.flip(loadPreset("slow-preset"))
expect(result).toBeInstanceOf(PresetLoadError)
expect(result.message).toContain("timed out")
})
)
Related
Summary
Add timeout protection to dynamic preset imports in
loadPresetto prevent the CLI from hanging indefinitely when a preset package has issues during module initialization.Problem
Current implementation in
packages/cli/src/loaders/presets.ts:Edge case: If a preset package:
...the CLI will hang indefinitely with no feedback to the user.
Proposed Solution
Wrap the import with
Effect.timeout:Configuration
Consider making timeout configurable:
Benefits
Acceptance Criteria
Effect.timeoutadded to preset importsPresetLoadErrorTesting
Related
effect/EffectloadPresets