Skip to content

refactor: KitManagerImpl user-attribute forwarding and UserAttributeListener cleanup#693

Open
denischilik wants to merge 8 commits intoworkstation/6.0-Releasefrom
feat/cleanup-kit-manager-impl
Open

refactor: KitManagerImpl user-attribute forwarding and UserAttributeListener cleanup#693
denischilik wants to merge 8 commits intoworkstation/6.0-Releasefrom
feat/cleanup-kit-manager-impl

Conversation

@denischilik
Copy link
Copy Markdown

@denischilik denischilik commented Apr 2, 2026

Background

Please review: FilteredMParticleUser was removed from UserAttributeListener callback parameters because, in the current kit implementations, it is not used in a meaningful way—callbacks do not rely on kit-scoped filtering via that type. If you know a reason we should keep it (e.g. a kit or integration pattern we missed), please comment; follow-up work may depend on that.

Refactor focus: duplicated dispatch logic in KitManagerImpl was removed by consolidating user-attribute and identity forwarding into shared listener iteration instead of repeating the same patterns in multiple places.

What Has Changed

  • UserAttributeListener API: FilteredMParticleUser removed from callback signatures (those callbacks no longer take a user parameter).
  • KitManagerImpl: centralized forwarding for user-attribute and identity listeners (activeKits(), shared loops) to avoid duplication across the class.
  • Kits and tests updated to match the new signatures.

Screenshots/Video

N/A (SDK internals)

Checklist

  • I have performed a self-review of my own code.
  • I have made corresponding changes to the documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have tested this locally.

Additional Notes

  • ~30 files vs workstation/6.0-Release; branch rebased with --onto so it contains 5 commits on top of the already-merged listener PRs.

Introduce activeKits() to return non-disabled kit integrations from the
providers map. Add KitManagerImplTest.testActiveKitsExcludesDisabled to
verify disabled kits are omitted.

Made-with: Cursor
Use activeKits() for user attribute and identity paths; inline former
setUserAttribute helpers to avoid duplicate isDisabled checks. Flatten
syncUserIdentities with early returns and drop redundant null check on
identities map.

Made-with: Cursor
…ttributesReceived

Declare getConfiguration() and getName() on UserAttributeListener so callers
can access kit metadata consistently. Route onUserAttributesReceived through
activeKits() and align variable naming with other active-kit paths.

Made-with: Cursor
Drop the user parameter from KitIntegration.UserAttributeListener methods;
update KitManagerImpl forwarding, instrumented/unit tests, and kit
implementations (Adobe, AppsFlyer, Apptentive, Braze, CleverTap, etc.).

Made-with: Cursor
Add getConfiguration() and getName() to UserAttributeListener so callers
can use the listener type without casting. Introduce userAttributeListeners()
and iterate with variable name listener; keep activeKits() package-visible
for tests.

Made-with: Cursor
@denischilik denischilik requested a review from a team as a code owner April 2, 2026 20:18
@cursor
Copy link
Copy Markdown

cursor bot commented Apr 2, 2026

PR Summary

Medium Risk
Changes the KitIntegration.UserAttributeListener interface by removing the FilteredMParticleUser context parameter and refactors KitManagerImpl dispatch paths; this is a broad API change that could break downstream kit implementations if any weren’t updated in this repo.

Overview
Simplifies kit user-attribute callbacks and reduces duplicated dispatch logic.

KitIntegration.UserAttributeListener removes the FilteredMParticleUser parameter from all callbacks (set/remove/increment/tag/list/all-attributes/consent), and KitManagerImpl refactors forwarding to iterate over shared activeKits() / userAttributeListeners() helpers while preserving per-kit attribute filtering and list-vs-scalar behavior.

All affected kits and test kits/tests are updated to the new signatures (including dataplan blocking tests), and a new unit test asserts activeKits() excludes disabled kits.

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

if (provider instanceof KitIntegration.UserAttributeListener && !provider.isDisabled()) {
try {
((KitIntegration.UserAttributeListener) provider).onConsentStateUpdated(oldState, newState, FilteredMParticleUser.getInstance(mpid, provider));
((KitIntegration.UserAttributeListener) provider).onConsentStateUpdated(oldState, newState);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent refactoring of onConsentStateUpdated forwarding loop

Low Severity

The onConsentStateUpdated method still iterates providers.values() directly and manually checks !provider.isDisabled(), while every other UserAttributeListener forwarding method (setUserAttribute, removeUserAttribute, incrementUserAttribute, setUserTag, setUserAttributeList, onUserAttributesReceived) was refactored to use the new userAttributeListeners() helper. This inconsistency means future changes to the active-kit filtering logic (e.g., in activeKits() or userAttributeListeners()) would not apply to consent forwarding, risking divergent behavior.

Fix in Cursor Fix in Web

…Listener API

Remove third argument and unused FilteredMParticleUser mock setup from unit tests.

Made-with: Cursor
UserAttributeListenerTestKit exposes (String?) -> Unit; a two-parameter
lambda failed Kotlin type inference in compileDebugAndroidTestKotlin.

Made-with: Cursor
KitIntegration.UserAttributeListener now passes only old and new
ConsentState. Drop the removed FilteredMParticleUser argument and
unused mock from AppboyKitTests across braze-38 through braze-41.

Made-with: Cursor
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 6, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
3.8% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7524884. Configure here.


Map<MParticle.IdentityType, String> identities = user.getUserIdentities();

for (Map.Entry<MParticle.IdentityType, String> entry : identities.entrySet()) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed null guard on identities map in syncUserIdentities

Low Severity

The refactored syncUserIdentities removed the null check on the identities map returned by getUserIdentities(). The old code guarded against a null return with if (identities != null) before iterating. While getUserIdentities() is declared @NonNull in the MParticleUser interface, the defensive check protected against contract violations. A null return now causes a NullPointerException on identities.entrySet().

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7524884. Configure here.

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