Skip to content
Snippets Groups Projects
browser-server.js 2.16 KiB
/* globals importScripts, backend */
let hasInitialized = false;

/**
 * Sometimes the frontend build is way faster than backend.
 * This results in the frontend starting up before backend is
 * finished and thus the backend script is not available.
 *
 * The goal of this function is to retry X amount of times
 * to retrieve the backend script with a small delay.
 */
const importScriptsWithRetry = async (script, { maxRetries = 5 } = {}) => {
  try {
    importScripts(script);
  } catch (error) {
    // Break if maxRetries has exceeded
    if (maxRetries <= 0) {
      throw error;
    } else {
      console.groupCollapsed(
        `Failed to load backend, will retry ${maxRetries} more time(s)`,
      );
      console.log(error);
      console.groupEnd();
    }

    // Attempt to retry after a small delay
    await new Promise(resolve =>
      setTimeout(async () => {
        await importScriptsWithRetry(script, {
          maxRetries: maxRetries - 1,
        });
        resolve();
      }, 5000),
    );
  }
};

self.addEventListener('message', async event => {
  try {
    if (!hasInitialized) {
      const msg = event.data;

      if (msg.type === 'init') {
        hasInitialized = true;
        const isDev = !!msg.isDev;
        // let version = msg.version;
        const hash = msg.hash;

        if (
          !self.SharedArrayBuffer &&
          !msg.isSharedArrayBufferOverrideEnabled
        ) {
          self.postMessage({
            type: 'app-init-failure',
            SharedArrayBufferMissing: true,
          });
          return;
        }

        await importScriptsWithRetry(
          `${msg.publicUrl}/kcab/kcab.worker.${hash}.js`,
          { maxRetries: isDev ? 5 : 0 },
        );

        backend.initApp(isDev, self).catch(err => {
          console.log(err);
          const msg = {
            type: 'app-init-failure',
            IDBFailure: err.message.includes('indexeddb-failure'),
          };
          self.postMessage(msg);

          throw err;
        });
      }
    }
  } catch (error) {
    console.log('Failed initializing backend:', error);
    self.postMessage({
      type: 'app-init-failure',
      BackendInitFailure: true,
    });
  }
});