Refactor URL import to reuse cached markdown

This commit is contained in:
Jurgis Sakalauskas
2025-10-17 16:39:20 +03:00
parent edcd0f0963
commit 4ac8fc1b60
3 changed files with 55 additions and 10 deletions
@@ -6,6 +6,11 @@ import {
listItems as listItemsRepo, listItems as listItemsRepo,
updateItem as updateItemRepo updateItem as updateItemRepo
} from '../db/items-repository.js'; } from '../db/items-repository.js';
import {
createUrl,
findUrlByValue,
updateUrlBodyText
} from '../db/urls-repository.js';
import { findImageById } from '../db/images-repository.js'; import { findImageById } from '../db/images-repository.js';
import { HttpError } from '../errors/http-error.js'; import { HttpError } from '../errors/http-error.js';
import { resolveUrlId } from './url-helpers.js'; import { resolveUrlId } from './url-helpers.js';
@@ -17,6 +22,7 @@ import {
parseItemUpdatePayload parseItemUpdatePayload
} from '../validation/items.js'; } from '../validation/items.js';
import { readUrlMarkdown } from '../services/url-reader-service.js'; import { readUrlMarkdown } from '../services/url-reader-service.js';
import { normalizeUrl } from '../utils/url-normalizer.js';
export const listItems = async (req: Request, res: Response) => { export const listItems = async (req: Request, res: Response) => {
const projectId = parseUuid(req.params.projectId, 'projectId'); const projectId = parseUuid(req.params.projectId, 'projectId');
@@ -162,7 +168,14 @@ export const importItemFromUrl = async (req: Request, res: Response) => {
// If the URL constructor fails here, readUrlMarkdown will surface the error. // If the URL constructor fails here, readUrlMarkdown will surface the error.
} }
const normalizedDbUrl = normalizeUrl(url);
let urlRecord = await findUrlByValue(normalizedDbUrl);
let markdown: string; let markdown: string;
const existingBody = urlRecord?.bodyText;
if (existingBody && existingBody.trim().length > 0) {
markdown = existingBody;
} else {
try { try {
markdown = await readUrlMarkdown(normalizedUrl); markdown = await readUrlMarkdown(normalizedUrl);
} catch (error) { } catch (error) {
@@ -175,6 +188,16 @@ export const importItemFromUrl = async (req: Request, res: Response) => {
); );
} }
if (urlRecord) {
const updated = await updateUrlBodyText(urlRecord.id, markdown);
if (updated) {
urlRecord = updated;
}
} else {
urlRecord = await createUrl({ url: normalizedDbUrl, bodyText: markdown });
}
}
try { try {
const parsed = new URL(normalizedUrl); const parsed = new URL(normalizedUrl);
hostname = parsed.hostname.replace(/^www\./, ''); hostname = parsed.hostname.replace(/^www\./, '');
+22
View File
@@ -90,3 +90,25 @@ export const createUrl = async (params: CreateUrlParams): Promise<UrlRecord> =>
return mapUrlRow(result.rows[0]); return mapUrlRow(result.rows[0]);
}; };
export const updateUrlBodyText = async (
id: string,
bodyText: string
): Promise<UrlRecord | null> => {
const result = await query<UrlRow>(
`
UPDATE urls
SET body_text = $2,
updated_at = NOW()
WHERE id = $1
RETURNING id, url, body_text, attributes, has_price, created_at, updated_at
`,
[id, bodyText]
);
if (result.rows.length === 0) {
return null;
}
return mapUrlRow(result.rows[0]);
};
+1 -1
View File
@@ -40,7 +40,7 @@ export const readUrlMarkdown = async (rawUrl: string): Promise<string> => {
Authorization: `Bearer ${env.urlReader.apiKey}` Authorization: `Bearer ${env.urlReader.apiKey}`
} }
}); });
} catch (error) { } catch {
throw new HttpError( throw new HttpError(
502, 502,
'We could not reach the URL reader service. Please try again later.' 'We could not reach the URL reader service. Please try again later.'