Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 82 additions & 12 deletions src/injected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,59 @@ const resolveWithExponentialBackoff = <T>(
const tryRequire = <T = any>(path: string) =>
resolveWithExponentialBackoff<T>(() => window.require(path));

const BOOT_RECOVERY_ATTEMPTS_KEY = 'rocketChatDesktopBootRecoveryAttempts';
const MAX_BOOT_RECOVERY_ATTEMPTS = 2;

const getBootRecoveryAttempts = (): number => {
try {
return (
Number(window.sessionStorage.getItem(BOOT_RECOVERY_ATTEMPTS_KEY)) || 0
);
} catch (error) {
return 0;
}
};

// Reloading in place never recovers a wedged webview (stale service worker or
// cache keeps serving a broken bundle), so recovery goes through
// reloadServer(), which clears the service worker and cache storage before
// reloading. The sessionStorage counter survives those reloads and caps the
// attempts, so a genuinely broken server degrades instead of reload-looping.
const attemptBootRecovery = (reason: string): void => {
const attempts = getBootRecoveryAttempts();

if (attempts >= MAX_BOOT_RECOVERY_ATTEMPTS) {
console.error(
`[Rocket.Chat Desktop] ${reason}. Boot recovery attempts exhausted (${attempts}); giving up. Restart the app or use "Reload Clearing Cache" to retry.`
);
return;
}

try {
window.sessionStorage.setItem(
BOOT_RECOVERY_ATTEMPTS_KEY,
String(attempts + 1)
);
} catch (error) {
// sessionStorage unavailable; still attempt a single recovery
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

console.error(
`[Rocket.Chat Desktop] ${reason}. Triggering force reload with cache clear to recover (attempt ${
attempts + 1
} of ${MAX_BOOT_RECOVERY_ATTEMPTS})...`
);
window.RocketChatDesktop.reloadServer();
};

const resetBootRecovery = (): void => {
try {
window.sessionStorage.removeItem(BOOT_RECOVERY_ATTEMPTS_KEY);
} catch (error) {
// sessionStorage unavailable; nothing to reset
}
};

let startRetryCount = 0;
let totalRetryTime = 0;
const MAX_RETRY_TIME = 30000; // Maximum 30 seconds total retry time
Expand All @@ -40,14 +93,9 @@ const start = async () => {
console.log('[Rocket.Chat Desktop] window.require is not defined');

if (totalRetryTime >= MAX_RETRY_TIME) {
console.error(
`[Rocket.Chat Desktop] Maximum retry time (${MAX_RETRY_TIME}ms) reached. window.require is still not available.`
attemptBootRecovery(
`Maximum retry time (${MAX_RETRY_TIME}ms) reached. window.require is still not available`
);
console.log(
'[Rocket.Chat Desktop] Triggering force reload with cache clear to recover...'
);
// Trigger force reload with cache clear to recover
window.RocketChatDesktop.reloadServer();
return;
}

Expand All @@ -64,23 +112,43 @@ const start = async () => {
console.log(
`[Rocket.Chat Desktop] Inject start - retry ${startRetryCount} in ${actualDelay}ms (total time: ${totalRetryTime}ms)`
);
setTimeout(start, actualDelay);
setTimeout(() => {
start().catch((error) => {
console.error(
'[Rocket.Chat Desktop] Injected.ts failed to start:',
error
);
});
}, actualDelay);
return;
}

// Reset retry counters on successful require detection
startRetryCount = 0;
totalRetryTime = 0;

const { Info: serverInfo = {} } = await tryRequire(
'/app/utils/rocketchat.info'
);
let serverInfo: any = {};
try {
({ Info: serverInfo = {} } = await tryRequire(
'/app/utils/rocketchat.info'
));
} catch (error) {
// window.require exists but the module registry is incomplete — the
// webapp boot is wedged (stuck throbber) and only a cache-clearing
// reload recovers it.
attemptBootRecovery(
"Failed to require '/app/utils/rocketchat.info' after retries"
);
return;
}

if (!serverInfo.version) {
console.log('[Rocket.Chat Desktop] serverInfo.version is not defined');
return;
}

resetBootRecovery();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

console.log('[Rocket.Chat Desktop] Injected.ts serverInfo', serverInfo);

window.RocketChatDesktop.setServerInfo(serverInfo);
Expand Down Expand Up @@ -693,4 +761,6 @@ const start = async () => {
console.log('[Rocket.Chat Desktop] Injected');
};

start();
start().catch((error) => {
console.error('[Rocket.Chat Desktop] Injected.ts failed to start:', error);
});
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { setupOutlookLogger } from './outlookCalendar/logger';
import { handleDesktopCapturerGetSources } from './screenSharing/desktopCapturerCache';
import { setupScreenSharing } from './screenSharing/main';
import { startServerViewScreenSharingHandler } from './screenSharing/serverViewScreenSharing';
import { setupBootWatchdog } from './servers/bootWatchdog';
import {
handleClearCacheDialog,
handleUserLoggedOutDataClearing,
Expand Down Expand Up @@ -159,6 +160,7 @@ const start = async (): Promise<void> => {
handleDesktopCapturerGetSources();
handleClearCacheDialog();
handleUserLoggedOutDataClearing();
setupBootWatchdog();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
startDocumentViewerHandler();
startBrowserHandler();
checkSupportedVersionServers();
Expand Down
Loading
Loading