Skip to content

feat: add registerPlugin so a plugin can be added after the client starts - #393

Open
abelonogov-ld wants to merge 2 commits into
mainfrom
andrey/register-plugin
Open

feat: add registerPlugin so a plugin can be added after the client starts#393
abelonogov-ld wants to merge 2 commits into
mainfrom
andrey/register-plugin

Conversation

@abelonogov-ld

@abelonogov-ld abelonogov-ld commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Plugins could only be supplied through LDConfig, so an integration that learns about a plugin later — or that wants to instrument a client it did not configure — had no way in. This adds LDClient.registerPlugin(Plugin), mirroring the method the .NET and Flutter SDKs already expose.

  • Hooks go live only once register succeeds. This follows the .NET ordering, and it differs from configuration-time registration, where a plugin's hooks are active before register is called. The consequence is that a plugin whose registration failed never contributes hooks, and a plugin's own hooks do not observe the evaluations or identify calls its register makes.
  • EnvironmentMetadata is now retained on the instance rather than living in a local map during init, so a plugin registered later is handed the same environment description as one configured up front. The init loop switches from a Map<LDClient, EnvironmentMetadata> to a List<LDClient> accordingly.
  • Failures are contained. A throwing getHooks leaves the plugin unregistered; a throwing register yields a failure result passed to onPluginsReady. Neither propagates to the caller. Reading the plugin's name for the log message tolerates metadata that itself throws, so reporting one failure cannot raise another out of the handler reporting it.

Registration applies to the one client it is called on, so a multi-environment setup means calling it per environment.

Test plan

Eight cases added to LDClientPluginsTest, all passing on an API 36 emulator alongside the three pre-existing plugin tests (11 total):

  • registerPluginPassesClientAndEnvironmentMetadata
  • registerPluginActivatesBundledHooks
  • registerPluginDoesNotRunTheRegisteringPluginsOwnHooks
  • registerPluginReportsSuccessToOnPluginsReady
  • registerPluginDoesNotRegisterPluginWhoseGetHooksThrows
  • registerPluginToleratesRegisterThrowing
  • registerPluginRejectsNullPlugin
  • registerPluginAppliesOnlyToTheClientItIsCalledOn
  • testDebugUnitTest green

Note

Overview
Adds LDClient.registerPlugin so a plugin can be attached after init, not only via LDConfig. Registration is per client (one environment).

Hooks are installed only after register succeeds, so they never observe the plugin’s own register work and a failed plugin contributes none. getHooks/register/onPluginsReady exceptions are logged, not thrown. EnvironmentMetadata is kept on the instance so late registration gets the same metadata as config-time plugins.

Reviewed by Cursor Bugbot for commit f556929. Bugbot is set up for automated code reviews on this repo. Configure here.

…arts

Plugins could only be supplied through LDConfig, so an integration that
learns about a plugin later — or that wants to instrument a client it did
not configure — had no way in.

Hooks go live only once register succeeds, matching the .NET ordering, so a
plugin whose registration failed never contributes hooks and a plugin's own
hooks do not observe its register call. Retaining EnvironmentMetadata on the
instance lets a plugin registered later be handed the same environment
description as one configured up front.

Co-authored-by: Cursor <cursoragent@cursor.com>
@abelonogov-ld
abelonogov-ld requested a review from a team as a code owner August 21, 2026 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant