Skip to content

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

Merged
denischilik merged 9 commits intoworkstation/6.0-Releasefrom
feat/cleanup-kit-manager-impl
Apr 13, 2026
Merged

refactor: KitManagerImpl user-attribute forwarding and UserAttributeListener cleanup#693
denischilik merged 9 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.

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 public API and refactors KitManagerImpl dispatch logic, which could break third-party kit implementations or alter when/which callbacks fire if filtering/disabled-state handling is incorrect.

Overview
Removes FilteredMParticleUser from all KitIntegration.UserAttributeListener callback signatures (attributes, lists, tags, increments, consent), updating core interfaces, testkits, and multiple production kits/tests to match.

Refactors KitManagerImpl user-attribute/identity/logout forwarding by centralizing iteration over enabled kits via new activeKits()/userAttributeListeners() helpers, applying per-kit attribute filtering and list-support behavior in one place, and adding a unit test to ensure disabled kits are excluded.

Reviewed by Cursor Bugbot for commit 2d2e931. 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
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.

Align GoogleAnalyticsFirebaseKitTest and GoogleAnalyticsFirebaseGA4KitTest
with KitIntegration: drop the removed FilteredMParticleUser argument and
unused mock from consent tests.

Made-with: Cursor
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

Copy link
Copy Markdown
Contributor

@BrandonStalnaker BrandonStalnaker left a comment

Choose a reason for hiding this comment

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

In general this seems good to me. I agree with the removal of FilteredUser for these events and Dennis has separately confirmed with me that no existing kits were utilizing that parameter. I'm less confident about the Kotlin code itself so I'd suggest another reviewer whose more confident before merging.

@denischilik denischilik merged commit 2b4cf31 into workstation/6.0-Release Apr 13, 2026
21 of 23 checks passed
@denischilik denischilik deleted the feat/cleanup-kit-manager-impl branch April 13, 2026 17:17
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.

3 participants