Consumer Mixins Explained
This document explains how mixins are used in the consumer and how method dispatch works in practice.
What a mixin is
A mixin is a class that contributes behavior to another class through inheritance, without being a full standalone domain model.
In this project, mixins are used to keep fluentbit/client.py and abstract_client.py smaller by separating large behavior groups into focused files.
Where mixins are used
AbstractOpAMPClient is defined as:
class AbstractOpAMPClient(
ClientTransportAuthorizationMixin,
ClientRuntimeMixin,
ServerMessageHandlingMixin,
OpAMPClientInterface,
ABC,
):
...
The mixins are:
ClientTransportAuthorizationMixininconsumer/src/opamp_consumer/client_transport_auth_mixin.pyClientRuntimeMixininconsumer/src/opamp_consumer/client_runtime_mixin.pyServerMessageHandlingMixininconsumer/src/opamp_consumer/client_server_message_mixin.py
Compatibility re-export module:
consumer/src/opamp_consumer/client_mixins.py
Runtime lifecycle strategies
ClientRuntimeMixin now delegates process lifecycle operations to strategy classes selected from configuration:
ClientSupervisorMixininconsumer/src/opamp_consumer/client_supervisor_mixin.pyClientObserverMixininconsumer/src/opamp_consumer/client_observer_mixin.py
Selection behavior:
consumer.processTrackingvalues:Supervisor(default)Observer
- Observer mode requires
consumer.processDetectionRegex
What each mixin owns
ClientTransportAuthorizationMixin owns outbound transport/auth behavior:
- transport send orchestration (
send,send_http,send_websocket) - auth header resolution (
none,env-var,config-var,idp) - retry-on-auth-failure behavior for
401/403
ClientRuntimeMixin owns runtime/process and polling behavior:
- lifecycle delegation (
launch_agent_process,terminate_agent_process,restart_agent_process) - local status polling (
poll_local_status_with_codes) - version discovery (
add_agent_version) - heartbeat loop (
_heartbeat_loop) - explicit awaited shutdown (
send_disconnect,finalize_async) - synchronous compatibility shutdown (
finalize)
Callers already running an event loop should await finalize_async() so the
disconnect attempt finishes before shutdown continues. Synchronous callers can
use finalize(), which runs cleanup directly when no loop exists and schedules
it on the caller’s active loop otherwise. Object destruction only disables the
local heartbeat flag; it does not start network I/O or a background thread.
ServerMessageHandlingMixin owns provider message handling:
- top-level dispatch (
_handle_server_to_agent) - reply validation (
_validate_reply_instance_uid) - handlers for server payload sections (
handle_*) - custom message dispatch to registered handlers (
handle_custom_message)
AbstractOpAMPClient keeps cross-cutting client responsibilities:
- runtime data model setup (
OpAMPClientData) - full update controller wiring
- agent description/capability assembly helpers
- custom-handler registry setup
How method resolution works
Python looks for methods in MRO order (Method Resolution Order). For OpAMPClient, that order starts:
OpAMPClientAbstractOpAMPClientClientTransportAuthorizationMixinClientRuntimeMixinServerMessageHandlingMixinOpAMPClientInterfaceABCobject
Practical impact:
send()resolves inClientTransportAuthorizationMixin._heartbeat_loop()resolves inClientRuntimeMixin._handle_server_to_agent()resolves inServerMessageHandlingMixin.
How runtime strategy dispatch works
When ClientRuntimeMixin.launch_agent_process() is called:
- runtime mixin resolves lifecycle strategy lazily (
_runtime_lifecycle()). - strategy is selected from
config.process_tracking:supervisor->ClientSupervisorMixinobserver->ClientObserverMixin
- runtime mixin delegates the call to that strategy instance.
Lifecycle selection is cached per client instance.
Why this refactor helps
- keeps each file focused and easier to review
- cleanly separates transport/auth, runtime lifecycle, and server-message handling
- enables two process-management modes without branching every runtime method
- reduces merge conflict pressure in one large concrete client module
- provides clear extension points for additional lifecycle strategies
Related files
consumer/src/opamp_consumer/abstract_client.pyconsumer/src/opamp_consumer/client_transport_auth_mixin.pyconsumer/src/opamp_consumer/client_runtime_mixin.pyconsumer/src/opamp_consumer/client_supervisor_mixin.pyconsumer/src/opamp_consumer/client_observer_mixin.pyconsumer/src/opamp_consumer/client_server_message_mixin.pyconsumer/src/opamp_consumer/client_mixins.pyconsumer/src/opamp_consumer/fluentbit/client.pyconsumer/src/opamp_consumer/fluentd/client.py
OpAMP