Skip to content

Commit 671d784

Browse files
committed
refactor: Type event_processor_class against the AsyncEventProcessor interface
Mirror how the sync Config types event_processor_class against the EventProcessor interface. Add an AsyncEventProcessor ABC to interfaces and reference it directly instead of the concrete implementation, which also removes the aiohttp-avoiding TYPE_CHECKING import.
1 parent 23ca0b6 commit 671d784

2 files changed

Lines changed: 37 additions & 8 deletions

File tree

ldclient/async_config.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
compatibility guarantees.
99
"""
1010

11-
from typing import TYPE_CHECKING, Callable, List, Optional, Set
11+
from typing import Callable, List, Optional, Set
1212

1313
from ldclient.config import (
1414
GET_LATEST_FEATURES_PATH,
@@ -28,16 +28,12 @@
2828
from ldclient.interfaces import (
2929
AsyncBigSegmentStore,
3030
AsyncDataSourceUpdateSink,
31+
AsyncEventProcessor,
3132
AsyncFeatureStore,
3233
UpdateProcessor
3334
)
3435
from ldclient.plugin import AsyncPlugin
3536

36-
if TYPE_CHECKING:
37-
# Imported for typing only. The concrete AsyncEventProcessor pulls in aiohttp
38-
# transitively, so it is kept out of the runtime import graph.
39-
from ldclient.impl.events.async_event_processor import AsyncEventProcessor
40-
4137

4238
class AsyncBigSegmentsConfig:
4339
"""Configuration options related to Big Segments for the async SDK client.
@@ -120,7 +116,7 @@ def __init__(
120116
use_ldd: bool = False,
121117
feature_store: Optional[AsyncFeatureStore] = None,
122118
feature_requester_class=None,
123-
event_processor_class: Optional[Callable[['AsyncConfig'], 'AsyncEventProcessor']] = None,
119+
event_processor_class: Optional[Callable[['AsyncConfig'], AsyncEventProcessor]] = None,
124120
private_attributes: Set[str] = set(),
125121
all_attributes_private: bool = False,
126122
offline: bool = False,
@@ -313,7 +309,7 @@ def feature_store(self) -> Optional[AsyncFeatureStore]:
313309
return self.__feature_store
314310

315311
@property
316-
def event_processor_class(self) -> Optional[Callable[['AsyncConfig'], 'AsyncEventProcessor']]:
312+
def event_processor_class(self) -> Optional[Callable[['AsyncConfig'], AsyncEventProcessor]]:
317313
return self.__event_processor_class
318314

319315
@property

ldclient/interfaces.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,39 @@ def stop(self):
484484
"""
485485

486486

487+
class AsyncEventProcessor(ABC):
488+
"""
489+
Async interface for the component that buffers analytics events and sends them to LaunchDarkly,
490+
for use with :class:`ldclient.async_client.AsyncLDClient`. It mirrors :class:`EventProcessor`,
491+
except ``stop`` is a coroutine. The default implementation can be replaced for testing.
492+
493+
.. caution::
494+
This feature is experimental and should NOT be considered ready for production
495+
use. It may change or be removed without notice and is not subject to backwards
496+
compatibility guarantees.
497+
"""
498+
499+
@abstractmethod
500+
def send_event(self, event):
501+
"""
502+
Processes an event to be sent at some point.
503+
"""
504+
505+
@abstractmethod
506+
def flush(self):
507+
"""
508+
Specifies that any buffered events should be sent as soon as possible, rather than waiting
509+
for the next flush interval. This method is not awaitable; calling ``stop()`` will deliver
510+
any events not yet sent prior to shutting down.
511+
"""
512+
513+
@abstractmethod
514+
async def stop(self):
515+
"""
516+
Shuts down the event processor after first delivering all pending events.
517+
"""
518+
519+
487520
class FeatureRequester(ABC):
488521
"""
489522
Interface for the component that acquires feature flag data in polling mode. The default

0 commit comments

Comments
 (0)