Skip to content

Commit

Permalink
Merge pull request #36047 from Expensify/arosiclair-reliable-push-notifs
Browse files Browse the repository at this point in the history
Apply onyx updates from push notifications reliably
  • Loading branch information
amyevans authored Mar 6, 2024
2 parents be716dd + c2b95d9 commit d22196a
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3108,6 +3108,7 @@ const CONST = {
ONYX_UPDATE_TYPES: {
HTTPS: 'https',
PUSHER: 'pusher',
AIRSHIP: 'airship',
},
EVENTS: {
SCROLLING: 'scrolling',
Expand Down
2 changes: 2 additions & 0 deletions src/libs/Notification/PushNotification/NotificationType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type ReportCommentNotificationData = {
shouldScrollToLastUnread?: boolean;
roomName?: string;
onyxData?: OnyxServerUpdate[];
lastUpdateID?: number;
previousUpdateID?: number;
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import Onyx from 'react-native-onyx';
import * as OnyxUpdates from '@libs/actions/OnyxUpdates';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import getPolicyMemberAccountIDs from '@libs/PolicyMembersUtils';
import {extractPolicyIDFromPath} from '@libs/PolicyUtils';
import {doesReportBelongToWorkspace, getReport} from '@libs/ReportUtils';
import Visibility from '@libs/Visibility';
import * as Modal from '@userActions/Modal';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {OnyxUpdatesFromServer} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import backgroundRefresh from './backgroundRefresh';
import PushNotification from './index';
Expand All @@ -27,9 +30,28 @@ Onyx.connect({
* Setup reportComment push notification callbacks.
*/
export default function subscribeToReportCommentPushNotifications() {
PushNotification.onReceived(PushNotification.TYPE.REPORT_COMMENT, ({reportID, reportActionID, onyxData}) => {
PushNotification.onReceived(PushNotification.TYPE.REPORT_COMMENT, ({reportID, reportActionID, onyxData, lastUpdateID, previousUpdateID}) => {
Log.info(`[PushNotification] received report comment notification in the ${Visibility.isVisible() ? 'foreground' : 'background'}`, false, {reportID, reportActionID});
Onyx.update(onyxData ?? []);

if (onyxData && lastUpdateID && previousUpdateID) {
Log.info('[PushNotification] reliable onyx update received', false, {lastUpdateID, previousUpdateID, onyxDataCount: onyxData?.length ?? 0});

const updates: OnyxUpdatesFromServer = {
type: CONST.ONYX_UPDATE_TYPES.AIRSHIP,
lastUpdateID,
previousUpdateID,
updates: [
{
eventType: 'eventType',
data: onyxData,
},
],
};
OnyxUpdates.applyOnyxUpdatesReliably(updates);
} else {
Log.hmmm("[PushNotification] Didn't apply onyx updates because some data is missing", {lastUpdateID, previousUpdateID, onyxDataCount: onyxData?.length ?? 0});
}

backgroundRefresh();
});

Expand Down
3 changes: 2 additions & 1 deletion src/libs/actions/OnyxUpdateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export default () => {
if (
!(typeof value === 'object' && !!value) ||
!('type' in value) ||
(!(value.type === CONST.ONYX_UPDATE_TYPES.HTTPS && value.request && value.response) && !(value.type === CONST.ONYX_UPDATE_TYPES.PUSHER && value.updates))
(!(value.type === CONST.ONYX_UPDATE_TYPES.HTTPS && value.request && value.response) &&
!((value.type === CONST.ONYX_UPDATE_TYPES.PUSHER || value.type === CONST.ONYX_UPDATE_TYPES.AIRSHIP) && value.updates))
) {
console.debug('[OnyxUpdateManager] Invalid format found for updates, cleaning and unpausing the queue');
Onyx.set(ONYXKEYS.ONYX_UPDATES_FROM_SERVER, null);
Expand Down
17 changes: 15 additions & 2 deletions src/libs/actions/OnyxUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {Merge} from 'type-fest';
import Log from '@libs/Log';
import * as SequentialQueue from '@libs/Network/SequentialQueue';
import PusherUtils from '@libs/PusherUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -107,7 +108,7 @@ function apply({lastUpdateID, type, request, response, updates}: OnyxUpdatesFrom
if (type === CONST.ONYX_UPDATE_TYPES.HTTPS && request && response) {
return applyHTTPSOnyxUpdates(request, response);
}
if (type === CONST.ONYX_UPDATE_TYPES.PUSHER && updates) {
if ((type === CONST.ONYX_UPDATE_TYPES.PUSHER || type === CONST.ONYX_UPDATE_TYPES.AIRSHIP) && updates) {
return applyPusherOnyxUpdates(updates);
}
}
Expand Down Expand Up @@ -141,5 +142,17 @@ function doesClientNeedToBeUpdated(previousUpdateID = 0): boolean {
return lastUpdateIDAppliedToClient < previousUpdateID;
}

function applyOnyxUpdatesReliably(updates: OnyxUpdatesFromServer) {
const previousUpdateID = Number(updates.previousUpdateID) || 0;
if (!doesClientNeedToBeUpdated(previousUpdateID)) {
apply(updates);
return;
}

// If we reached this point, we need to pause the queue while we prepare to fetch older OnyxUpdates.
SequentialQueue.pause();
saveUpdateInformation(updates);
}

// eslint-disable-next-line import/prefer-default-export
export {saveUpdateInformation, doesClientNeedToBeUpdated, apply};
export {saveUpdateInformation, doesClientNeedToBeUpdated, apply, applyOnyxUpdatesReliably};
9 changes: 1 addition & 8 deletions src/libs/actions/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,14 +599,7 @@ function subscribeToUserEvents() {
updates: pushJSON.updates ?? [],
previousUpdateID: Number(pushJSON.previousUpdateID || 0),
};
if (!OnyxUpdates.doesClientNeedToBeUpdated(Number(pushJSON.previousUpdateID || 0))) {
OnyxUpdates.apply(updates);
return;
}

// If we reached this point, we need to pause the queue while we prepare to fetch older OnyxUpdates.
SequentialQueue.pause();
OnyxUpdates.saveUpdateInformation(updates);
OnyxUpdates.applyOnyxUpdatesReliably(updates);
});

// Handles Onyx updates coming from Pusher through the mega multipleEvents.
Expand Down
2 changes: 1 addition & 1 deletion src/types/onyx/OnyxUpdatesFromServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type OnyxUpdateEvent = {
};

type OnyxUpdatesFromServer = {
type: 'https' | 'pusher';
type: 'https' | 'pusher' | 'airship';
lastUpdateID: number | string;
previousUpdateID: number | string;
request?: Request;
Expand Down

0 comments on commit d22196a

Please sign in to comment.