Skip to content

Replace callbacks with event dispatcher in UnleashClient and its Connectors - #404

Open
ppicom wants to merge 4 commits into
fix/eg-4649-move-event-callback-execution-out-of-the-hot-path-offrom
fix/eg-4649-use-dispatcher
Open

Replace callbacks with event dispatcher in UnleashClient and its Connectors#404
ppicom wants to merge 4 commits into
fix/eg-4649-move-event-callback-execution-out-of-the-hot-path-offrom
fix/eg-4649-use-dispatcher

Conversation

@ppicom

@ppicom ppicom commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

This pull request wires the EventDispatcher to the UnleashClient and its connectors. It changes all connectors from expecting an event_callback
(and, in some instances, a ready_callback) to accepting an instance
of the newly created EventDispatcher.

Tricky things when reviewing

unleash_event_callback instance variable

After reviewing #243, it seems like that property was not meant to be public.
Furthermore, it is not mentioned in any docs. However, it would be a breaking
change to remove it, and rude to any users who might be using it.

I'd clean it up otherwise.

events.py utilities

Testing a dispatcher of events that uses Threads is hard. I've introduced
an EventRecorder helper class that aids in testing that the publishing
of events works as intended without having to poke the internals of
the class being tested.

I agree, though, that it can be funny. I'm happy to review this decision if
better alternatives come to mind.

asserting awaited signals

Because the callback ran in the same thread as tests, ensuring signals
were awaited instead of timed out made sense:

    ready_signal.wait(timeout=1) # We don't care about the return value

Callbacks run in another thread now, so asserting these waits makes
more sense:

    assert ready_signal.wait(timeout=WAIT_TIMEOUT)

BoostrapConnector behaves funny

Two things worth noting about this connector:

  1. It does not emit events because it never accepted a callback in the
    first place.
  2. It's the only connector which start() function is called in the
    UnleashClient constructor.

ppicom added 4 commits August 5, 2026 16:34
This commit replaces the direct invocation of `event_callback` inside
the `UnleashClient` with calls to `emit_event()` from the newly created
`EventDispatcher`

After reviewing #243, it seems like that property was not meant to be public.
Furthermore, it is not mentioned in any docs. However, it would be a breaking
change to remove it, and rude to any users who might be using it.

I'd clean it up otherwise.

Testing a dispatcher of events that uses Threads is hard. I've introduced
an `EventRecorder` helper class that aids in testing that the publishing
of events works as intended without having to poke the internals of
the class being tested.

I agree, though, that it can be funny. I'm happy to review this decision if
better alternatives come to mind.

Because the callback ran in the same thread as tests, ensuring signals
were awaited instead of timed out made sense:

```
    ready_signal.wait(timeout=1) # We don't care about the return value
```

Callbacks run in another thread now, so asserting these waits makes
more sense:

```
    assert ready_signal.wait(timeout=WAIT_TIMEOUT)
```

UnleashClient used to invoke the user-provided callback directly. That
left the door open for a long-running callback to interfere with the
performance of `get_variant` and `is_enabled`.
This commit changes all connectors from expecting an `event_callback`
(and, in some instances, a `ready_callback`) to accepting an instance
of the newly created EventDispatcher.

All event emission now happens through this new collaborator.

Two things worth noting about this connector:

1. It does not emit events because it never accepted a callback in the
first place.
2. It's the only connector which `start()` function is called in the
`UnleashClient` constructor.

I haven't changed neither, just left a comment. We can discuss in the pull
request if we want to change this.
@ppicom ppicom changed the title fix/eg 4649 use dispatcher Replace callbacks with event dispatcher in UnleashClient and its Connectors Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

2 participants