Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Workspace Switching feature #512

Open
wants to merge 13 commits into
base: development
Choose a base branch
from

Conversation

einsteinx2
Copy link
Collaborator

@einsteinx2 einsteinx2 commented Oct 7, 2024

Summary

  • This adds the workspace switching feature allowing a customer to sign into a workspace, then later in the same app launch, switch to another workspace. It also handles the case where a customer signs into one workspace, the app is closed, then the app signs into a different workspace. In both cases, all event batches are attributed to the correct workspaces.

Testing Plan

  • Was this tested locally? If not, explain why.
  • E2E tested the implementation by connecting to a workspace, logging events, switching workspaces, logging another event and the uploading; also E2E tested by connecting to a workspace, logging events without upload, killing the app, connecting to a different workspace, and logging events.
  • All existing tests pass and added new ones

Reference Issue (For mParticle employees only. Ignore if you are an outside contributor)

@einsteinx2 einsteinx2 changed the title Feat/sqdsdks 6592 workspace switching feat: Add Workspace Switching feature Oct 7, 2024
…ClientImpl.java

Co-authored-by: Mansi-mParticle <[email protected]>
Signed-off-by: Ben Baron <[email protected]>
Copy link
Contributor

@Mansi-mParticle Mansi-mParticle left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@samdozor samdozor left a comment

Choose a reason for hiding this comment

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

hi! I have more to review but found a hairy issue so wanted to give you feedback asap. will do another pass tomorrow.

public static void switchWorkspace(@NonNull MParticleOptions options) {
if (instance != null) {
// End session if active
if (instance.isSessionActive()) {
Copy link
Member

Choose a reason for hiding this comment

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

who is to say that instance didn't become null due to another thread in between 294 and 296?

i would:

  • synchronize on the class (see getinstance) so nobody crazy can call this method simultaneously and
  • grab a local reference to the instance, and then check if that's null and use that.

i'd lock on the instance (eg synchronized (MParticle.class)) and to be extra safe

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Lock added


// Batch any remaining messages into upload records
try {
instance.mMessageManager.mUploadHandler.prepareMessageUploads(instance.mConfigManager.getUploadSettings());
Copy link
Member

@samdozor samdozor Oct 30, 2024

Choose a reason for hiding this comment

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

key factor in making threading work in the android SDK (and ios sdk for that matter..) is to make sure things run sequentially.

as you have it now - this will happen:

1a. customer calls mparticle.logEvent("foo")
1b async invoke message handler thread to store "foo"
2. then mparticle.switchWorkpace("bar")

and you'll prepare message uploads in (2) before (1b) ever gets around to even storing the "foo" event in the message table. actually you'll have this problem with the call to "endSession" above too since you're not waiting for that to store the resulting message.

so - you need to wait on the messages thread to make sure every event to this point has been stored before we prepare and delete etc.

but wait..there's more. the actual call to prepare should probably happen on the uploads thread, otherwise you'll end up with this method running simultaneously with natural/normal uploads and a mess of inconsistent/unpredictable state.

there's some precedence throughout the code base of doing things like this:

  • MessageManager#doUpload() - which forces a message into the message handler and then into the upload handler just to make sure we do a full pass through both.
  • IdentityApi which continuously uses mBackgroundHandler (which is actually the upload handler!) to ensure that identity requests are synchronous to uploads
  • KitManagerImpl#runOnKitThread for another example of just using another thread

there's a few ways to code this but ultimately I think you need to accomplish:

  • ensuring that everything currently queued on the message thread completes before you prepare this
  • ensure that you don't concurrently modify the database/state/etc with both the message thread and upload thread

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Please see my latest commit, I believe it should address these concerns

@einsteinx2 einsteinx2 requested a review from samdozor November 22, 2024 15:12
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