Railway-Oriented Error Handling
Relevant source files
The following files were used as context for generating this wiki page:
Railway-Oriented Programming (ROP) is a core design principle within the flext-target-oracle project, primarily facilitated by the r (Result) pattern. This approach treats operations as a sequence of "tracks"—a "happy path" (success) and an "error path" (failure). Instead of using traditional exception-based control flow for expected operational issues, functions return a Result object that explicitly contains either the successful value or an error container.
This architecture ensures type safety and predictable error propagation across the Singer target implementation, from message parsing in the client to DDL/DML execution in the Oracle loader. By wrapping operations in Result objects, the system avoids deeply nested try-except blocks and provides a clear mechanism for recovery and logging.
Sources: CONTRIBUTING.md:143-145, examples/README.md:92-98, src/flext_target_oracle/_utilities/client.py:61-73
The Result (r) Pattern
The project utilizes flext_core.r as the primary vehicle for ROP. Every major internal method in the FlextTargetOracle and FlextTargetOracleLoader classes returns a p.Result[T]. This object provides boolean checks (is_success, is_failure) and methods to unwrap values or handle errors gracefully.
Operation Flow Diagram
This diagram illustrates how a Singer message moves through the system using ROP tracks.
The flow ensures that any failure at the parsing or processing stage immediately diverts the execution to the error track.
Sources: src/flext_target_oracle/_utilities/client.py:84-100, examples/README.md:94-98
Oracle Exception Hierarchy
While ROP is used for logical flow, the project maintains a structured exception hierarchy for terminal errors and metadata-rich reporting. These exceptions inherit from flext_core.FlextExceptionsBase and are mapped to specific Oracle error codes.
Exception Components
| Class Name | Base Type | Description |
|---|---|---|
FlextTargetOracleExceptions.Error | BaseError | Main base error for the Oracle target. |
ConfigurationError | e.ConfigurationError | Triggered by invalid settings or business rule violations. |
OracleConnectionError | e.ConnectionError | Includes context such as service_name, user, and dsn. |
AuthenticationError | e.AuthenticationError | Captures auth_method and wallet_location for Oracle security. |
ProcessingError | Error | Used during RECORD processing; captures stream_name and record_count. |
SchemaError | ValidationError | Captures schema_hash and specific validation_errors list. |
Sources: src/flext_target_oracle/_utilities/errors.py:48-155
Error Metadata Structure
The FlextTargetOracleErrorMetadata model is used to attach structured data to error responses, enabling cross-service correlation.
class FlextTargetOracleErrorMetadata(m.FlexibleInternalModel):
code: Annotated[str, u.Field(description="Canonical error code")]
context: Annotated[t.JsonMapping | None, u.Field(description="Structured context")] = None
correlation_id: Annotated[str | None, u.Field(description="Correlation ID")] = None
Sources: src/flext_target_oracle/_utilities/errors.py:24-38
Implementation in Loader and Client
The FlextTargetOracleLoader and FlextTargetOracle classes implement ROP by wrapping DDL/DML operations and Singer message routing.
Connection and Transaction Handling
The loader uses a with self.oracle_api context manager, but the entry and exit points are managed via Result objects to ensure that connection failures are caught and returned rather than raised as unhandled exceptions.
Batch Processing Failures
When flushing batches to Oracle, the loader builds insert parameters. If validation fails for a single record in a batch, the entire batch operation returns a Result.fail, which is then logged with metadata including the stream name and the specific validation error.
Key methods returning p.Result:
test_connection(): Validates Oracle connectivity._flush_batch(): Coordinates batch parameter building andexecute_manycalls.process_singer_message(): Routes messages to specific handlers (SCHEMA, RECORD, STATE).
Sources: src/flext_target_oracle/_utilities/loader.py:461-480, src/flext_target_oracle/_utilities/client.py:165-177, examples/01_basic_usage.py:164-175
Conclusion
Railway-Oriented Error Handling in flext-target-oracle provides a robust framework for managing the complexities of database integrations. By combining the r pattern for functional flow control with a rich, metadata-heavy exception hierarchy for reporting, the project achieves high resilience and observability. This ensures that data loading issues are captured, categorized (e.g., SchemaError vs ConnectionError), and reported without interrupting the target's ability to maintain state and provide diagnostic information.
Sources: CONTRIBUTING.md:143-150, src/flext_target_oracle/_utilities/errors.py:12-20