66
77namespace Cortex . Streams . Operators
88{
9- public class SourceOperatorAdapter < TOutput > : IOperator , IHasNextOperators , ITelemetryEnabled
9+ /// <summary>
10+ /// Adapter that wraps an ISourceOperator to work within the operator chain.
11+ /// Handles telemetry, error handling, and lifecycle management for source operators.
12+ /// </summary>
13+ public class SourceOperatorAdapter < TOutput > : IOperator , IHasNextOperators , ITelemetryEnabled , IErrorHandlingEnabled
1014 {
1115 private readonly ISourceOperator < TOutput > _sourceOperator ;
1216 private IOperator _nextOperator ;
1317
18+ // Cached operator name to avoid string allocation on hot path
19+ private static readonly string OperatorName = $ "SourceOperatorAdapter<{ typeof ( TOutput ) . Name } >";
20+
1421 // Telemetry fields
1522 private ITelemetryProvider _telemetryProvider ;
1623 private ICounter _emittedCounter ;
@@ -19,11 +26,28 @@ public class SourceOperatorAdapter<TOutput> : IOperator, IHasNextOperators, ITel
1926 private Action _incrementEmittedCounter ;
2027 private Action < double > _recordEmissionTime ;
2128
29+ // Error handling fields
30+ private StreamExecutionOptions _executionOptions = StreamExecutionOptions . Default ;
31+
2232 public SourceOperatorAdapter ( ISourceOperator < TOutput > sourceOperator )
2333 {
2434 _sourceOperator = sourceOperator ;
2535 }
2636
37+ /// <summary>
38+ /// Sets the error handling options for this operator and propagates to next operators.
39+ /// </summary>
40+ public void SetErrorHandling ( StreamExecutionOptions options )
41+ {
42+ _executionOptions = options ?? StreamExecutionOptions . Default ;
43+
44+ // Propagate to the next operator if it supports error handling
45+ if ( _nextOperator is IErrorHandlingEnabled nextWithErrorHandling )
46+ {
47+ nextWithErrorHandling . SetErrorHandling ( _executionOptions ) ;
48+ }
49+ }
50+
2751 public void SetTelemetryProvider ( ITelemetryProvider telemetryProvider )
2852 {
2953 _telemetryProvider = telemetryProvider ;
@@ -67,6 +91,12 @@ public void SetNext(IOperator nextOperator)
6791 nextTelemetryEnabled . SetTelemetryProvider ( _telemetryProvider ) ;
6892 }
6993
94+ // Propagate error handling to the next operator
95+ if ( _nextOperator is IErrorHandlingEnabled nextWithErrorHandling && _executionOptions != null )
96+ {
97+ nextWithErrorHandling . SetErrorHandling ( _executionOptions ) ;
98+ }
99+
70100 // Start the source operator
71101 Start ( ) ;
72102 }
@@ -84,8 +114,15 @@ private void Start()
84114 try
85115 {
86116 _incrementEmittedCounter ? . Invoke ( ) ;
87- _nextOperator ? . Process ( output ) ;
88- span . SetAttribute ( "status" , "success" ) ;
117+
118+ // Use error handling helper to properly handle errors according to stream configuration
119+ var executed = ErrorHandlingHelper . TryExecute < TOutput > (
120+ _executionOptions ,
121+ OperatorName ,
122+ output ,
123+ item => _nextOperator ? . Process ( item ) ) ;
124+
125+ span . SetAttribute ( "status" , executed ? "success" : "skipped" ) ;
89126 }
90127 catch ( StreamStoppedException ex )
91128 {
@@ -99,6 +136,7 @@ private void Start()
99136 {
100137 span . SetAttribute ( "status" , "error" ) ;
101138 span . SetAttribute ( "exception" , ex . ToString ( ) ) ;
139+ // Re-throw to let the source operator handle it (e.g., logging, stopping)
102140 throw ;
103141 }
104142 finally
@@ -112,7 +150,12 @@ private void Start()
112150 {
113151 try
114152 {
115- _nextOperator ? . Process ( output ) ;
153+ // Use error handling helper to properly handle errors according to stream configuration
154+ ErrorHandlingHelper . TryExecute < TOutput > (
155+ _executionOptions ,
156+ OperatorName ,
157+ output ,
158+ item => _nextOperator ? . Process ( item ) ) ;
116159 }
117160 catch ( StreamStoppedException )
118161 {
0 commit comments