refactor(search): read OPENSEARCH_* env per call
Some checks failed
CI / check (push) Failing after 12s
Some checks failed
CI / check (push) Failing after 12s
Tests can't override values captured at module load because ES imports hoist before any Deno.env.set call. Reading env on each helper invocation makes the module trivially testable and has no production cost (env doesn't change at runtime).
This commit is contained in:
@@ -1,21 +1,19 @@
|
|||||||
import type { API } from "@opensearch-project/opensearch";
|
import type { API } from "@opensearch-project/opensearch";
|
||||||
import { log } from "../log.ts";
|
import { log } from "../log.ts";
|
||||||
|
|
||||||
const OPENSEARCH_URL = Deno.env.get("OPENSEARCH_URL");
|
|
||||||
const OPENSEARCH_USERNAME = Deno.env.get("OPENSEARCH_USERNAME");
|
|
||||||
const OPENSEARCH_PASSWORD = Deno.env.get("OPENSEARCH_PASSWORD");
|
|
||||||
const OPENSEARCH_INDEX = Deno.env.get("OPENSEARCH_INDEX") ?? "notes";
|
|
||||||
|
|
||||||
const MAX_LIMIT = 100;
|
const MAX_LIMIT = 100;
|
||||||
|
|
||||||
const enabled = (): boolean => {
|
const openSearchUrl = (): string | undefined => Deno.env.get("OPENSEARCH_URL");
|
||||||
if (!OPENSEARCH_URL) return false;
|
const openSearchIndex = (): string =>
|
||||||
return true;
|
Deno.env.get("OPENSEARCH_INDEX") ?? "notes";
|
||||||
};
|
|
||||||
|
const enabled = (): boolean => Boolean(openSearchUrl());
|
||||||
|
|
||||||
const authHeaders = (): Record<string, string> => {
|
const authHeaders = (): Record<string, string> => {
|
||||||
if (OPENSEARCH_USERNAME && OPENSEARCH_PASSWORD) {
|
const username = Deno.env.get("OPENSEARCH_USERNAME");
|
||||||
const creds = btoa(`${OPENSEARCH_USERNAME}:${OPENSEARCH_PASSWORD}`);
|
const password = Deno.env.get("OPENSEARCH_PASSWORD");
|
||||||
|
if (username && password) {
|
||||||
|
const creds = btoa(`${username}:${password}`);
|
||||||
return { Authorization: `Basic ${creds}` };
|
return { Authorization: `Basic ${creds}` };
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@@ -29,7 +27,7 @@ const request = async (
|
|||||||
path: string,
|
path: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
const url = `${OPENSEARCH_URL}${path}`;
|
const url = `${openSearchUrl()}${path}`;
|
||||||
const headers: Record<string, string> = { ...authHeaders() };
|
const headers: Record<string, string> = { ...authHeaders() };
|
||||||
if (body !== undefined) headers["Content-Type"] = "application/json";
|
if (body !== undefined) headers["Content-Type"] = "application/json";
|
||||||
return await fetch(url, {
|
return await fetch(url, {
|
||||||
@@ -59,11 +57,12 @@ const indexMappings = {
|
|||||||
|
|
||||||
export const ensureIndex = async (): Promise<void> => {
|
export const ensureIndex = async (): Promise<void> => {
|
||||||
if (!enabled()) return;
|
if (!enabled()) return;
|
||||||
const head = await request("HEAD", `/${OPENSEARCH_INDEX}`);
|
const index = openSearchIndex();
|
||||||
|
const head = await request("HEAD", `/${index}`);
|
||||||
if (head.status === 200) return;
|
if (head.status === 200) return;
|
||||||
const res = await request("PUT", `/${OPENSEARCH_INDEX}`, indexMappings);
|
const res = await request("PUT", `/${index}`, indexMappings);
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
log(`[opensearch] created index ${OPENSEARCH_INDEX}`);
|
log(`[opensearch] created index ${index}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const text = await res.text();
|
const text = await res.text();
|
||||||
@@ -96,7 +95,7 @@ export const indexNote = async (note: IndexedNote): Promise<void> => {
|
|||||||
};
|
};
|
||||||
const res = await request(
|
const res = await request(
|
||||||
"PUT",
|
"PUT",
|
||||||
`/${OPENSEARCH_INDEX}/_doc/${docId(note.did, note.rkey)}`,
|
`/${openSearchIndex()}/_doc/${docId(note.did, note.rkey)}`,
|
||||||
doc,
|
doc,
|
||||||
);
|
);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -114,7 +113,7 @@ export const removeNote = async (
|
|||||||
if (!enabled()) return;
|
if (!enabled()) return;
|
||||||
const res = await request(
|
const res = await request(
|
||||||
"DELETE",
|
"DELETE",
|
||||||
`/${OPENSEARCH_INDEX}/_doc/${docId(did, rkey)}`,
|
`/${openSearchIndex()}/_doc/${docId(did, rkey)}`,
|
||||||
);
|
);
|
||||||
if (!res.ok && res.status !== 404) {
|
if (!res.ok && res.status !== 404) {
|
||||||
const text = await res.text();
|
const text = await res.text();
|
||||||
@@ -219,7 +218,7 @@ export const searchNotes = async (
|
|||||||
...(searchAfter ? { search_after: searchAfter } : {}),
|
...(searchAfter ? { search_after: searchAfter } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await request("POST", `/${OPENSEARCH_INDEX}/_search`, body);
|
const res = await request("POST", `/${openSearchIndex()}/_search`, body);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const text = await res.text();
|
const text = await res.text();
|
||||||
throw new Error(`Search failed: ${res.status} ${text}`);
|
throw new Error(`Search failed: ${res.status} ${text}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user