Skip to content

refactor: Made PendingEventsStore interface asynchronous #513

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

Closed

Conversation

zashraf1985
Copy link
Contributor

Summary

Made PendingEventsStore interface asynchronous. This change is done to implement React Native Async Storage which is asynchronous using the same interface.

Test plan

Fixed the failing unit tests

@coveralls
Copy link

coveralls commented Jun 18, 2020

Coverage Status

Coverage remained the same at 96.7% when pulling 8c63727 on zeeshan/rn-offline-events-pendingtore-async into 29ae7be on master.

@zashraf1985 zashraf1985 removed their assignment Jun 18, 2020
// assert that the passed in callback to pendingEventsDispatcher was called
expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith({ statusCode: 200 })
setTimeout(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you add this setTimeout?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because i want to detect call dispatchEvent on the original event dispatcher which was called synchronously earlier but now its being called asynchronously after the set promise resolves.

try {
this.send(item, () => {})
} catch (e) {}
this.store.values().then((pendingEvents) => {
Copy link
Contributor

@mjc1283 mjc1283 Jun 18, 2020

Choose a reason for hiding this comment

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

  • Did you test this in the browser to see how its behavior compares to the old version? I'm curious if the additional async step would affect how much of this is allowed by the browser to execute during a page close.
  • If close is called while values() is in progress, I think we need to stop and not send the events. To the extent possible, we should stop all additional work after close is called.

this.dispatcher.dispatchEvent(entry.request, response => {
this.store.remove(entry.uuid)
callback(response)
this.store.set(entry.uuid, entry).then(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as above RE: doing things after close: If close is called while set(...) is in progress, we need to stop and not send the events.

Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed this offline w/Zeeshan - this part is OK as-is, disregard.

callback(response)
this.store.set(entry.uuid, entry).then(() => {
this.dispatcher.dispatchEvent(entry.request, response => {
this.store.remove(entry.uuid)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to wait for remove to complete before calling the callback. This callback eventually feeds into the close promise status. We don't want close to resolve while an async operation is still pending.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

@jaeopt jaeopt left a comment

Choose a reason for hiding this comment

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

I see event ordering issues in some places. All the events queued must be sent to the server in their dispatch orders. See my comments.

logger.debug('Sending %s pending events from previous page', pendingEvents.length)
pendingEvents.forEach(item => {
try {
this.send(item, () => {})
Copy link
Contributor

Choose a reason for hiding this comment

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

Does MAP guarantee the fifo order in JS? Otherwise, we lose the order of events dispatched.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, orders are concerned in other cases as well:

  • if we have any queued events, all the following events dispatched should be queued as well instead of sending them first. We may have queued events from the previous session or new events queued from the last failed dispatch.

callback(response)
this.store.set(entry.uuid, entry).then(() => {
this.dispatcher.dispatchEvent(entry.request, response => {
this.store.remove(entry.uuid).then(() => callback(response))
Copy link
Contributor

Choose a reason for hiding this comment

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

We also need a protection from one packet stuck in the queue forever (cannot send to the server successfully for JSON format error etc). This can be an issue when we change them in FIFO order.

@zashraf1985
Copy link
Contributor Author

This is no longer needed now. I am now leaving the existing localstorge implementation intact and implementing event caching for react native separately in a new PR.
#517

@zashraf1985 zashraf1985 closed this Jul 7, 2020
@raju-opti raju-opti deleted the zeeshan/rn-offline-events-pendingtore-async branch October 4, 2023 13:41
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.

4 participants