@@ -119,7 +119,7 @@ async def _sync_to_async_iterable() -> t.AsyncIterable[T]:
119
119
return _sync_to_async_iterable ()
120
120
121
121
122
- PipelineErrors = t .Literal ["strict " , "ignore" , "lazy_raise " ]
122
+ PipelineErrors = t .Literal ["eager " , "ignore" , "group " ]
123
123
124
124
125
125
class RateLimiter :
@@ -244,7 +244,7 @@ def _collect_result(self, task, next_):
244
244
return next_ ((task .order_tag , task .result ()))
245
245
# Hardcoded: exception - ignore.
246
246
logger .error ("Exception in pipelined stage: %s" , exc )
247
- self .parent .output .put_nowait ((EXC_MARKER , exc ))
247
+ self .parent .output .put_nowait ((EXC_MARKER , ( task . order_tag , exc ) ))
248
248
249
249
def _create_task (self , value : tuple [int , t .Any ]):
250
250
@@ -312,7 +312,7 @@ def __init__(
312
312
max_concurrency : t .Optional [int ] = None ,
313
313
rate_limit : None | RateLimiter | Real = None ,
314
314
rate_limit_unit : TIME_UNIT = "second" ,
315
- on_error : PipelineErrors = "strict " ,
315
+ on_error : PipelineErrors = "eager " ,
316
316
preserve_order : bool = False ,
317
317
max_simultaneous_records : t .Optional [int ] = None ,
318
318
sink : None | SupportsRShift | MutableSequence | MutableSet = None ,
@@ -326,7 +326,7 @@ def __init__(
326
326
(i.e. if there are 2 stages, and max_concurrency is set to 4, we may have
327
327
up to 8 concurrent tasks running at once in the pipeline, but each stage is
328
328
limited to 4)
329
- - on_error: WHat to do if any stage raises an exeception - defaults to re-raise the
329
+ - on_error: WHat to do if any stage raises an exception - defaults to re-raise the
330
330
exception and stop the whole pipeline
331
331
- rate_limit: An overall rate-limitting parameter which can be used to throtle all stages.
332
332
If anyone stage should have a limit different from the limit to the whole pipeline,
@@ -390,7 +390,7 @@ def chain_data(self, data_source):
390
390
# TBD
391
391
392
392
async def __aiter__ (self ):
393
- """Each iteration retrieves the next final result, after passing it trhough all teh stages
393
+ """Each iteration retrieves the next final result, after passing it trhough all the stages
394
394
395
395
NB: calling this a single time will trigger the Pipeline background execution, and
396
396
more than one item can be (or will be) fectched from source in a single iteration,
@@ -429,9 +429,11 @@ async def __aiter__(self):
429
429
if order_marker is EXC_MARKER :
430
430
if self .on_error == "ignore" :
431
431
await asyncio .sleep (0 )
432
+ if self .preserve_order :
433
+ self .ordered_results .push ((result_data [0 ], EXC_MARKER ))
432
434
continue
433
435
elif self .on_error == "strict" :
434
- raise result_data
436
+ raise result_data [ 1 ]
435
437
elif self .on_error == "lazy" :
436
438
raise NotImplementedError ("Lazy error raising in pipeline" )
437
439
if not self .preserve_order :
@@ -440,7 +442,8 @@ async def __aiter__(self):
440
442
self .ordered_results .push ((order_marker , result_data ))
441
443
if self .ordered_results .peek () == last_yielded_index + 1 :
442
444
last_yielded_index , result_data = self .ordered_results .pop ()
443
- yield result_data
445
+ if result_data is not EXC_MARKER :
446
+ yield result_data
444
447
445
448
await asyncio .sleep (0 )
446
449
0 commit comments