pipeline(task): since everything is async tasks should wait for EndFrame

This commit is contained in:
Aleix Conchillo Flaqué
2024-09-30 11:56:59 -07:00
parent e115a274d6
commit f64902eb25

View File

@@ -69,6 +69,19 @@ class Source(FrameProcessor):
await self._up_queue.put(StopTaskFrame()) await self._up_queue.put(StopTaskFrame())
class Sink(FrameProcessor):
def __init__(self, down_queue: asyncio.Queue):
super().__init__()
self._down_queue = down_queue
async def process_frame(self, frame: Frame, direction: FrameDirection):
await super().process_frame(frame, direction)
# We really just want to know when the EndFrame reached the sink.
if isinstance(frame, EndFrame):
await self._down_queue.put(frame)
class PipelineTask: class PipelineTask:
def __init__( def __init__(
self, self,
@@ -84,12 +97,16 @@ class PipelineTask:
self._params = params self._params = params
self._finished = False self._finished = False
self._down_queue = asyncio.Queue()
self._up_queue = asyncio.Queue() self._up_queue = asyncio.Queue()
self._down_queue = asyncio.Queue()
self._push_queue = asyncio.Queue()
self._source = Source(self._up_queue) self._source = Source(self._up_queue)
self._source.link(pipeline) self._source.link(pipeline)
self._sink = Sink(self._down_queue)
pipeline.link(self._sink)
def has_finished(self): def has_finished(self):
return self._finished return self._finished
@@ -103,19 +120,19 @@ class PipelineTask:
# out-of-band from the main streaming task which is what we want since # out-of-band from the main streaming task which is what we want since
# we want to cancel right away. # we want to cancel right away.
await self._source.push_frame(CancelFrame()) await self._source.push_frame(CancelFrame())
self._process_down_task.cancel() self._process_push_task.cancel()
self._process_up_task.cancel() self._process_up_task.cancel()
await self._process_down_task await self._process_push_task
await self._process_up_task await self._process_up_task
async def run(self): async def run(self):
self._process_up_task = asyncio.create_task(self._process_up_queue()) self._process_up_task = asyncio.create_task(self._process_up_queue())
self._process_down_task = asyncio.create_task(self._process_down_queue()) self._process_push_task = asyncio.create_task(self._process_push_queue())
await asyncio.gather(self._process_up_task, self._process_down_task) await asyncio.gather(self._process_up_task, self._process_push_task)
self._finished = True self._finished = True
async def queue_frame(self, frame: Frame): async def queue_frame(self, frame: Frame):
await self._down_queue.put(frame) await self._push_queue.put(frame)
async def queue_frames(self, frames: Iterable[Frame] | AsyncIterable[Frame]): async def queue_frames(self, frames: Iterable[Frame] | AsyncIterable[Frame]):
if isinstance(frames, AsyncIterable): if isinstance(frames, AsyncIterable):
@@ -133,7 +150,7 @@ class PipelineTask:
data.append(ProcessingMetricsData(processor=p.name, value=0.0)) data.append(ProcessingMetricsData(processor=p.name, value=0.0))
return MetricsFrame(data=data) return MetricsFrame(data=data)
async def _process_down_queue(self): async def _process_push_queue(self):
self._clock.start() self._clock.start()
start_frame = StartFrame( start_frame = StartFrame(
@@ -154,11 +171,13 @@ class PipelineTask:
should_cleanup = True should_cleanup = True
while running: while running:
try: try:
frame = await self._down_queue.get() frame = await self._push_queue.get()
await self._source.process_frame(frame, FrameDirection.DOWNSTREAM) await self._source.process_frame(frame, FrameDirection.DOWNSTREAM)
if isinstance(frame, EndFrame):
await self._wait_for_endframe()
running = not (isinstance(frame, StopTaskFrame) or isinstance(frame, EndFrame)) running = not (isinstance(frame, StopTaskFrame) or isinstance(frame, EndFrame))
should_cleanup = not isinstance(frame, StopTaskFrame) should_cleanup = not isinstance(frame, StopTaskFrame)
self._down_queue.task_done() self._push_queue.task_done()
except asyncio.CancelledError: except asyncio.CancelledError:
break break
# Cleanup only if we need to. # Cleanup only if we need to.
@@ -169,6 +188,12 @@ class PipelineTask:
self._process_up_task.cancel() self._process_up_task.cancel()
await self._process_up_task await self._process_up_task
async def _wait_for_endframe(self):
# NOTE(aleix): the Sink element just pushes EndFrames to the down queue,
# so just wait for it. In the future we might do something else here,
# but for now this is fine.
await self._down_queue.get()
async def _process_up_queue(self): async def _process_up_queue(self):
while True: while True:
try: try: