The basic machinery is:
- An
Event
type - A
Client
that receives "inbound events" (responses from previous i/o) and emits "outbound events"; one core implementation - An
IOClient
that performs i/o based on outbound events and forms inbound events from i/o results; one implementation per i/o framework
Event
:
class InboundEvent:
pass
class OutboundEvent:
pass
class SubmitRequest(OutboundEvent):
pass
class SubmitResponse(InboundEvent):
pass
Client
:
class Record:
...
class Client:
def submit(self, data: Iterable[Record]) -> Iterable[OutboundEvent]:
""" Generate initial events from input data """
...
def handle(self, event: InboundEvent) -> Iterable[OutboundEvent]:
""" Handle inbound events, return corresponding outbound events """
...
IOClient
:
class IOClient:
def send(self, event: OutboundEvent) -> Iterable[InboundEvent]:
""" Perform i/o specified by an outbound event """
...
class AsyncIOClient:
async def asend(self, event: OutboundEvent) -> AsyncIterable[InboundEvent]:
""" Perform async i/o specified by an outbound event """
...
This would be for some kind of very-minimal non-async IO client, using a very basic system for queuing events.
from queue import Queue
from clientlib import Client
from clientlib.requests import IOClient
client = Client(key='hello')
io_client = IOClient()
input_data = [
(1, 2),
(3, 4),
]
event_queue = Queue()
for event in client.submit(input_data):
event_queue.push(event)
while True:
event0 = event_queue.pop()
response = io_client.send(event0)
for event in client.handle(response)
event_queue.push(event)