-
-
Notifications
You must be signed in to change notification settings - Fork 15
Open
Description
Summary
Module state is tracked through multiple overlapping mechanisms, making it unclear which source of truth to use and potentially allowing inconsistent states.
Current State Management
Location: src/ModularPipelines/Engine/Execution/
Multiple state tracking paths:
- ModuleExecutionContext - Tracks execution metadata
- ModuleState - Holds individual module status
- ModuleResult - Final result wrapper
- SubModuleTracker - Tracks sub-operations
Problems
- Multiple sources of truth: State can be checked in different places
- Unclear ownership: Which component owns state transitions?
- Mutation patterns: State changes happen through multiple channels
- Race condition risk: Concurrent access during error scenarios
- Testing difficulty: Hard to mock/verify state transitions
Current Flow (Simplified)
Module Starts → ModuleExecutionContext updated
↓
ModuleState set to Running
↓
Execution happens
↓
ModuleResult created
↓
ModuleState set to Success/Failed
↓
SubModuleTracker updated (if sub-modules exist)
Proposed Solutions
Option A: Immutable State Machine
public abstract record ModuleExecutionState
{
public sealed record Pending : ModuleExecutionState;
public sealed record Running(DateTime StartedAt) : ModuleExecutionState;
public sealed record Completed(DateTime StartedAt, DateTime EndedAt, object? Result) : ModuleExecutionState;
public sealed record Failed(DateTime StartedAt, DateTime EndedAt, Exception Error) : ModuleExecutionState;
public sealed record Skipped(string Reason) : ModuleExecutionState;
}Benefits:
- Clear state transitions
- Immutable = thread-safe
- Pattern matching for handling
- Compile-time exhaustiveness checks
Option B: Single State Owner
Consolidate all state into ModuleExecutionContext:
- Remove
ModuleStateas separate concept ModuleResultbecomes read-only projection- Clear single point of mutation
Option C: Event Sourcing (Lightweight)
public interface IModuleStateEvents
{
void Emit(ModuleStateEvent @event);
IReadOnlyList<ModuleStateEvent> GetHistory(IModule module);
}
public abstract record ModuleStateEvent(DateTime Timestamp);
public record ModuleStarted(DateTime Timestamp) : ModuleStateEvent(Timestamp);
public record ModuleCompleted(DateTime Timestamp, object? Result) : ModuleStateEvent(Timestamp);Recommended Approach
Option A (Immutable State Machine) provides the best balance of:
- Type safety
- Thread safety
- Explicit transitions
- Easy testing
Impact
- Breaking change: Internal refactoring, may affect extensions
- Improves: Reliability, testability, debugging
Labels
- v2.0
- architecture
- enhancement
Metadata
Metadata
Assignees
Labels
No labels