Skip to content

Commit

Permalink
Merge pull request Expensify#30605 from waterim/fix-21490-User-experi…
Browse files Browse the repository at this point in the history
…enced-big-delay-2

Reopened/Fix: User experienced big delay when posting the messages
  • Loading branch information
nkuoch authored Jan 11, 2024
2 parents 1f7d006 + 7d5dd5e commit c8b4419
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 3 deletions.
17 changes: 17 additions & 0 deletions src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ Onyx.connect({
},
});

let networkTimeSkew = 0;
Onyx.connect({
key: ONYXKEYS.NETWORK,
callback: (value) => (networkTimeSkew = value?.timeSkew ?? 0),
});

/**
* Get the day of the week that the week starts on
*/
Expand Down Expand Up @@ -359,6 +365,16 @@ function getDBTime(timestamp: string | number = ''): string {
return datetime.toISOString().replace('T', ' ').replace('Z', '');
}

/**
* Returns the current time plus skew in milliseconds in the format expected by the database
*/
function getDBTimeWithSkew(): string {
if (networkTimeSkew > 0) {
return getDBTime(new Date().valueOf() + networkTimeSkew);
}
return getDBTime();
}

function subtractMillisecondsFromDateTime(dateTime: string, milliseconds: number): string {
const date = zonedTimeToUtc(dateTime, 'UTC');
const newTimestamp = subMilliseconds(date, milliseconds).valueOf();
Expand Down Expand Up @@ -728,6 +744,7 @@ const DateUtils = {
setTimezoneUpdated,
getMicroseconds,
getDBTime,
getDBTimeWithSkew,
setLocale,
subtractMillisecondsFromDateTime,
getDateStringFromISOTimestamp,
Expand Down
25 changes: 25 additions & 0 deletions src/libs/HttpUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {RequestType} from '@src/types/onyx/Request';
import type Response from '@src/types/onyx/Response';
import * as NetworkActions from './actions/Network';
import * as ApiUtils from './ApiUtils';
import HttpsError from './Errors/HttpsError';

Expand All @@ -25,17 +26,41 @@ Onyx.connect({
// We use the AbortController API to terminate pending request in `cancelPendingRequests`
let cancellationController = new AbortController();

/**
* The API commands that require the skew calculation
*/
const addSkewList = ['OpenReport', 'ReconnectApp', 'OpenApp'];

/**
* Regex to get API command from the command
*/
const APICommandRegex = /[?&]command=([^&]+)/;

/**
* Send an HTTP request, and attempt to resolve the json response.
* If there is a network error, we'll set the application offline.
*/
function processHTTPRequest(url: string, method: RequestType = 'get', body: FormData | null = null, canCancel = true): Promise<Response> {
const startTime = new Date().valueOf();
return fetch(url, {
// We hook requests to the same Controller signal, so we can cancel them all at once
signal: canCancel ? cancellationController.signal : undefined,
method,
body,
})
.then((response) => {
// We are calculating the skew to minimize the delay when posting the messages
const match = url.match(APICommandRegex)?.[1];
if (match && addSkewList.includes(match) && response.headers) {
const dateHeaderValue = response.headers.get('Date');
const serverTime = dateHeaderValue ? new Date(dateHeaderValue).valueOf() : new Date().valueOf();
const endTime = new Date().valueOf();
const latency = (endTime - startTime) / 2;
const skew = serverTime - startTime + latency;
NetworkActions.setTimeSkew(dateHeaderValue ? skew : 0);
}
return response;
})
.then((response) => {
// Test mode where all requests will succeed in the server, but fail to return a response
if (shouldFailAllRequests || shouldForceOffline) {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2406,7 +2406,7 @@ function buildOptimisticAddCommentReportAction(text?: string, file?: File): Opti
],
automatic: false,
avatar: allPersonalDetails?.[currentUserAccountID ?? -1]?.avatar ?? UserUtils.getDefaultAvatarURL(currentUserAccountID),
created: DateUtils.getDBTime(),
created: DateUtils.getDBTimeWithSkew(),
message: [
{
translationKey: isAttachment ? CONST.TRANSLATION_KEYS.ATTACHMENT : '',
Expand Down
6 changes: 5 additions & 1 deletion src/libs/actions/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ function setIsOffline(isOffline: boolean) {
Onyx.merge(ONYXKEYS.NETWORK, {isOffline});
}

function setTimeSkew(skew: number) {
Onyx.merge(ONYXKEYS.NETWORK, {timeSkew: skew});
}

function setShouldForceOffline(shouldForceOffline: boolean) {
Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline});
}
Expand All @@ -16,4 +20,4 @@ function setShouldFailAllRequests(shouldFailAllRequests: boolean) {
Onyx.merge(ONYXKEYS.NETWORK, {shouldFailAllRequests});
}

export {setIsOffline, setShouldForceOffline, setShouldFailAllRequests};
export {setIsOffline, setShouldForceOffline, setShouldFailAllRequests, setTimeSkew};
2 changes: 1 addition & 1 deletion src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ function addActions(reportID: string, text = '', file?: File) {

// Always prefer the file as the last action over text
const lastAction = attachmentAction ?? reportCommentAction;
const currentTime = DateUtils.getDBTime();
const currentTime = DateUtils.getDBTimeWithSkew();
const lastComment = lastAction?.message?.[0];
const lastCommentText = ReportUtils.formatReportLastMessageText(lastComment?.text ?? '');

Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ type Network = {

/** Whether we should fail all network requests */
shouldFailAllRequests?: boolean;

/** Skew between the client and server clocks */
timeSkew?: number;
};

export default Network;

0 comments on commit c8b4419

Please sign in to comment.