Middle
```python import asyncio from typing import List, Optional class Chunk: def __init__(self, items: List[dict]): self.items = items @property def size(self) -> int: return len(self.items) class Producer: async def next(self) -> Optional[Chunk]: # возвращает пачку данных или None ... async def commit(self, chunks: List[Chunk]) -> None: # фиксируем успешную обработку chunks ... class Consumer: max_batch_size = 100 async def consume(self, chunks: List[Chunk]) -> None: total_size = sum(chunk.size for chunk in chunks) if total_size > self.max_batch_size: raise ValueError("batch is too large") # обработка данных ... producer = Producer() consumer = Consumer() async def process(): while True: chunk = await producer.next() if chunk is None: break try: await consumer.consume([chunk]) await producer.commit([chunk]) except Exception as e: print("error but continue:", e) continue if __name__ == "__main__": asyncio.run(process()) ``` This code defines asynchronous producer-consumer classes with batch processing and error handling. The task is to implement or complete the logic for producing, consuming, and committing chunks of data, ensuring batch size limits are respected and errors are handled gracefully.
sobes.tech AI
Answer from AI
In the provided code, you need to implement the methods Producer.next(), Producer.commit(), and the processing logic in Consumer.consume().
Producer.next()should asynchronously return the nextChunkobject with data orNoneif there are no more data.Consumer.consume()checks that the total batch size does not exceedmax_batch_sizeand processes the data (e.g., saves or analyzes it).Producer.commit()confirms the successful processing of the batch, for example, by updating the status in a database.
An example implementation with data simulation:
import asyncio
from typing import List, Optional
class Chunk:
def __init__(self, items: List[dict]):
self.items = items
@property
def size(self) -> int:
return len(self.items)
class Producer:
def __init__(self):
self.data = [
[{'id': i} for i in range(30)],
[{'id': i} for i in range(50)],
[{'id': i} for i in range(120)], # too large chunk
[{'id': i} for i in range(20)],
]
self.index = 0
async def next(self) -> Optional[Chunk]:
await asyncio.sleep(0.1) # simulate delay
if self.index >= len(self.data):
return None
chunk = Chunk(self.data[self.index])
self.index += 1
return chunk
async def commit(self, chunks: List[Chunk]) -> None:
await asyncio.sleep(0.05) # simulate commit
print(f"Committed {sum(chunk.size for chunk in chunks)} items")
class Consumer:
max_batch_size = 100
async def consume(self, chunks: List[Chunk]) -> None:
total_size = sum(chunk.size for chunk in chunks)
if total_size > self.max_batch_size:
raise ValueError(f"batch is too large: {total_size} > {self.max_batch_size}")
await asyncio.sleep(0.1) # simulate processing
print(f"Consumed {total_size} items")
producer = Producer()
consumer = Consumer()
async def process():
while True:
chunk = await producer.next()
if chunk is None:
break
try:
await consumer.consume([chunk])
await producer.commit([chunk])
except Exception as e:
print("error but continue:", e)
continue
if __name__ == "__main__":
asyncio.run(process())
In this example, the third chunk exceeds the limit, causing an exception, which is handled to allow continuation with subsequent chunks.