Skip to content

Commit

Permalink
Mobile RPC queue up pending messages until reconnected in foreground (#…
Browse files Browse the repository at this point in the history
…5479)

Co-authored-by: Todd.Southen <toddsouthenbentley@users.noreply.github.com>
Co-authored-by: Paul Connelly <22944042+pmconne@users.noreply.github.com>
  • Loading branch information
3 people authored May 4, 2023
1 parent 3abee97 commit 42d90d8
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/core-mobile",
"comment": "Queue up pending messages until reconnected in foreground.",
"type": "none"
}
],
"packageName": "@itwin/core-mobile"
}
29 changes: 27 additions & 2 deletions core/mobile/src/backend/MobileRpcServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class MobileRpcServer {
private _port: number;
private _connectionId: number;
private _pingTimer: NodeJS.Timeout;
public constructor() {
public constructor(private _pendingMessages: Array<string | Uint8Array> | undefined = undefined) {
/* _pingTime is a fix for ios/mobile case where when the app moves into foreground from
* background backend restart ws.Server and then notify frontend to reconnect. But ws.Server
* listening event is not fired as node yield to kevent and wait for some io event to happen.
Expand Down Expand Up @@ -81,6 +81,7 @@ export class MobileRpcServer {
this._connection = connection;
this._connection.on("message", (data) => this._onConnectionMessage(data));
this._createSender();
this._sendPending();
(global as any).__iTwinJsRpcReady = true;
});
}
Expand All @@ -102,6 +103,20 @@ export class MobileRpcServer {
MobileRpcServer.interop.sendBinary = sender;
}

private _sendPending() {
if (this._pendingMessages === undefined)
return;

for (const message of this._pendingMessages) {
this._connection!.send(message, (err) => {
if (err) {
throw err;
}
});
}
this._pendingMessages.length = 0;
}

private _onConnectionMessage(data: ws.Data) {
let message = data;
if (Array.isArray(message)) {
Expand Down Expand Up @@ -152,6 +167,15 @@ export function setupMobileRpc() {
Thus, we install a temporary timer on suspend to prevent the loop from exiting prematurely.
*/
let retainUvLoop: NodeJS.Timer | undefined;
const pendingMessages: Array<string | Uint8Array> = [];

function usePendingSender() {
const sender = (message: string | Uint8Array, _connectionId: number) => {
pendingMessages.push(message);
};
MobileRpcServer.interop.sendString = sender;
MobileRpcServer.interop.sendBinary = sender;
}

MobileHost.onEnterBackground.addListener(() => {
hasSuspended = true;
Expand All @@ -162,6 +186,7 @@ export function setupMobileRpc() {

retainUvLoop = setInterval(() => { }, 1000);
server.dispose();
usePendingSender();
server = null;
});

Expand All @@ -170,7 +195,7 @@ export function setupMobileRpc() {
return;
}

server = new MobileRpcServer();
server = new MobileRpcServer(pendingMessages);
clearInterval(retainUvLoop);
retainUvLoop = undefined;
});
Expand Down

0 comments on commit 42d90d8

Please sign in to comment.