From f415551fb45174f2618f916fd323fb076adfd7a6 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 2 May 2024 15:15:55 -0300 Subject: client: move search into worker, defer loading --- src/static/js/search-worker.js | 92 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/static/js/search-worker.js (limited to 'src/static/js/search-worker.js') diff --git a/src/static/js/search-worker.js b/src/static/js/search-worker.js new file mode 100644 index 00000000..7932655b --- /dev/null +++ b/src/static/js/search-worker.js @@ -0,0 +1,92 @@ +import {makeSearchIndexes} from '../shared-util/searchSchema.js'; +import {withEntries} from '../shared-util/sugar.js'; + +import FlexSearch from '../lib/flexsearch/flexsearch.bundle.module.min.js'; + +let status = null; + +onmessage = handleWindowMessage; + +postStatus('alive'); + +const indexes = + makeSearchIndexes(FlexSearch); + +const searchData = + await fetch('/search-data/index.json') + .then(resp => resp.json()); + +// If this fails, it's because an outdated index was cached. +// TODO: If this fails, try again once with a cache busting url. +for (const [indexName, indexData] of Object.entries(searchData)) { + for (const [key, value] of Object.entries(indexData)) { + indexes[indexName].import(key, value); + } +} + +postStatus('ready'); + +function handleWindowMessage(message) { + switch (message.data.kind) { + case 'action': + handleWindowActionMessage(message); + break; + + default: + console.warn(`Unknown message kind -> to search worker:`, message.data); + break; + } +} + +async function handleWindowActionMessage(message) { + const {id} = message.data; + + if (!id) { + console.warn(`Action without id -> to search worker:`, message.data); + return; + } + + if (status !== 'ready') { + return postActionResult(id, 'reject', 'not ready'); + } + + let value; + + switch (message.data.action) { + case 'search': + value = await performSearch(message.data.options); + break; + + default: + console.warn(`Unknown action "${message.data.action}" -> to search worker:`, message.data); + return postActionResult(id, 'reject', 'unknown action'); + } + + await postActionResult(id, 'resolve', value); +} + +function postStatus(newStatus) { + status = newStatus; + postMessage({ + kind: 'status', + status: newStatus, + }); +} + +function postActionResult(id, status, value) { + postMessage({ + kind: 'result', + id, + status, + value, + }); +} + +function performSearch({query, options}) { + return ( + withEntries(indexes, entries => entries + .map(([indexName, index]) => [ + indexName, + index.search(query, options), + ]))); +} -- cgit 1.3.0-6-gf8a5