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

Apply onyx updates from push notifications reliably #36047

Merged
merged 8 commits into from
Mar 6, 2024
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3025,6 +3025,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 @@ -503,14 +503,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
Loading