Skip to content

guidellm.utils.messaging

Inter-process messaging abstractions for distributed scheduler coordination.

Provides high-level interfaces for asynchronous message passing between worker processes using various transport mechanisms including queues and pipes. Supports configurable encoding, serialization, error handling, and flow control with buffering and stop event coordination for distributed scheduler operations.

ReceiveMessageT = TypeVar('ReceiveMessageT', bound=Any) module-attribute

Generic type variable for messages received through the messaging system

SendMessageT = TypeVar('SendMessageT', bound=Any) module-attribute

Generic type variable for messages sent through the messaging system

InterProcessMessaging

Bases: Generic[SendMessageT, ReceiveMessageT], ABC

Abstract base for inter-process messaging in distributed scheduler coordination.

Provides unified interface for asynchronous message passing between scheduler components using configurable transport mechanisms, encoding schemes, and flow control policies. Manages buffering, serialization, error handling, and coordinated shutdown across worker processes for distributed operations.

Example: :: from guidellm.utils.messaging import InterProcessMessagingQueue

messaging = InterProcessMessagingQueue(
    serialization="pickle",
    max_pending_size=100
)

await messaging.start()
await messaging.put(request_data)
response = await messaging.get(timeout=5.0)
await messaging.stop()
Source code in src/guidellm/utils/messaging.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
class InterProcessMessaging(Generic[SendMessageT, ReceiveMessageT], ABC):
    """
    Abstract base for inter-process messaging in distributed scheduler coordination.

    Provides unified interface for asynchronous message passing between scheduler
    components using configurable transport mechanisms, encoding schemes, and
    flow control policies. Manages buffering, serialization, error handling,
    and coordinated shutdown across worker processes for distributed operations.

    Example:
    ::
        from guidellm.utils.messaging import InterProcessMessagingQueue

        messaging = InterProcessMessagingQueue(
            serialization="pickle",
            max_pending_size=100
        )

        await messaging.start()
        await messaging.put(request_data)
        response = await messaging.get(timeout=5.0)
        await messaging.stop()
    """

    STOP_REQUIRED_QUEUE_EMPTY_COUNT: int = 3

    def __init__(
        self,
        mp_context: BaseContext | None = None,
        serialization: SerializationTypesAlias = "dict",
        encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
        max_pending_size: int | None = None,
        max_buffer_send_size: int | None = None,
        max_done_size: int | None = None,
        max_buffer_receive_size: int | None = None,
        poll_interval: float = 0.1,
        worker_index: int | None = None,
    ):
        """
        Initialize inter-process messaging coordinator.

        :param serialization: Message serialization method for transport encoding
        :param encoding: Optional encoding scheme for serialized message data
        :param max_pending_size: Maximum items in send queue before blocking
        :param max_buffer_send_size: Maximum items in buffer send queue
        :param max_done_size: Maximum items in done queue before blocking
        :param max_buffer_receive_size: Maximum items in buffer receive queue
        :param poll_interval: Time interval for checking queue status and events
        :param worker_index: Index identifying this worker in the process group
        """
        self.worker_index: int | None = worker_index
        self.mp_context = mp_context or multiprocessing.get_context()
        self.serialization = serialization
        self.encoding = encoding
        self.max_pending_size = max_pending_size
        self.max_buffer_send_size = max_buffer_send_size
        self.max_done_size = max_done_size
        self.max_buffer_receive_size = max_buffer_receive_size
        self.poll_interval = poll_interval

        self.send_stopped_event: ThreadingEvent | ProcessingEvent | None = None
        self.receive_stopped_event: ThreadingEvent | ProcessingEvent | None = None
        self.shutdown_event: ThreadingEvent | None = None
        self.buffer_send_queue: culsans.Queue[SendMessageT] | None = None
        self.buffer_receive_queue: culsans.Queue[ReceiveMessageT] | None = None
        self.receive_demand_event: ThreadingEvent | None = None
        self._receive_demand: int = 0
        self.send_task: asyncio.Task | None = None
        self.receive_task: asyncio.Task | None = None
        self.running = False

    @abstractmethod
    def create_worker_copy(
        self, worker_index: int, **kwargs
    ) -> InterProcessMessaging[ReceiveMessageT, SendMessageT]:
        """
        Create worker-specific copy for distributed process coordination.

        :param worker_index: Index of the worker process for message routing
        :return: Configured messaging instance for the specified worker
        """
        ...

    @abstractmethod
    def create_send_messages_threads(
        self,
        send_items: Iterable[Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ) -> list[tuple[Callable, tuple[Any, ...]]]:
        """
        Create send message processing threads for transport implementation.

        :param send_items: Optional collection of items to send during processing
        :param message_encoding: Message encoding configuration for serialization
        :param check_stop: Callable for evaluating stop conditions during processing
        :return: List of thread callables with their arguments for execution
        """
        ...

    @abstractmethod
    def create_receive_messages_threads(
        self,
        receive_callback: Callable[[Any], Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ) -> list[tuple[Callable, tuple[Any, ...]]]:
        """
        Create receive message processing threads for transport implementation.

        :param receive_callback: Optional callback for processing received messages
        :param message_encoding: Message encoding configuration for deserialization
        :param check_stop: Callable for evaluating stop conditions during processing
        :return: List of thread callables with their arguments for execution
        """
        ...

    async def start(
        self,
        send_items: Iterable[Any] | None = None,
        receive_callback: Callable[[Any], Any] | None = None,
        send_stop_criteria: (
            list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
        ) = None,
        send_stopped_event: ThreadingEvent | ProcessingEvent | None = None,
        receive_stop_criteria: (
            list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
        ) = None,
        receive_stopped_event: ThreadingEvent | ProcessingEvent | None = None,
        pydantic_models: list[type[BaseModel]] | None = None,
    ):
        """
        Start asynchronous message processing tasks with buffering.

        :param send_items: Optional collection of items to send during processing
        :param receive_callback: Optional callback for processing received messages
        :param send_stop_criteria: Events and callables that trigger send task shutdown
        :param send_stopped_event: Event set when send task has fully stopped
        :param receive_stop_criteria: Events and callables that trigger receive shutdown
        :param receive_stopped_event: Event set when receive task has fully stopped
        :param pydantic_models: Optional list of Pydantic models for serialization
        """
        self.running = True
        self.send_stopped_event = send_stopped_event or ThreadingEvent()
        self.receive_stopped_event = receive_stopped_event or ThreadingEvent()
        self.shutdown_event = ThreadingEvent()
        self.buffer_send_queue = culsans.Queue[SendMessageT](
            maxsize=self.max_buffer_send_size or 0
        )
        self.buffer_receive_queue = culsans.Queue[ReceiveMessageT](
            maxsize=self.max_buffer_receive_size or 0
        )
        self.receive_demand_event = ThreadingEvent()
        self._receive_demand = 0

        message_encoding: MessageEncoding = MessageEncoding(
            serialization=self.serialization,
            encoding=self.encoding,
            pydantic_models=pydantic_models,
        )
        send_stop_criteria = send_stop_criteria or []
        receive_stop_events = receive_stop_criteria or []

        self.send_task = asyncio.create_task(
            self.send_messages_coroutine(
                send_items=send_items,
                message_encoding=message_encoding,
                send_stop_criteria=send_stop_criteria,
            )
        )
        self.receive_task = asyncio.create_task(
            self.receive_messages_coroutine(
                receive_callback=receive_callback,
                message_encoding=message_encoding,
                receive_stop_criteria=receive_stop_events,
            )
        )

    async def stop(self):
        """
        Stop message processing tasks and clean up resources.
        """
        if self.shutdown_event is not None:
            self.shutdown_event.set()
        else:
            raise RuntimeError(
                "shutdown_event is not set; was start() not called or "
                "is this a redundant stop() call?"
            )
        tasks = [self.send_task, self.receive_task]
        tasks_to_run: list[asyncio.Task[Any]] = [
            task for task in tasks if task is not None
        ]
        if len(tasks_to_run) > 0:
            with contextlib.suppress(asyncio.CancelledError):
                await asyncio.gather(*tasks_to_run, return_exceptions=True)
        self.send_task = None
        self.receive_task = None
        if self.worker_index is None:
            if self.buffer_send_queue is not None:
                self.buffer_send_queue.clear()
                await self.buffer_send_queue.aclose()
            if self.buffer_receive_queue is not None:
                self.buffer_receive_queue.clear()
                await self.buffer_receive_queue.aclose()
        self.buffer_send_queue = None
        self.buffer_receive_queue = None
        self.receive_demand_event = None
        self.send_stopped_event = None
        self.receive_stopped_event = None
        self.shutdown_event = None
        self.running = False

    async def send_messages_coroutine(
        self,
        send_items: Iterable[Any] | None,
        message_encoding: MessageEncoding,
        send_stop_criteria: (
            list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
        ),
    ):
        """
        Execute send message processing with encoding and stop condition handling.

        :param send_items: Optional collection of items to send during processing
        :param message_encoding: Message encoding configuration for serialization
        :param send_stop_criteria: Events and callables that trigger send task shutdown
        """
        canceled_event = ThreadingEvent()

        try:
            await asyncio.gather(
                *[
                    asyncio.to_thread(thread, *args)
                    for (thread, args) in self.create_send_messages_threads(
                        send_items=send_items,
                        message_encoding=message_encoding,
                        check_stop=self._create_check_stop_callable(
                            send_stop_criteria, canceled_event
                        ),
                    )
                ]
            )
        except asyncio.CancelledError:
            canceled_event.set()
            raise
        finally:
            if self.send_stopped_event is not None:
                self.send_stopped_event.set()

    async def receive_messages_coroutine(
        self,
        receive_callback: Callable[[Any], Any] | None,
        message_encoding: MessageEncoding,
        receive_stop_criteria: (
            list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
        ),
    ):
        """
        Execute receive message processing with decoding and callback handling.

        :param receive_callback: Optional callback for processing received messages
        :param message_encoding: Message encoding configuration for deserialization
        :param receive_stop_criteria: Events and callables that trigger receive shutdown
        """
        canceled_event = ThreadingEvent()

        try:
            await asyncio.gather(
                *[
                    asyncio.to_thread(thread, *args)
                    for thread, args in self.create_receive_messages_threads(
                        receive_callback=receive_callback,
                        message_encoding=message_encoding,
                        check_stop=self._create_check_stop_callable(
                            receive_stop_criteria, canceled_event
                        ),
                    )
                ]
            )
        except asyncio.CancelledError:
            canceled_event.set()
            raise
        finally:
            if self.receive_stopped_event is not None:
                self.receive_stopped_event.set()

    async def get(self, timeout: float | None = None) -> ReceiveMessageT:
        """
        Retrieve a message from receive buffer with optional timeout.

        :param timeout: Maximum time to wait for a message
        :return: Decoded message from the receive buffer
        """
        if self.buffer_receive_queue is None:
            raise RuntimeError(
                "buffer receive queue is None; check start()/stop() calls"
            )
        self._signal_receive_demand()
        try:
            return await asyncio.wait_for(
                self.buffer_receive_queue.async_get(), timeout=timeout
            )
        finally:
            self._receive_demand -= 1

    def get_sync(self, timeout: float | None = None) -> ReceiveMessageT:
        """
        Retrieve message from receive buffer synchronously with optional timeout.

        :param timeout: Maximum time to wait for a message, if <=0 uses get_nowait
        :return: Decoded message from the receive buffer
        """
        if self.buffer_receive_queue is None:
            raise RuntimeError(
                "buffer receive queue is None; check start()/stop() calls"
            )
        self._signal_receive_demand()
        try:
            if timeout is not None and timeout <= 0:
                return self.buffer_receive_queue.get_nowait()
            else:
                return self.buffer_receive_queue.sync_get(timeout=timeout)
        finally:
            self._receive_demand -= 1

    async def put(self, item: SendMessageT, timeout: float | None = None):
        """
        Add message to send buffer with optional timeout.

        :param item: Message item to add to the send buffer
        :param timeout: Maximum time to wait for buffer space
        """
        if self.buffer_send_queue is None:
            raise RuntimeError(
                "buffer receive queue is None; check start()/stop() calls"
            )
        await asyncio.wait_for(self.buffer_send_queue.async_put(item), timeout=timeout)

    def put_sync(self, item: SendMessageT, timeout: float | None = None):
        """
        Add message to send buffer synchronously with optional timeout.

        :param item: Message item to add to the send buffer
        :param timeout: Maximum time to wait for buffer space, if <=0 uses put_nowait
        """
        if self.buffer_send_queue is None:
            raise RuntimeError(
                "buffer receive queue is None; check start()/stop() calls"
            )
        if timeout is not None and timeout <= 0:
            self.buffer_send_queue.put_nowait(item)
        else:
            self.buffer_send_queue.sync_put(item, timeout=timeout)

    def _signal_receive_demand(self):
        """
        Register a consumer waiting on the receive buffer and wake the receive
        thread so it can fetch a message for it.
        """
        self._receive_demand += 1
        if self.receive_demand_event is not None:
            self.receive_demand_event.set()

    def _has_receive_demand(self) -> bool:
        """
        Check whether a consumer is waiting on the receive buffer for a message
        that is not already buffered.

        :return: True if more consumers are waiting than messages are buffered
        """
        if self.buffer_receive_queue is None:
            return False

        return self._receive_demand > self.buffer_receive_queue.qsize()

    def _create_check_stop_callable(
        self,
        stop_criteria: (
            list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
        ),
        canceled_event: ThreadingEvent,
    ):
        stop_events = tuple(
            item
            for item in stop_criteria or []
            if isinstance(item, ThreadingEvent | ProcessingEvent)
        )
        stop_callbacks = tuple(item for item in stop_criteria or [] if callable(item))

        def check_stop(pending: bool, queue_empty_count: int) -> bool:
            if canceled_event.is_set():
                return True

            if stop_callbacks and any(
                cb(self, pending, queue_empty_count) for cb in stop_callbacks
            ):
                return True

            if self.shutdown_event is None:
                return True

            return (
                not pending
                and queue_empty_count >= self.STOP_REQUIRED_QUEUE_EMPTY_COUNT
                and (
                    self.shutdown_event.is_set()
                    or any(event.is_set() for event in stop_events)
                )
            )

        return check_stop

__init__(mp_context=None, serialization='dict', encoding=None, max_pending_size=None, max_buffer_send_size=None, max_done_size=None, max_buffer_receive_size=None, poll_interval=0.1, worker_index=None)

Initialize inter-process messaging coordinator.

Parameters:

Name Type Description Default
serialization SerializationTypesAlias

Message serialization method for transport encoding

'dict'
encoding EncodingTypesAlias | list[EncodingTypesAlias]

Optional encoding scheme for serialized message data

None
max_pending_size int | None

Maximum items in send queue before blocking

None
max_buffer_send_size int | None

Maximum items in buffer send queue

None
max_done_size int | None

Maximum items in done queue before blocking

None
max_buffer_receive_size int | None

Maximum items in buffer receive queue

None
poll_interval float

Time interval for checking queue status and events

0.1
worker_index int | None

Index identifying this worker in the process group

None
Source code in src/guidellm/utils/messaging.py
def __init__(
    self,
    mp_context: BaseContext | None = None,
    serialization: SerializationTypesAlias = "dict",
    encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
    max_pending_size: int | None = None,
    max_buffer_send_size: int | None = None,
    max_done_size: int | None = None,
    max_buffer_receive_size: int | None = None,
    poll_interval: float = 0.1,
    worker_index: int | None = None,
):
    """
    Initialize inter-process messaging coordinator.

    :param serialization: Message serialization method for transport encoding
    :param encoding: Optional encoding scheme for serialized message data
    :param max_pending_size: Maximum items in send queue before blocking
    :param max_buffer_send_size: Maximum items in buffer send queue
    :param max_done_size: Maximum items in done queue before blocking
    :param max_buffer_receive_size: Maximum items in buffer receive queue
    :param poll_interval: Time interval for checking queue status and events
    :param worker_index: Index identifying this worker in the process group
    """
    self.worker_index: int | None = worker_index
    self.mp_context = mp_context or multiprocessing.get_context()
    self.serialization = serialization
    self.encoding = encoding
    self.max_pending_size = max_pending_size
    self.max_buffer_send_size = max_buffer_send_size
    self.max_done_size = max_done_size
    self.max_buffer_receive_size = max_buffer_receive_size
    self.poll_interval = poll_interval

    self.send_stopped_event: ThreadingEvent | ProcessingEvent | None = None
    self.receive_stopped_event: ThreadingEvent | ProcessingEvent | None = None
    self.shutdown_event: ThreadingEvent | None = None
    self.buffer_send_queue: culsans.Queue[SendMessageT] | None = None
    self.buffer_receive_queue: culsans.Queue[ReceiveMessageT] | None = None
    self.receive_demand_event: ThreadingEvent | None = None
    self._receive_demand: int = 0
    self.send_task: asyncio.Task | None = None
    self.receive_task: asyncio.Task | None = None
    self.running = False

create_receive_messages_threads(receive_callback, message_encoding, check_stop) abstractmethod

Create receive message processing threads for transport implementation.

Parameters:

Name Type Description Default
receive_callback Callable[[Any], Any] | None

Optional callback for processing received messages

required
message_encoding MessageEncoding

Message encoding configuration for deserialization

required
check_stop CheckStopCallableT

Callable for evaluating stop conditions during processing

required

Returns:

Type Description
list[tuple[Callable, tuple[Any, ...]]]

List of thread callables with their arguments for execution

Source code in src/guidellm/utils/messaging.py
@abstractmethod
def create_receive_messages_threads(
    self,
    receive_callback: Callable[[Any], Any] | None,
    message_encoding: MessageEncoding,
    check_stop: CheckStopCallableT,
) -> list[tuple[Callable, tuple[Any, ...]]]:
    """
    Create receive message processing threads for transport implementation.

    :param receive_callback: Optional callback for processing received messages
    :param message_encoding: Message encoding configuration for deserialization
    :param check_stop: Callable for evaluating stop conditions during processing
    :return: List of thread callables with their arguments for execution
    """
    ...

create_send_messages_threads(send_items, message_encoding, check_stop) abstractmethod

Create send message processing threads for transport implementation.

Parameters:

Name Type Description Default
send_items Iterable[Any] | None

Optional collection of items to send during processing

required
message_encoding MessageEncoding

Message encoding configuration for serialization

required
check_stop CheckStopCallableT

Callable for evaluating stop conditions during processing

required

Returns:

Type Description
list[tuple[Callable, tuple[Any, ...]]]

List of thread callables with their arguments for execution

Source code in src/guidellm/utils/messaging.py
@abstractmethod
def create_send_messages_threads(
    self,
    send_items: Iterable[Any] | None,
    message_encoding: MessageEncoding,
    check_stop: CheckStopCallableT,
) -> list[tuple[Callable, tuple[Any, ...]]]:
    """
    Create send message processing threads for transport implementation.

    :param send_items: Optional collection of items to send during processing
    :param message_encoding: Message encoding configuration for serialization
    :param check_stop: Callable for evaluating stop conditions during processing
    :return: List of thread callables with their arguments for execution
    """
    ...

create_worker_copy(worker_index, **kwargs) abstractmethod

Create worker-specific copy for distributed process coordination.

Parameters:

Name Type Description Default
worker_index int

Index of the worker process for message routing

required

Returns:

Type Description
InterProcessMessaging[ReceiveMessageT, SendMessageT]

Configured messaging instance for the specified worker

Source code in src/guidellm/utils/messaging.py
@abstractmethod
def create_worker_copy(
    self, worker_index: int, **kwargs
) -> InterProcessMessaging[ReceiveMessageT, SendMessageT]:
    """
    Create worker-specific copy for distributed process coordination.

    :param worker_index: Index of the worker process for message routing
    :return: Configured messaging instance for the specified worker
    """
    ...

get(timeout=None) async

Retrieve a message from receive buffer with optional timeout.

Parameters:

Name Type Description Default
timeout float | None

Maximum time to wait for a message

None

Returns:

Type Description
ReceiveMessageT

Decoded message from the receive buffer

Source code in src/guidellm/utils/messaging.py
async def get(self, timeout: float | None = None) -> ReceiveMessageT:
    """
    Retrieve a message from receive buffer with optional timeout.

    :param timeout: Maximum time to wait for a message
    :return: Decoded message from the receive buffer
    """
    if self.buffer_receive_queue is None:
        raise RuntimeError(
            "buffer receive queue is None; check start()/stop() calls"
        )
    self._signal_receive_demand()
    try:
        return await asyncio.wait_for(
            self.buffer_receive_queue.async_get(), timeout=timeout
        )
    finally:
        self._receive_demand -= 1

get_sync(timeout=None)

Retrieve message from receive buffer synchronously with optional timeout.

Parameters:

Name Type Description Default
timeout float | None

Maximum time to wait for a message, if <=0 uses get_nowait

None

Returns:

Type Description
ReceiveMessageT

Decoded message from the receive buffer

Source code in src/guidellm/utils/messaging.py
def get_sync(self, timeout: float | None = None) -> ReceiveMessageT:
    """
    Retrieve message from receive buffer synchronously with optional timeout.

    :param timeout: Maximum time to wait for a message, if <=0 uses get_nowait
    :return: Decoded message from the receive buffer
    """
    if self.buffer_receive_queue is None:
        raise RuntimeError(
            "buffer receive queue is None; check start()/stop() calls"
        )
    self._signal_receive_demand()
    try:
        if timeout is not None and timeout <= 0:
            return self.buffer_receive_queue.get_nowait()
        else:
            return self.buffer_receive_queue.sync_get(timeout=timeout)
    finally:
        self._receive_demand -= 1

put(item, timeout=None) async

Add message to send buffer with optional timeout.

Parameters:

Name Type Description Default
item SendMessageT

Message item to add to the send buffer

required
timeout float | None

Maximum time to wait for buffer space

None
Source code in src/guidellm/utils/messaging.py
async def put(self, item: SendMessageT, timeout: float | None = None):
    """
    Add message to send buffer with optional timeout.

    :param item: Message item to add to the send buffer
    :param timeout: Maximum time to wait for buffer space
    """
    if self.buffer_send_queue is None:
        raise RuntimeError(
            "buffer receive queue is None; check start()/stop() calls"
        )
    await asyncio.wait_for(self.buffer_send_queue.async_put(item), timeout=timeout)

put_sync(item, timeout=None)

Add message to send buffer synchronously with optional timeout.

Parameters:

Name Type Description Default
item SendMessageT

Message item to add to the send buffer

required
timeout float | None

Maximum time to wait for buffer space, if <=0 uses put_nowait

None
Source code in src/guidellm/utils/messaging.py
def put_sync(self, item: SendMessageT, timeout: float | None = None):
    """
    Add message to send buffer synchronously with optional timeout.

    :param item: Message item to add to the send buffer
    :param timeout: Maximum time to wait for buffer space, if <=0 uses put_nowait
    """
    if self.buffer_send_queue is None:
        raise RuntimeError(
            "buffer receive queue is None; check start()/stop() calls"
        )
    if timeout is not None and timeout <= 0:
        self.buffer_send_queue.put_nowait(item)
    else:
        self.buffer_send_queue.sync_put(item, timeout=timeout)

receive_messages_coroutine(receive_callback, message_encoding, receive_stop_criteria) async

Execute receive message processing with decoding and callback handling.

Parameters:

Name Type Description Default
receive_callback Callable[[Any], Any] | None

Optional callback for processing received messages

required
message_encoding MessageEncoding

Message encoding configuration for deserialization

required
receive_stop_criteria list[Event | Event | MessagingStopCallback] | None

Events and callables that trigger receive shutdown

required
Source code in src/guidellm/utils/messaging.py
async def receive_messages_coroutine(
    self,
    receive_callback: Callable[[Any], Any] | None,
    message_encoding: MessageEncoding,
    receive_stop_criteria: (
        list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
    ),
):
    """
    Execute receive message processing with decoding and callback handling.

    :param receive_callback: Optional callback for processing received messages
    :param message_encoding: Message encoding configuration for deserialization
    :param receive_stop_criteria: Events and callables that trigger receive shutdown
    """
    canceled_event = ThreadingEvent()

    try:
        await asyncio.gather(
            *[
                asyncio.to_thread(thread, *args)
                for thread, args in self.create_receive_messages_threads(
                    receive_callback=receive_callback,
                    message_encoding=message_encoding,
                    check_stop=self._create_check_stop_callable(
                        receive_stop_criteria, canceled_event
                    ),
                )
            ]
        )
    except asyncio.CancelledError:
        canceled_event.set()
        raise
    finally:
        if self.receive_stopped_event is not None:
            self.receive_stopped_event.set()

send_messages_coroutine(send_items, message_encoding, send_stop_criteria) async

Execute send message processing with encoding and stop condition handling.

Parameters:

Name Type Description Default
send_items Iterable[Any] | None

Optional collection of items to send during processing

required
message_encoding MessageEncoding

Message encoding configuration for serialization

required
send_stop_criteria list[Event | Event | MessagingStopCallback] | None

Events and callables that trigger send task shutdown

required
Source code in src/guidellm/utils/messaging.py
async def send_messages_coroutine(
    self,
    send_items: Iterable[Any] | None,
    message_encoding: MessageEncoding,
    send_stop_criteria: (
        list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
    ),
):
    """
    Execute send message processing with encoding and stop condition handling.

    :param send_items: Optional collection of items to send during processing
    :param message_encoding: Message encoding configuration for serialization
    :param send_stop_criteria: Events and callables that trigger send task shutdown
    """
    canceled_event = ThreadingEvent()

    try:
        await asyncio.gather(
            *[
                asyncio.to_thread(thread, *args)
                for (thread, args) in self.create_send_messages_threads(
                    send_items=send_items,
                    message_encoding=message_encoding,
                    check_stop=self._create_check_stop_callable(
                        send_stop_criteria, canceled_event
                    ),
                )
            ]
        )
    except asyncio.CancelledError:
        canceled_event.set()
        raise
    finally:
        if self.send_stopped_event is not None:
            self.send_stopped_event.set()

start(send_items=None, receive_callback=None, send_stop_criteria=None, send_stopped_event=None, receive_stop_criteria=None, receive_stopped_event=None, pydantic_models=None) async

Start asynchronous message processing tasks with buffering.

Parameters:

Name Type Description Default
send_items Iterable[Any] | None

Optional collection of items to send during processing

None
receive_callback Callable[[Any], Any] | None

Optional callback for processing received messages

None
send_stop_criteria list[Event | Event | MessagingStopCallback] | None

Events and callables that trigger send task shutdown

None
send_stopped_event Event | Event | None

Event set when send task has fully stopped

None
receive_stop_criteria list[Event | Event | MessagingStopCallback] | None

Events and callables that trigger receive shutdown

None
receive_stopped_event Event | Event | None

Event set when receive task has fully stopped

None
pydantic_models list[type[BaseModel]] | None

Optional list of Pydantic models for serialization

None
Source code in src/guidellm/utils/messaging.py
async def start(
    self,
    send_items: Iterable[Any] | None = None,
    receive_callback: Callable[[Any], Any] | None = None,
    send_stop_criteria: (
        list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
    ) = None,
    send_stopped_event: ThreadingEvent | ProcessingEvent | None = None,
    receive_stop_criteria: (
        list[ThreadingEvent | ProcessingEvent | MessagingStopCallback] | None
    ) = None,
    receive_stopped_event: ThreadingEvent | ProcessingEvent | None = None,
    pydantic_models: list[type[BaseModel]] | None = None,
):
    """
    Start asynchronous message processing tasks with buffering.

    :param send_items: Optional collection of items to send during processing
    :param receive_callback: Optional callback for processing received messages
    :param send_stop_criteria: Events and callables that trigger send task shutdown
    :param send_stopped_event: Event set when send task has fully stopped
    :param receive_stop_criteria: Events and callables that trigger receive shutdown
    :param receive_stopped_event: Event set when receive task has fully stopped
    :param pydantic_models: Optional list of Pydantic models for serialization
    """
    self.running = True
    self.send_stopped_event = send_stopped_event or ThreadingEvent()
    self.receive_stopped_event = receive_stopped_event or ThreadingEvent()
    self.shutdown_event = ThreadingEvent()
    self.buffer_send_queue = culsans.Queue[SendMessageT](
        maxsize=self.max_buffer_send_size or 0
    )
    self.buffer_receive_queue = culsans.Queue[ReceiveMessageT](
        maxsize=self.max_buffer_receive_size or 0
    )
    self.receive_demand_event = ThreadingEvent()
    self._receive_demand = 0

    message_encoding: MessageEncoding = MessageEncoding(
        serialization=self.serialization,
        encoding=self.encoding,
        pydantic_models=pydantic_models,
    )
    send_stop_criteria = send_stop_criteria or []
    receive_stop_events = receive_stop_criteria or []

    self.send_task = asyncio.create_task(
        self.send_messages_coroutine(
            send_items=send_items,
            message_encoding=message_encoding,
            send_stop_criteria=send_stop_criteria,
        )
    )
    self.receive_task = asyncio.create_task(
        self.receive_messages_coroutine(
            receive_callback=receive_callback,
            message_encoding=message_encoding,
            receive_stop_criteria=receive_stop_events,
        )
    )

stop() async

Stop message processing tasks and clean up resources.

Source code in src/guidellm/utils/messaging.py
async def stop(self):
    """
    Stop message processing tasks and clean up resources.
    """
    if self.shutdown_event is not None:
        self.shutdown_event.set()
    else:
        raise RuntimeError(
            "shutdown_event is not set; was start() not called or "
            "is this a redundant stop() call?"
        )
    tasks = [self.send_task, self.receive_task]
    tasks_to_run: list[asyncio.Task[Any]] = [
        task for task in tasks if task is not None
    ]
    if len(tasks_to_run) > 0:
        with contextlib.suppress(asyncio.CancelledError):
            await asyncio.gather(*tasks_to_run, return_exceptions=True)
    self.send_task = None
    self.receive_task = None
    if self.worker_index is None:
        if self.buffer_send_queue is not None:
            self.buffer_send_queue.clear()
            await self.buffer_send_queue.aclose()
        if self.buffer_receive_queue is not None:
            self.buffer_receive_queue.clear()
            await self.buffer_receive_queue.aclose()
    self.buffer_send_queue = None
    self.buffer_receive_queue = None
    self.receive_demand_event = None
    self.send_stopped_event = None
    self.receive_stopped_event = None
    self.shutdown_event = None
    self.running = False

InterProcessMessagingManagerQueue

Bases: InterProcessMessagingQueue[SendMessageT, ReceiveMessageT]

Manager-based queue messaging for inter-process scheduler coordination.

Extends queue-based messaging with multiprocessing.Manager support for shared state coordination across worker processes. Provides managed queues for reliable message passing in distributed scheduler environments with enhanced process synchronization and resource management capabilities.

Example: :: import multiprocessing from guidellm.utils.messaging import InterProcessMessagingManagerQueue

manager = multiprocessing.Manager()
messaging = InterProcessMessagingManagerQueue(
    manager=manager,
    serialization="pickle"
)
Source code in src/guidellm/utils/messaging.py
class InterProcessMessagingManagerQueue(
    InterProcessMessagingQueue[SendMessageT, ReceiveMessageT]
):
    """
    Manager-based queue messaging for inter-process scheduler coordination.

    Extends queue-based messaging with multiprocessing.Manager support for
    shared state coordination across worker processes. Provides managed queues
    for reliable message passing in distributed scheduler environments with
    enhanced process synchronization and resource management capabilities.

    Example:
    ::
        import multiprocessing
        from guidellm.utils.messaging import InterProcessMessagingManagerQueue

        manager = multiprocessing.Manager()
        messaging = InterProcessMessagingManagerQueue(
            manager=manager,
            serialization="pickle"
        )
    """

    def __init__(
        self,
        manager: SyncManager,
        mp_context: BaseContext | None = None,
        serialization: SerializationTypesAlias = "dict",
        encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
        max_pending_size: int | None = None,
        max_buffer_send_size: int | None = None,
        max_done_size: int | None = None,
        max_buffer_receive_size: int | None = None,
        poll_interval: float = 0.1,
        worker_index: int | None = None,
        pending_queue: multiprocessing.Queue | None = None,
        done_queue: multiprocessing.Queue | None = None,
    ):
        """
        Initialize manager-based queue messaging for inter-process communication.

        :param manager: Multiprocessing manager for shared queue creation
        :param serialization: Message serialization method for transport encoding
        :param encoding: Optional encoding scheme for serialized message data
        :param max_pending_size: Maximum items in send queue before blocking
        :param max_buffer_send_size: Maximum items in buffer send queue
        :param max_done_size: Maximum items in receive queue before blocking
        :param max_buffer_receive_size: Maximum items in buffer receive queue
        :param poll_interval: Time interval for checking queue status and events
        :param worker_index: Index identifying this worker in the process group
        :param pending_queue: Managed multiprocessing queue for sending messages
        :param done_queue: Managed multiprocessing queue for receiving completed
            messages
        """
        super().__init__(
            mp_context=mp_context,
            serialization=serialization,
            encoding=encoding,
            max_pending_size=max_pending_size,
            max_buffer_send_size=max_buffer_send_size,
            max_done_size=max_done_size,
            max_buffer_receive_size=max_buffer_receive_size,
            poll_interval=poll_interval,
            worker_index=worker_index,
            pending_queue=pending_queue or manager.Queue(maxsize=max_pending_size or 0),
            done_queue=done_queue or manager.Queue(maxsize=max_done_size or 0),
        )

    def create_worker_copy(
        self, worker_index: int, **kwargs
    ) -> InterProcessMessagingManagerQueue[ReceiveMessageT, SendMessageT]:
        """
        Create worker-specific copy for managed queue-based coordination.

        :param worker_index: Index of the worker process for message routing
        :return: Configured manager queue messaging instance for the specified worker
        """
        copy_args = {
            "manager": None,
            "mp_context": self.mp_context,
            "serialization": self.serialization,
            "encoding": self.encoding,
            "max_pending_size": self.max_pending_size,
            "max_buffer_send_size": self.max_buffer_send_size,
            "max_done_size": self.max_done_size,
            "max_buffer_receive_size": self.max_buffer_receive_size,
            "poll_interval": self.poll_interval,
            "worker_index": worker_index,
            "pending_queue": self.pending_queue,
            "done_queue": self.done_queue,
        }
        final_args = {**copy_args, **kwargs}

        return InterProcessMessagingManagerQueue(**final_args)

    async def stop(self):
        """
        Stop the messaging system and wait for all tasks to complete.
        """
        await InterProcessMessaging.stop(self)
        self.pending_queue = None
        self.done_queue = None

__init__(manager, mp_context=None, serialization='dict', encoding=None, max_pending_size=None, max_buffer_send_size=None, max_done_size=None, max_buffer_receive_size=None, poll_interval=0.1, worker_index=None, pending_queue=None, done_queue=None)

Initialize manager-based queue messaging for inter-process communication.

Parameters:

Name Type Description Default
manager SyncManager

Multiprocessing manager for shared queue creation

required
serialization SerializationTypesAlias

Message serialization method for transport encoding

'dict'
encoding EncodingTypesAlias | list[EncodingTypesAlias]

Optional encoding scheme for serialized message data

None
max_pending_size int | None

Maximum items in send queue before blocking

None
max_buffer_send_size int | None

Maximum items in buffer send queue

None
max_done_size int | None

Maximum items in receive queue before blocking

None
max_buffer_receive_size int | None

Maximum items in buffer receive queue

None
poll_interval float

Time interval for checking queue status and events

0.1
worker_index int | None

Index identifying this worker in the process group

None
pending_queue Queue | None

Managed multiprocessing queue for sending messages

None
done_queue Queue | None

Managed multiprocessing queue for receiving completed messages

None
Source code in src/guidellm/utils/messaging.py
def __init__(
    self,
    manager: SyncManager,
    mp_context: BaseContext | None = None,
    serialization: SerializationTypesAlias = "dict",
    encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
    max_pending_size: int | None = None,
    max_buffer_send_size: int | None = None,
    max_done_size: int | None = None,
    max_buffer_receive_size: int | None = None,
    poll_interval: float = 0.1,
    worker_index: int | None = None,
    pending_queue: multiprocessing.Queue | None = None,
    done_queue: multiprocessing.Queue | None = None,
):
    """
    Initialize manager-based queue messaging for inter-process communication.

    :param manager: Multiprocessing manager for shared queue creation
    :param serialization: Message serialization method for transport encoding
    :param encoding: Optional encoding scheme for serialized message data
    :param max_pending_size: Maximum items in send queue before blocking
    :param max_buffer_send_size: Maximum items in buffer send queue
    :param max_done_size: Maximum items in receive queue before blocking
    :param max_buffer_receive_size: Maximum items in buffer receive queue
    :param poll_interval: Time interval for checking queue status and events
    :param worker_index: Index identifying this worker in the process group
    :param pending_queue: Managed multiprocessing queue for sending messages
    :param done_queue: Managed multiprocessing queue for receiving completed
        messages
    """
    super().__init__(
        mp_context=mp_context,
        serialization=serialization,
        encoding=encoding,
        max_pending_size=max_pending_size,
        max_buffer_send_size=max_buffer_send_size,
        max_done_size=max_done_size,
        max_buffer_receive_size=max_buffer_receive_size,
        poll_interval=poll_interval,
        worker_index=worker_index,
        pending_queue=pending_queue or manager.Queue(maxsize=max_pending_size or 0),
        done_queue=done_queue or manager.Queue(maxsize=max_done_size or 0),
    )

create_worker_copy(worker_index, **kwargs)

Create worker-specific copy for managed queue-based coordination.

Parameters:

Name Type Description Default
worker_index int

Index of the worker process for message routing

required

Returns:

Type Description
InterProcessMessagingManagerQueue[ReceiveMessageT, SendMessageT]

Configured manager queue messaging instance for the specified worker

Source code in src/guidellm/utils/messaging.py
def create_worker_copy(
    self, worker_index: int, **kwargs
) -> InterProcessMessagingManagerQueue[ReceiveMessageT, SendMessageT]:
    """
    Create worker-specific copy for managed queue-based coordination.

    :param worker_index: Index of the worker process for message routing
    :return: Configured manager queue messaging instance for the specified worker
    """
    copy_args = {
        "manager": None,
        "mp_context": self.mp_context,
        "serialization": self.serialization,
        "encoding": self.encoding,
        "max_pending_size": self.max_pending_size,
        "max_buffer_send_size": self.max_buffer_send_size,
        "max_done_size": self.max_done_size,
        "max_buffer_receive_size": self.max_buffer_receive_size,
        "poll_interval": self.poll_interval,
        "worker_index": worker_index,
        "pending_queue": self.pending_queue,
        "done_queue": self.done_queue,
    }
    final_args = {**copy_args, **kwargs}

    return InterProcessMessagingManagerQueue(**final_args)

stop() async

Stop the messaging system and wait for all tasks to complete.

Source code in src/guidellm/utils/messaging.py
async def stop(self):
    """
    Stop the messaging system and wait for all tasks to complete.
    """
    await InterProcessMessaging.stop(self)
    self.pending_queue = None
    self.done_queue = None

InterProcessMessagingPipe

Bases: InterProcessMessaging[SendMessageT, ReceiveMessageT]

Pipe-based inter-process messaging for distributed scheduler coordination.

Provides message passing using multiprocessing.Pipe objects for direct communication between scheduler workers and main process. Offers lower latency than queue-based messaging with duplex communication channels for high-performance distributed operations.

Example: :: from guidellm.utils.messaging import InterProcessMessagingPipe

messaging = InterProcessMessagingPipe(
    num_workers=4,
    serialization="pickle",
    poll_interval=0.05
)

# Create worker copy for specific worker process
worker_messaging = messaging.create_worker_copy(worker_index=0)
Source code in src/guidellm/utils/messaging.py
class InterProcessMessagingPipe(InterProcessMessaging[SendMessageT, ReceiveMessageT]):
    """
    Pipe-based inter-process messaging for distributed scheduler coordination.

    Provides message passing using multiprocessing.Pipe objects for direct
    communication between scheduler workers and main process. Offers lower
    latency than queue-based messaging with duplex communication channels
    for high-performance distributed operations.

    Example:
    ::
        from guidellm.utils.messaging import InterProcessMessagingPipe

        messaging = InterProcessMessagingPipe(
            num_workers=4,
            serialization="pickle",
            poll_interval=0.05
        )

        # Create worker copy for specific worker process
        worker_messaging = messaging.create_worker_copy(worker_index=0)
    """

    def __init__(
        self,
        num_workers: int,
        mp_context: BaseContext | None = None,
        serialization: SerializationTypesAlias = "dict",
        encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
        max_pending_size: int | None = None,
        max_buffer_send_size: int | None = None,
        max_done_size: int | None = None,
        max_buffer_receive_size: int | None = None,
        poll_interval: float = 0.1,
        worker_index: int | None = None,
        pipe: tuple[Connection, Connection] | None = None,
    ):
        """
        Initialize pipe-based messaging for inter-process communication.

        :param num_workers: Number of worker processes requiring pipe connections
        :param serialization: Message serialization method for transport encoding
        :param encoding: Optional encoding scheme for serialized message data
        :param max_pending_size: Maximum items in send queue before blocking
        :param max_buffer_send_size: Maximum items in buffer send queue
        :param max_done_size: Maximum items in receive queue before blocking
        :param max_buffer_receive_size: Maximum items in buffer receive queue
        :param poll_interval: Time interval for checking queue status and events
        :param worker_index: Index identifying this worker in the process group
        :param pipe: Existing pipe connection for worker-specific instances
        """
        super().__init__(
            mp_context=mp_context,
            serialization=serialization,
            encoding=encoding,
            max_pending_size=max_pending_size,
            max_buffer_send_size=max_buffer_send_size,
            max_done_size=max_done_size,
            max_buffer_receive_size=max_buffer_receive_size,
            poll_interval=poll_interval,
            worker_index=worker_index,
        )
        self.num_workers = num_workers

        self.pipes: list[tuple[Connection, Connection]]
        if pipe is None:
            self.pipes = [self.mp_context.Pipe(duplex=True) for _ in range(num_workers)]
        else:
            self.pipes = [pipe]

    def create_worker_copy(
        self, worker_index: int, **kwargs
    ) -> InterProcessMessagingPipe[ReceiveMessageT, SendMessageT]:
        """
        Create worker-specific copy for pipe-based coordination.

        :param worker_index: Index of the worker process for pipe routing
        :return: Configured pipe messaging instance for the specified worker
        """
        copy_args = {
            "num_workers": self.num_workers,
            "mp_context": self.mp_context,
            "serialization": self.serialization,
            "encoding": self.encoding,
            "max_pending_size": self.max_pending_size,
            "max_buffer_send_size": self.max_buffer_send_size,
            "max_done_size": self.max_done_size,
            "max_buffer_receive_size": self.max_buffer_receive_size,
            "poll_interval": self.poll_interval,
            "worker_index": worker_index,
            "pipe": self.pipes[worker_index],
        }

        final_args = {**copy_args, **kwargs}

        return InterProcessMessagingPipe(**final_args)

    async def stop(self):
        """
        Stop the messaging system and wait for all tasks to complete.
        """
        await super().stop()
        if self.worker_index is None:
            # Only main process should close the pipes
            for main_con, worker_con in self.pipes:
                main_con.close()
                worker_con.close()

    def create_send_messages_threads(
        self,
        send_items: Iterable[Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ) -> list[tuple[Callable, tuple[Any, ...]]]:
        """
        Create send message processing threads for pipe-based transport.

        :param send_items: Optional collection of items to send during processing
        :param message_encoding: Message encoding configuration for serialization
        :param check_stop: Callable for evaluating stop conditions during processing
        :return: List of thread callables with their arguments for execution
        """
        if self.worker_index is None:
            # Create a separate task for each worker's pipe
            return [
                (
                    self._send_messages_task_thread,
                    (self.pipes[index], send_items, message_encoding, check_stop),
                )
                for index in range(self.num_workers)
            ]
        else:
            return [
                (
                    self._send_messages_task_thread,
                    (self.pipes[0], send_items, message_encoding, check_stop),
                )
            ]

    def create_receive_messages_threads(
        self,
        receive_callback: Callable[[Any], Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ) -> list[tuple[Callable, tuple[Any, ...]]]:
        """
        Create receive message processing threads for pipe-based transport.

        :param receive_callback: Optional callback for processing received messages
        :param message_encoding: Message encoding configuration for deserialization
        :param check_stop: Callable for evaluating stop conditions during processing
        :return: List of thread callables with their arguments for execution
        """
        if self.worker_index is None:
            # Create a separate task for each worker's pipe
            return [
                (
                    self._receive_messages_task_thread,
                    (self.pipes[index], receive_callback, message_encoding, check_stop),
                )
                for index in range(self.num_workers)
            ]
        else:
            return [
                (
                    self._receive_messages_task_thread,
                    (self.pipes[0], receive_callback, message_encoding, check_stop),
                )
            ]

    def _send_messages_task_thread(  # noqa: C901, PLR0912, PLR0915
        self,
        pipe: tuple[Connection, Connection],
        send_items: Iterable[Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ):
        local_stop = ThreadingEvent()
        send_connection: Connection = pipe[0] if self.worker_index is None else pipe[1]
        send_items_iter = iter(send_items) if send_items is not None else None
        pending_item = None
        queue_empty_count = 0
        pipe_item = None
        pipe_lock = threading.Lock()

        def _background_pipe_recv():
            nonlocal pipe_item

            while not local_stop.is_set():
                try:
                    with pipe_lock:
                        pending = pipe_item
                        pipe_item = None

                    if pending is not None:
                        send_connection.send(pending)
                except (EOFError, ConnectionResetError):
                    break

        if send_items_iter is None:
            threading.Thread(target=_background_pipe_recv, daemon=True).start()

        try:
            while not check_stop(pending_item is not None, queue_empty_count):
                if pending_item is None:
                    try:
                        if send_items_iter is not None:
                            item = next(send_items_iter)
                        else:
                            if self.buffer_send_queue is None:
                                raise RuntimeError(
                                    "buffer_send_queue is None; check start()/stop() calls"  # noqa: E501
                                )
                            item = self.buffer_send_queue.sync_get(
                                timeout=self.poll_interval
                            )
                        pending_item = message_encoding.encode(item)
                        queue_empty_count = 0
                    except (culsans.QueueEmpty, queue.Empty, StopIteration):
                        queue_empty_count += 1

                if pending_item is not None:
                    try:
                        with pipe_lock:
                            if pipe_item is not None:
                                time.sleep(self.poll_interval / 100)
                                raise queue.Full
                            else:
                                pipe_item = pending_item
                        if send_items_iter is None:
                            if self.buffer_send_queue is None:
                                raise RuntimeError(
                                    "buffer_send_queue is None; check start()/stop() calls"  # noqa: E501
                                )
                            self.buffer_send_queue.task_done()
                        pending_item = None
                    except (culsans.QueueFull, queue.Full):
                        pass
        finally:
            local_stop.set()

    def _receive_messages_task_thread(  # noqa: C901
        self,
        pipe: tuple[Connection, Connection],
        receive_callback: Callable[[Any], Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ):
        receive_connection: Connection = (
            pipe[0] if self.worker_index is not None else pipe[1]
        )
        pending_item = None
        received_item = None
        queue_empty_count = 0

        while not check_stop(pending_item is not None, queue_empty_count):
            if pending_item is None:
                try:
                    if receive_connection.poll(self.poll_interval):
                        item = receive_connection.recv()
                        pending_item = message_encoding.decode(item)
                    else:
                        raise queue.Empty
                    queue_empty_count = 0
                except (culsans.QueueEmpty, queue.Empty):
                    queue_empty_count += 1

            if pending_item is not None or received_item is not None:
                try:
                    if received_item is None:
                        received_item = (
                            pending_item
                            if not receive_callback
                            else receive_callback(pending_item)
                        )
                    if self.buffer_receive_queue is None:
                        raise RuntimeError(
                            "buffer receive queue is None; check start()/stop() calls"
                        )
                    self.buffer_receive_queue.sync_put(
                        cast("ReceiveMessageT", received_item)
                    )
                    pending_item = None
                    received_item = None
                except (culsans.QueueFull, queue.Full):
                    pass

__init__(num_workers, mp_context=None, serialization='dict', encoding=None, max_pending_size=None, max_buffer_send_size=None, max_done_size=None, max_buffer_receive_size=None, poll_interval=0.1, worker_index=None, pipe=None)

Initialize pipe-based messaging for inter-process communication.

Parameters:

Name Type Description Default
num_workers int

Number of worker processes requiring pipe connections

required
serialization SerializationTypesAlias

Message serialization method for transport encoding

'dict'
encoding EncodingTypesAlias | list[EncodingTypesAlias]

Optional encoding scheme for serialized message data

None
max_pending_size int | None

Maximum items in send queue before blocking

None
max_buffer_send_size int | None

Maximum items in buffer send queue

None
max_done_size int | None

Maximum items in receive queue before blocking

None
max_buffer_receive_size int | None

Maximum items in buffer receive queue

None
poll_interval float

Time interval for checking queue status and events

0.1
worker_index int | None

Index identifying this worker in the process group

None
pipe tuple[Connection, Connection] | None

Existing pipe connection for worker-specific instances

None
Source code in src/guidellm/utils/messaging.py
def __init__(
    self,
    num_workers: int,
    mp_context: BaseContext | None = None,
    serialization: SerializationTypesAlias = "dict",
    encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
    max_pending_size: int | None = None,
    max_buffer_send_size: int | None = None,
    max_done_size: int | None = None,
    max_buffer_receive_size: int | None = None,
    poll_interval: float = 0.1,
    worker_index: int | None = None,
    pipe: tuple[Connection, Connection] | None = None,
):
    """
    Initialize pipe-based messaging for inter-process communication.

    :param num_workers: Number of worker processes requiring pipe connections
    :param serialization: Message serialization method for transport encoding
    :param encoding: Optional encoding scheme for serialized message data
    :param max_pending_size: Maximum items in send queue before blocking
    :param max_buffer_send_size: Maximum items in buffer send queue
    :param max_done_size: Maximum items in receive queue before blocking
    :param max_buffer_receive_size: Maximum items in buffer receive queue
    :param poll_interval: Time interval for checking queue status and events
    :param worker_index: Index identifying this worker in the process group
    :param pipe: Existing pipe connection for worker-specific instances
    """
    super().__init__(
        mp_context=mp_context,
        serialization=serialization,
        encoding=encoding,
        max_pending_size=max_pending_size,
        max_buffer_send_size=max_buffer_send_size,
        max_done_size=max_done_size,
        max_buffer_receive_size=max_buffer_receive_size,
        poll_interval=poll_interval,
        worker_index=worker_index,
    )
    self.num_workers = num_workers

    self.pipes: list[tuple[Connection, Connection]]
    if pipe is None:
        self.pipes = [self.mp_context.Pipe(duplex=True) for _ in range(num_workers)]
    else:
        self.pipes = [pipe]

create_receive_messages_threads(receive_callback, message_encoding, check_stop)

Create receive message processing threads for pipe-based transport.

Parameters:

Name Type Description Default
receive_callback Callable[[Any], Any] | None

Optional callback for processing received messages

required
message_encoding MessageEncoding

Message encoding configuration for deserialization

required
check_stop CheckStopCallableT

Callable for evaluating stop conditions during processing

required

Returns:

Type Description
list[tuple[Callable, tuple[Any, ...]]]

List of thread callables with their arguments for execution

Source code in src/guidellm/utils/messaging.py
def create_receive_messages_threads(
    self,
    receive_callback: Callable[[Any], Any] | None,
    message_encoding: MessageEncoding,
    check_stop: CheckStopCallableT,
) -> list[tuple[Callable, tuple[Any, ...]]]:
    """
    Create receive message processing threads for pipe-based transport.

    :param receive_callback: Optional callback for processing received messages
    :param message_encoding: Message encoding configuration for deserialization
    :param check_stop: Callable for evaluating stop conditions during processing
    :return: List of thread callables with their arguments for execution
    """
    if self.worker_index is None:
        # Create a separate task for each worker's pipe
        return [
            (
                self._receive_messages_task_thread,
                (self.pipes[index], receive_callback, message_encoding, check_stop),
            )
            for index in range(self.num_workers)
        ]
    else:
        return [
            (
                self._receive_messages_task_thread,
                (self.pipes[0], receive_callback, message_encoding, check_stop),
            )
        ]

create_send_messages_threads(send_items, message_encoding, check_stop)

Create send message processing threads for pipe-based transport.

Parameters:

Name Type Description Default
send_items Iterable[Any] | None

Optional collection of items to send during processing

required
message_encoding MessageEncoding

Message encoding configuration for serialization

required
check_stop CheckStopCallableT

Callable for evaluating stop conditions during processing

required

Returns:

Type Description
list[tuple[Callable, tuple[Any, ...]]]

List of thread callables with their arguments for execution

Source code in src/guidellm/utils/messaging.py
def create_send_messages_threads(
    self,
    send_items: Iterable[Any] | None,
    message_encoding: MessageEncoding,
    check_stop: CheckStopCallableT,
) -> list[tuple[Callable, tuple[Any, ...]]]:
    """
    Create send message processing threads for pipe-based transport.

    :param send_items: Optional collection of items to send during processing
    :param message_encoding: Message encoding configuration for serialization
    :param check_stop: Callable for evaluating stop conditions during processing
    :return: List of thread callables with their arguments for execution
    """
    if self.worker_index is None:
        # Create a separate task for each worker's pipe
        return [
            (
                self._send_messages_task_thread,
                (self.pipes[index], send_items, message_encoding, check_stop),
            )
            for index in range(self.num_workers)
        ]
    else:
        return [
            (
                self._send_messages_task_thread,
                (self.pipes[0], send_items, message_encoding, check_stop),
            )
        ]

create_worker_copy(worker_index, **kwargs)

Create worker-specific copy for pipe-based coordination.

Parameters:

Name Type Description Default
worker_index int

Index of the worker process for pipe routing

required

Returns:

Type Description
InterProcessMessagingPipe[ReceiveMessageT, SendMessageT]

Configured pipe messaging instance for the specified worker

Source code in src/guidellm/utils/messaging.py
def create_worker_copy(
    self, worker_index: int, **kwargs
) -> InterProcessMessagingPipe[ReceiveMessageT, SendMessageT]:
    """
    Create worker-specific copy for pipe-based coordination.

    :param worker_index: Index of the worker process for pipe routing
    :return: Configured pipe messaging instance for the specified worker
    """
    copy_args = {
        "num_workers": self.num_workers,
        "mp_context": self.mp_context,
        "serialization": self.serialization,
        "encoding": self.encoding,
        "max_pending_size": self.max_pending_size,
        "max_buffer_send_size": self.max_buffer_send_size,
        "max_done_size": self.max_done_size,
        "max_buffer_receive_size": self.max_buffer_receive_size,
        "poll_interval": self.poll_interval,
        "worker_index": worker_index,
        "pipe": self.pipes[worker_index],
    }

    final_args = {**copy_args, **kwargs}

    return InterProcessMessagingPipe(**final_args)

stop() async

Stop the messaging system and wait for all tasks to complete.

Source code in src/guidellm/utils/messaging.py
async def stop(self):
    """
    Stop the messaging system and wait for all tasks to complete.
    """
    await super().stop()
    if self.worker_index is None:
        # Only main process should close the pipes
        for main_con, worker_con in self.pipes:
            main_con.close()
            worker_con.close()

InterProcessMessagingQueue

Bases: InterProcessMessaging[SendMessageT, ReceiveMessageT]

Queue-based inter-process messaging for distributed scheduler coordination.

Provides message passing using multiprocessing.Queue objects for communication between scheduler workers and main process. Handles message encoding, buffering, flow control, and coordinated shutdown with configurable queue behavior and error handling policies for distributed operations.

Example: :: from guidellm.utils.messaging import InterProcessMessagingQueue

messaging = InterProcessMessagingQueue(
    serialization="pickle",
    max_pending_size=100
)

# Create worker copy for distributed processing
worker_messaging = messaging.create_worker_copy(worker_index=0)
Source code in src/guidellm/utils/messaging.py
class InterProcessMessagingQueue(InterProcessMessaging[SendMessageT, ReceiveMessageT]):
    """
    Queue-based inter-process messaging for distributed scheduler coordination.

    Provides message passing using multiprocessing.Queue objects for communication
    between scheduler workers and main process. Handles message encoding, buffering,
    flow control, and coordinated shutdown with configurable queue behavior and
    error handling policies for distributed operations.

    Example:
    ::
        from guidellm.utils.messaging import InterProcessMessagingQueue

        messaging = InterProcessMessagingQueue(
            serialization="pickle",
            max_pending_size=100
        )

        # Create worker copy for distributed processing
        worker_messaging = messaging.create_worker_copy(worker_index=0)
    """

    pending_queue: multiprocessing.Queue | queue.Queue[Any] | None
    done_queue: multiprocessing.Queue | queue.Queue[Any] | None

    def __init__(
        self,
        mp_context: BaseContext | None = None,
        serialization: SerializationTypesAlias = "dict",
        encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
        max_pending_size: int | None = None,
        max_buffer_send_size: int | None = None,
        max_done_size: int | None = None,
        max_buffer_receive_size: int | None = None,
        poll_interval: float = 0.1,
        worker_index: int | None = None,
        pending_queue: multiprocessing.Queue | queue.Queue[Any] | None = None,
        done_queue: multiprocessing.Queue | queue.Queue[Any] | None = None,
    ):
        """
        Initialize queue-based messaging for inter-process communication.

        :param serialization: Message serialization method for transport encoding
        :param encoding: Optional encoding scheme for serialized message data
        :param max_pending_size: Maximum items in send queue before blocking
        :param max_buffer_send_size: Maximum items in buffer send queue
        :param max_done_size: Maximum items in receive queue before blocking
        :param max_buffer_receive_size: Maximum items in buffer receive queue
        :param poll_interval: Time interval for checking queue status and events
        :param worker_index: Index identifying this worker in the process group
        :param pending_queue: Multiprocessing queue for sending messages
        :param done_queue: Multiprocessing queue for receiving completed messages
        :param context: Multiprocessing context for creating queues
        """
        super().__init__(
            mp_context=mp_context,
            serialization=serialization,
            encoding=encoding,
            max_pending_size=max_pending_size,
            max_buffer_send_size=max_buffer_send_size,
            max_done_size=max_done_size,
            max_buffer_receive_size=max_buffer_receive_size,
            poll_interval=poll_interval,
            worker_index=worker_index,
        )
        self.pending_queue = pending_queue or self.mp_context.Queue(
            maxsize=max_pending_size or 0
        )
        self.done_queue = done_queue or self.mp_context.Queue(
            maxsize=max_done_size or 0
        )

    def create_worker_copy(
        self, worker_index: int, **kwargs
    ) -> InterProcessMessagingQueue[ReceiveMessageT, SendMessageT]:
        """
        Create worker-specific copy for distributed queue-based coordination.

        :param worker_index: Index of the worker process for message routing
        :return: Configured queue messaging instance for the specified worker
        """
        copy_args = {
            "mp_context": self.mp_context,
            "serialization": self.serialization,
            "encoding": self.encoding,
            "max_pending_size": self.max_pending_size,
            "max_buffer_send_size": self.max_buffer_send_size,
            "max_done_size": self.max_done_size,
            "max_buffer_receive_size": self.max_buffer_receive_size,
            "poll_interval": self.poll_interval,
            "worker_index": worker_index,
            "pending_queue": self.pending_queue,
            "done_queue": self.done_queue,
        }
        final_args = {**copy_args, **kwargs}

        return InterProcessMessagingQueue[ReceiveMessageT, SendMessageT](**final_args)

    async def stop(self):
        """
        Stop the messaging system and wait for all tasks to complete.
        """
        await super().stop()
        if self.worker_index is None:
            # only main process should close the queues
            if self.pending_queue is None:
                raise RuntimeError("pending_queue is None; was stop() already called?")
            with contextlib.suppress(queue.Empty):
                while True:
                    self.pending_queue.get_nowait()
            if hasattr(self.pending_queue, "close"):
                self.pending_queue.close()

            if self.done_queue is None:
                raise RuntimeError("done_queue is None; was stop() already called?")
            with contextlib.suppress(queue.Empty):
                while True:
                    self.done_queue.get_nowait()
            if hasattr(self.done_queue, "close"):
                self.done_queue.close()

        self.pending_queue = None
        self.done_queue = None

    def create_send_messages_threads(
        self,
        send_items: Iterable[Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ) -> list[tuple[Callable, tuple[Any, ...]]]:
        """
        Create send message processing threads for queue-based transport.

        :param send_items: Optional collection of items to send during processing
        :param message_encoding: Message encoding configuration for serialization
        :param check_stop: Callable for evaluating stop conditions during processing
        :return: List of thread callables with their arguments for execution
        """
        return [
            (
                self._send_messages_task_thread,
                (send_items, message_encoding, check_stop),
            )
        ]

    def create_receive_messages_threads(
        self,
        receive_callback: Callable[[Any], Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ) -> list[tuple[Callable, tuple[Any, ...]]]:
        """
        Create receive message processing threads for queue-based transport.

        :param receive_callback: Optional callback for processing received messages
        :param message_encoding: Message encoding configuration for deserialization
        :param check_stop: Callable for evaluating stop conditions during processing
        :return: List of thread callables with their arguments for execution
        """
        return [
            (
                self._receive_messages_task_thread,
                (receive_callback, message_encoding, check_stop),
            )
        ]

    def _send_messages_task_thread(  # noqa: C901, PLR0912
        self,
        send_items: Iterable[Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ):
        send_items_iter = iter(send_items) if send_items is not None else None
        pending_item = None
        queue_empty_count = 0

        while not check_stop(pending_item is not None, queue_empty_count):
            if pending_item is None:
                try:
                    if send_items_iter is not None:
                        item = next(send_items_iter)
                    else:
                        if self.buffer_send_queue is None:
                            raise RuntimeError(
                                "buffer_send_queue is None; was stop() already called?"
                            )
                        item = self.buffer_send_queue.sync_get(
                            timeout=self.poll_interval
                        )
                    pending_item = message_encoding.encode(item)
                    queue_empty_count = 0
                except (culsans.QueueEmpty, queue.Empty, StopIteration):
                    queue_empty_count += 1

            if pending_item is not None:
                try:
                    if self.worker_index is None:
                        # Main publisher
                        if self.pending_queue is None:
                            raise RuntimeError(
                                "pending_queue is None; was stop() already called?"
                            )
                        self.pending_queue.put(pending_item, timeout=self.poll_interval)
                    else:
                        # Worker
                        if self.done_queue is None:
                            raise RuntimeError(
                                "done_queue is None; was stop() already called?"
                            )
                        self.done_queue.put(pending_item, timeout=self.poll_interval)
                    if send_items_iter is None:
                        if self.buffer_send_queue is None:
                            raise RuntimeError(
                                "buffer_send_queue is None; was stop() already called?"
                            )
                        self.buffer_send_queue.task_done()
                    pending_item = None
                except (culsans.QueueFull, queue.Full):
                    pass

            time.sleep(0)  # Yield to other threads

    def _receive_messages_task_thread(  # noqa: C901, PLR0912
        self,
        receive_callback: Callable[[Any], Any] | None,
        message_encoding: MessageEncoding,
        check_stop: CheckStopCallableT,
    ):
        pending_item = None
        received_item = None
        queue_empty_count = 0

        while not check_stop(pending_item is not None, queue_empty_count):
            if pending_item is None:
                if self.worker_index is not None and not self._has_receive_demand():
                    # Worker: only take from the shared pending queue when a
                    # consumer is waiting. Otherwise the item is stuck in this
                    # worker's buffer while other workers with free capacity
                    # have nothing to process.
                    if self.shutdown_event is not None and self.shutdown_event.is_set():
                        # Count as an empty poll so check_stop can terminate
                        queue_empty_count += 1
                    elif self.receive_demand_event is not None:
                        # Block until a consumer signals demand (or poll interval)
                        self.receive_demand_event.clear()
                        if not self._has_receive_demand():
                            self.receive_demand_event.wait(timeout=self.poll_interval)
                    continue

                try:
                    if self.worker_index is None:
                        # Main publisher
                        if self.done_queue is None:
                            raise RuntimeError(
                                "done_queue is None; check start()/stop() calls"
                            )
                        item = self.done_queue.get(timeout=self.poll_interval)
                    else:
                        # Worker
                        if self.pending_queue is None:
                            raise RuntimeError(
                                "pending_queue is None; check start()/stop() calls"
                            )
                        # Queue.get holds the read lock while it polls, so a
                        # worker waiting on an empty queue blocks the others;
                        # keep that window short.
                        item = self.pending_queue.get(timeout=self.poll_interval / 10)
                    pending_item = message_encoding.decode(item)
                    queue_empty_count = 0
                except (culsans.QueueEmpty, queue.Empty):
                    queue_empty_count += 1

            if pending_item is not None or received_item is not None:
                try:
                    if received_item is None:
                        received_item = (
                            pending_item
                            if not receive_callback
                            else receive_callback(pending_item)
                        )

                    if self.buffer_receive_queue is None:
                        raise RuntimeError(
                            "buffer_receive_queue is None; check start()/stop() calls"
                        )
                    self.buffer_receive_queue.sync_put(
                        cast("ReceiveMessageT", received_item)
                    )
                    pending_item = None
                    received_item = None
                except (culsans.QueueFull, queue.Full):
                    pass

            time.sleep(0)  # Yield to other threads

__init__(mp_context=None, serialization='dict', encoding=None, max_pending_size=None, max_buffer_send_size=None, max_done_size=None, max_buffer_receive_size=None, poll_interval=0.1, worker_index=None, pending_queue=None, done_queue=None)

Initialize queue-based messaging for inter-process communication.

Parameters:

Name Type Description Default
serialization SerializationTypesAlias

Message serialization method for transport encoding

'dict'
encoding EncodingTypesAlias | list[EncodingTypesAlias]

Optional encoding scheme for serialized message data

None
max_pending_size int | None

Maximum items in send queue before blocking

None
max_buffer_send_size int | None

Maximum items in buffer send queue

None
max_done_size int | None

Maximum items in receive queue before blocking

None
max_buffer_receive_size int | None

Maximum items in buffer receive queue

None
poll_interval float

Time interval for checking queue status and events

0.1
worker_index int | None

Index identifying this worker in the process group

None
pending_queue Queue | Queue[Any] | None

Multiprocessing queue for sending messages

None
done_queue Queue | Queue[Any] | None

Multiprocessing queue for receiving completed messages

None
context

Multiprocessing context for creating queues

required
Source code in src/guidellm/utils/messaging.py
def __init__(
    self,
    mp_context: BaseContext | None = None,
    serialization: SerializationTypesAlias = "dict",
    encoding: EncodingTypesAlias | list[EncodingTypesAlias] = None,
    max_pending_size: int | None = None,
    max_buffer_send_size: int | None = None,
    max_done_size: int | None = None,
    max_buffer_receive_size: int | None = None,
    poll_interval: float = 0.1,
    worker_index: int | None = None,
    pending_queue: multiprocessing.Queue | queue.Queue[Any] | None = None,
    done_queue: multiprocessing.Queue | queue.Queue[Any] | None = None,
):
    """
    Initialize queue-based messaging for inter-process communication.

    :param serialization: Message serialization method for transport encoding
    :param encoding: Optional encoding scheme for serialized message data
    :param max_pending_size: Maximum items in send queue before blocking
    :param max_buffer_send_size: Maximum items in buffer send queue
    :param max_done_size: Maximum items in receive queue before blocking
    :param max_buffer_receive_size: Maximum items in buffer receive queue
    :param poll_interval: Time interval for checking queue status and events
    :param worker_index: Index identifying this worker in the process group
    :param pending_queue: Multiprocessing queue for sending messages
    :param done_queue: Multiprocessing queue for receiving completed messages
    :param context: Multiprocessing context for creating queues
    """
    super().__init__(
        mp_context=mp_context,
        serialization=serialization,
        encoding=encoding,
        max_pending_size=max_pending_size,
        max_buffer_send_size=max_buffer_send_size,
        max_done_size=max_done_size,
        max_buffer_receive_size=max_buffer_receive_size,
        poll_interval=poll_interval,
        worker_index=worker_index,
    )
    self.pending_queue = pending_queue or self.mp_context.Queue(
        maxsize=max_pending_size or 0
    )
    self.done_queue = done_queue or self.mp_context.Queue(
        maxsize=max_done_size or 0
    )

create_receive_messages_threads(receive_callback, message_encoding, check_stop)

Create receive message processing threads for queue-based transport.

Parameters:

Name Type Description Default
receive_callback Callable[[Any], Any] | None

Optional callback for processing received messages

required
message_encoding MessageEncoding

Message encoding configuration for deserialization

required
check_stop CheckStopCallableT

Callable for evaluating stop conditions during processing

required

Returns:

Type Description
list[tuple[Callable, tuple[Any, ...]]]

List of thread callables with their arguments for execution

Source code in src/guidellm/utils/messaging.py
def create_receive_messages_threads(
    self,
    receive_callback: Callable[[Any], Any] | None,
    message_encoding: MessageEncoding,
    check_stop: CheckStopCallableT,
) -> list[tuple[Callable, tuple[Any, ...]]]:
    """
    Create receive message processing threads for queue-based transport.

    :param receive_callback: Optional callback for processing received messages
    :param message_encoding: Message encoding configuration for deserialization
    :param check_stop: Callable for evaluating stop conditions during processing
    :return: List of thread callables with their arguments for execution
    """
    return [
        (
            self._receive_messages_task_thread,
            (receive_callback, message_encoding, check_stop),
        )
    ]

create_send_messages_threads(send_items, message_encoding, check_stop)

Create send message processing threads for queue-based transport.

Parameters:

Name Type Description Default
send_items Iterable[Any] | None

Optional collection of items to send during processing

required
message_encoding MessageEncoding

Message encoding configuration for serialization

required
check_stop CheckStopCallableT

Callable for evaluating stop conditions during processing

required

Returns:

Type Description
list[tuple[Callable, tuple[Any, ...]]]

List of thread callables with their arguments for execution

Source code in src/guidellm/utils/messaging.py
def create_send_messages_threads(
    self,
    send_items: Iterable[Any] | None,
    message_encoding: MessageEncoding,
    check_stop: CheckStopCallableT,
) -> list[tuple[Callable, tuple[Any, ...]]]:
    """
    Create send message processing threads for queue-based transport.

    :param send_items: Optional collection of items to send during processing
    :param message_encoding: Message encoding configuration for serialization
    :param check_stop: Callable for evaluating stop conditions during processing
    :return: List of thread callables with their arguments for execution
    """
    return [
        (
            self._send_messages_task_thread,
            (send_items, message_encoding, check_stop),
        )
    ]

create_worker_copy(worker_index, **kwargs)

Create worker-specific copy for distributed queue-based coordination.

Parameters:

Name Type Description Default
worker_index int

Index of the worker process for message routing

required

Returns:

Type Description
InterProcessMessagingQueue[ReceiveMessageT, SendMessageT]

Configured queue messaging instance for the specified worker

Source code in src/guidellm/utils/messaging.py
def create_worker_copy(
    self, worker_index: int, **kwargs
) -> InterProcessMessagingQueue[ReceiveMessageT, SendMessageT]:
    """
    Create worker-specific copy for distributed queue-based coordination.

    :param worker_index: Index of the worker process for message routing
    :return: Configured queue messaging instance for the specified worker
    """
    copy_args = {
        "mp_context": self.mp_context,
        "serialization": self.serialization,
        "encoding": self.encoding,
        "max_pending_size": self.max_pending_size,
        "max_buffer_send_size": self.max_buffer_send_size,
        "max_done_size": self.max_done_size,
        "max_buffer_receive_size": self.max_buffer_receive_size,
        "poll_interval": self.poll_interval,
        "worker_index": worker_index,
        "pending_queue": self.pending_queue,
        "done_queue": self.done_queue,
    }
    final_args = {**copy_args, **kwargs}

    return InterProcessMessagingQueue[ReceiveMessageT, SendMessageT](**final_args)

stop() async

Stop the messaging system and wait for all tasks to complete.

Source code in src/guidellm/utils/messaging.py
async def stop(self):
    """
    Stop the messaging system and wait for all tasks to complete.
    """
    await super().stop()
    if self.worker_index is None:
        # only main process should close the queues
        if self.pending_queue is None:
            raise RuntimeError("pending_queue is None; was stop() already called?")
        with contextlib.suppress(queue.Empty):
            while True:
                self.pending_queue.get_nowait()
        if hasattr(self.pending_queue, "close"):
            self.pending_queue.close()

        if self.done_queue is None:
            raise RuntimeError("done_queue is None; was stop() already called?")
        with contextlib.suppress(queue.Empty):
            while True:
                self.done_queue.get_nowait()
        if hasattr(self.done_queue, "close"):
            self.done_queue.close()

    self.pending_queue = None
    self.done_queue = None

MessagingStopCallback

Bases: Protocol

Protocol for evaluating stop conditions in messaging operations.

Source code in src/guidellm/utils/messaging.py
class MessagingStopCallback(Protocol):
    """Protocol for evaluating stop conditions in messaging operations."""

    def __call__(
        self, messaging: InterProcessMessaging, pending: bool, queue_empty_count: int
    ) -> bool:
        """
        Evaluate whether messaging operations should stop.

        :param messaging: The messaging instance to evaluate
        :param pending: Whether there are pending operations
        :param queue_empty_count: The number of times in a row the queue has been empty
        :return: True if operations should stop, False otherwise
        """
        ...

__call__(messaging, pending, queue_empty_count)

Evaluate whether messaging operations should stop.

Parameters:

Name Type Description Default
messaging InterProcessMessaging

The messaging instance to evaluate

required
pending bool

Whether there are pending operations

required
queue_empty_count int

The number of times in a row the queue has been empty

required

Returns:

Type Description
bool

True if operations should stop, False otherwise

Source code in src/guidellm/utils/messaging.py
def __call__(
    self, messaging: InterProcessMessaging, pending: bool, queue_empty_count: int
) -> bool:
    """
    Evaluate whether messaging operations should stop.

    :param messaging: The messaging instance to evaluate
    :param pending: Whether there are pending operations
    :param queue_empty_count: The number of times in a row the queue has been empty
    :return: True if operations should stop, False otherwise
    """
    ...