diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 729a3b7..d87724f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -56,11 +56,9 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max - # This step generates an artifact attestation for the image, which is an - # unforgeable statement about where and how it was built. It increases - # supply chain security for people who consume the image. For more - # information, see - # https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds + # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. + # It increases supply chain security for people who consume the image. + # For more information, see https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds - name: Generate artifact attestation uses: actions/attest-build-provenance@v1 with: diff --git a/src/backend/utils/elastic.ts b/src/backend/utils/elastic.ts index 0733fe5..38d8c2a 100644 --- a/src/backend/utils/elastic.ts +++ b/src/backend/utils/elastic.ts @@ -6,13 +6,19 @@ import { Question } from "@prisma/client"; import { prisma } from "../database/prisma"; import { platformNameToLabel } from "../platforms/registry"; -const client = new ElasticClient({ - node: process.env.ELASTIC_HOST, - auth: { - username: process.env.ELASTIC_USER!, - password: process.env.ELASTIC_PASSWORD!, - }, -}); +let _CACHED_CLIENT: ElasticClient | null = null; +function getClient() { + if (!_CACHED_CLIENT) { + _CACHED_CLIENT = new ElasticClient({ + node: process.env.ELASTIC_HOST, + auth: { + username: process.env.ELASTIC_USER!, + password: process.env.ELASTIC_PASSWORD!, + }, + }); + } + return _CACHED_CLIENT; +} const ALIAS_NAME = process.env.ELASTIC_INDEX!; @@ -50,8 +56,8 @@ export async function rebuildElasticDatabase() { const questions = await prisma.question.findMany(); const oldIndexNames: string[] = []; - if (await client.indices.existsAlias({ name: ALIAS_NAME })) { - const alias = await client.indices.getAlias({ name: ALIAS_NAME }); + if (await getClient().indices.existsAlias({ name: ALIAS_NAME })) { + const alias = await getClient().indices.getAlias({ name: ALIAS_NAME }); oldIndexNames.push(...Object.keys(alias)); } @@ -59,7 +65,7 @@ export async function rebuildElasticDatabase() { const index = `${ALIAS_NAME}-${suffix}`; console.log(`Creating a new index ${index}`); - await client.indices.create({ + await getClient().indices.create({ index, settings: { number_of_replicas: 0, @@ -71,7 +77,7 @@ export async function rebuildElasticDatabase() { const flush = async () => { if (!operations.length) return; - await client.bulk({ + await getClient().bulk({ operations: operations.flatMap((op) => [ { index: { _index: index, _id: op.id } }, op.document, @@ -95,7 +101,7 @@ export async function rebuildElasticDatabase() { console.log(`Pushed ${count} records to Elasticsearch.`); console.log("Switching alias to new index"); - await client.indices.updateAliases({ + await getClient().indices.updateAliases({ body: { actions: [ { remove: { index: "*", alias: ALIAS_NAME } }, @@ -106,6 +112,6 @@ export async function rebuildElasticDatabase() { for (const oldIndexName of oldIndexNames) { console.log(`Removing old index ${oldIndexName}`); - await client.indices.delete({ index: oldIndexName }); + await getClient().indices.delete({ index: oldIndexName }); } } diff --git a/src/web/worker/searchWithElastic.ts b/src/web/worker/searchWithElastic.ts index 87accee..7a59e7f 100644 --- a/src/web/worker/searchWithElastic.ts +++ b/src/web/worker/searchWithElastic.ts @@ -6,13 +6,19 @@ import { import { ElasticQuestion } from "../../backend/utils/elastic"; -const client = new ElasticClient({ - node: process.env.ELASTIC_HOST, - auth: { - username: process.env.ELASTIC_USER!, - password: process.env.ELASTIC_PASSWORD!, - }, -}); +let _CACHED_CLIENT: ElasticClient | null = null; +function getClient() { + if (!_CACHED_CLIENT) { + _CACHED_CLIENT = new ElasticClient({ + node: process.env.ELASTIC_HOST, + auth: { + username: process.env.ELASTIC_USER!, + password: process.env.ELASTIC_PASSWORD!, + }, + }); + } + return _CACHED_CLIENT; +} const INDEX_NAME = process.env.ELASTIC_INDEX!; @@ -89,7 +95,7 @@ export async function searchWithElastic({ filterByPlatforms, forecastsThreshold, }: SearchOpts): Promise[]> { - const response = await client.search({ + const response = await getClient().search({ index: INDEX_NAME, sort: [{ "qualityindicators.stars": "desc" }, "_score"], query: {