import { config as setupEnv } from 'dotenv-flow'; import connect from '@/config/db'; import { Page } from '@/entities'; import { TypeormDataLoader } from '@/entities/utils'; import logger from '@/logger'; import { AlgoliaIndexKind, AlgoliaSearchIndex } from '@/services'; import { ContextType } from '@/types'; setupEnv(); const main = async () => { await connect(); let unindexedPages = new Array(); let indexedPageCount = 0; const dbDataLoader = new TypeormDataLoader(); const algoliaIndex = AlgoliaSearchIndex.fromIndex(AlgoliaIndexKind.PAGES); const indexPages = async () => { // uncomment to ensure too many pages don't get indexed // if (indexedPageCount > 10000) { // stream.pause(); // stream.destroy(); // throw new Error('too many pages indexed'); // } await algoliaIndex.createOrUpdateRecords( await Promise.all( unindexedPages.map((page) => page.getAlgoliaPage({ dbDataLoader } as ContextType) ) ) ); indexedPageCount = indexedPageCount + unindexedPages.length; logger.info(`indexed ${indexedPageCount} pages`); unindexedPages = []; }; const stream = await Page.createQueryBuilder('Page') .where({ discoverable: true, }) .stream(); await new Promise((resolve, reject) => { stream.on('data', (pgPage: Record) => { const page = Page.create( Object.entries(pgPage).reduce((prev, [key, value]) => { return { ...prev, [key.startsWith('Page_') ? key.slice(5) : key]: value, }; }, {}) ); unindexedPages.push(page); if (unindexedPages.length >= 100) { stream.pause(); indexPages() .then(() => { stream.resume(); }) .catch((error) => { stream.destroy(error); reject(error); }); } }); stream.on('end', async () => { resolve(undefined); if (unindexedPages.length >= 0) { try { indexPages().then(resolve); } catch (error) { stream.destroy(); reject(error); throw error; } } }); }); }; console.time('main'); main() .then(() => { console.timeEnd('main'); }) .catch((error) => { console.error(error); process.exit(1); });