Skip to content

Conversation

oscb
Copy link
Contributor

@oscb oscb commented Jul 20, 2022

  • fix: upgrade sovran to v0.3.0, add concurrency safe getters
  • fix: support async processing in timeline
  • fix: make all client methods awaitable, fix userInfo race condition
  • chore: cleanup

@oscb oscb linked an issue Jul 21, 2022 that may be closed by this pull request
Copy link
Contributor

@alanjcharles alanjcharles left a comment

Choose a reason for hiding this comment

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

lgtm!

@oscb oscb merged commit 40ede04 into master Jul 25, 2022
@oscb oscb deleted the user/oscb/raceCondition branch July 25, 2022 22:37
@509dave16
Copy link
Contributor

@oscb Can you do a release for these changes today or tomorrow? The userInfo race condition will break our analytics models and other downstream destinations.

oscb pushed a commit that referenced this pull request Jul 27, 2022
## [@segment/analytics-react-native-v2.5.0](https://github.com/segmentio/analytics-react-native/compare/@segment/analytics-react-native-v2.4.0...@segment/analytics-react-native-v2.5.0) (2022-07-27)

### Features

* update react native in example to 0.69.2 ([#613](#613)) ([d9e7967](d9e7967))

### Bug Fixes

* race condition when using state changing events ([#611](#611)) ([40ede04](40ede04))
@oscb
Copy link
Contributor Author

oscb commented Jul 27, 2022

🎉 This PR is included in version @segment/analytics-react-native-v2.5.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@oscb oscb added the released label Jul 27, 2022
oscb pushed a commit that referenced this pull request Jul 27, 2022
@oscb
Copy link
Contributor Author

oscb commented Jul 27, 2022

🎉 This PR is included in version @segment/analytics-react-native-plugin-amplitude-session-v0.3.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

group: (...args) => client.group(...args),
alias: (...args) => client.alias(...args),
reset: (...args) => client.reset(...args),
screen: async (...args) => client.screen(...args),

Choose a reason for hiding this comment

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

Adding async without await has a limited sense. It only moves the execution of client.screen() after the end of the current synchronous code but it doesn't allow to fully control the order of multiple concurrent event calls.

@oscb
Copy link
Contributor Author

oscb commented Aug 12, 2022 via email

@buuuudzik
Copy link

buuuudzik commented Aug 12, 2022

In JS async isn't only a mark, it has a significant influence on the order of a code execution. And returning a promise doesn't mean that the function is asynchronous.

In analytics.js all looks ok and async+await has a lot of sense and allows to precisely wait until specific async function will end.

async identify(userId, userTraits) {
    const userData = await this.store.userInfo.set(state => ({ ...state,
      userId: userId ?? state.userId,
      traits: { ...state.traits,
        ...userTraits
      }
    }));
    const event = createIdentifyEvent({
      userId: userData.userId,
      userTraits: userData.traits
    });
    await this.process(event);
    this.logger.info('IDENTIFY event saved', event);
}

But in client.js and the object returned by useAnalytics hook we don't need to wait for returning promise. And the result of await will be still another promise which needs to be handled in such a way.

const { screen } = useAnalytics();

const onClick = async () => {
  const promise = await screen();
  await promise;
  console.log("100% after screen")
}

It will have a sense only with such a code:

screen: async (...args) => await client.screen(...args),

Another thing is that is this really necessary to transforming the whole API to async? It looks that only the storage persistence and sending events over http are async. But adding events to the queue and storing userData in RAM for consecutive calls could be fully sync.

@buuuudzik
Copy link

Sorry, I've checked and I see that it works in a current Chrome also with only returning a promise. But still I don't know why async API is necessary for handling events locally.

@oscb
Copy link
Contributor Author

oscb commented Oct 11, 2022 via email

@buuuudzik
Copy link

buuuudzik commented Oct 11, 2022

Thanks @oscb for this exhaustive explanation and maybe the plugins part could be unpredictable.

But really in my opinion segment library should have an option to handle synchronously event queue because using async/await equals that events will receive later timestamps and it works but only in the same async function, it's much harder to sync events executed from totally different app places.

For me at least .identify() call should be synchronous or asynchronous but the userId passed by this event should be immediately used in further events.

You wrote:
'It's up to the caller to decide if the order of execution is important or not, instead of us deciding that it is not (which was the original problem).'

Probably what is the most important for the users is:

  • createdAt timestamp,
  • immediate usage of the userData passed by .identify().

If Segment would not handle userData by .identify() call and all events payload would be prepared by the user then .track() calls order would be not important. This is the case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug with Braze plugin

4 participants