feat: cache post URIs & prevent recursion loop
This commit is contained in:
parent
9b3be5d52a
commit
e6372de095
3 changed files with 73 additions and 10 deletions
42
src/utils/cache.ts
Normal file
42
src/utils/cache.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
interface CacheEntry<T> {
|
||||
value: T;
|
||||
expiry: number;
|
||||
}
|
||||
|
||||
class TimedCache<T> {
|
||||
private cache = new Map<string, CacheEntry<T>>();
|
||||
private ttl: number; // Time to live in milliseconds
|
||||
|
||||
constructor(ttl: number) {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
get(key: string): T | undefined {
|
||||
const entry = this.cache.get(key);
|
||||
if (!entry) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (Date.now() > entry.expiry) {
|
||||
this.cache.delete(key); // Entry expired
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
set(key: string, value: T): void {
|
||||
const expiry = Date.now() + this.ttl;
|
||||
this.cache.set(key, { value, expiry });
|
||||
}
|
||||
|
||||
delete(key: string): void {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export const postCache = new TimedCache<any>(2 * 60 * 1000); // 2 minutes cache
|
||||
|
|
@ -11,6 +11,7 @@ import { and, eq } from "drizzle-orm";
|
|||
import { env } from "../env";
|
||||
import { bot, ERROR_MESSAGE, MAX_GRAPHEMES } from "../core";
|
||||
import { parsePost, parsePostImages, traverseThread } from "./post";
|
||||
import { postCache } from "../utils/cache";
|
||||
|
||||
/*
|
||||
Utilities
|
||||
|
|
@ -123,14 +124,19 @@ export async function parseConversation(
|
|||
});
|
||||
}
|
||||
|
||||
const post = await bot.getPost(row.postUri);
|
||||
let post = postCache.get(row.postUri);
|
||||
if (!post) {
|
||||
post = await bot.getPost(row.postUri);
|
||||
postCache.set(row.postUri, post);
|
||||
}
|
||||
const convoMessages = await getRelevantMessages(row!);
|
||||
|
||||
let parseResult = null;
|
||||
try {
|
||||
const parsedPost = await parsePost(post, true, new Set());
|
||||
parseResult = {
|
||||
context: yaml.dump({
|
||||
post: await parsePost(post, true),
|
||||
post: parsedPost || null,
|
||||
}),
|
||||
messages: convoMessages.map((message) => {
|
||||
const role = message.did == env.DID ? "model" : "user";
|
||||
|
|
|
|||
|
|
@ -8,14 +8,21 @@ import {
|
|||
import * as c from "../core";
|
||||
import * as yaml from "js-yaml";
|
||||
import type { ParsedPost } from "../types";
|
||||
import { postCache } from "../utils/cache";
|
||||
|
||||
export async function parsePost(
|
||||
post: Post,
|
||||
includeThread: boolean,
|
||||
): Promise<ParsedPost> {
|
||||
seenUris: Set<string> = new Set(),
|
||||
): Promise<ParsedPost | undefined> {
|
||||
if (seenUris.has(post.uri)) {
|
||||
return undefined;
|
||||
}
|
||||
seenUris.add(post.uri);
|
||||
|
||||
const [images, quotePost, ancestorPosts] = await Promise.all([
|
||||
parsePostImages(post),
|
||||
parseQuote(post),
|
||||
parseQuote(post, seenUris),
|
||||
includeThread ? traverseThread(post) : Promise.resolve(null),
|
||||
]);
|
||||
|
||||
|
|
@ -28,23 +35,31 @@ export async function parsePost(
|
|||
...(quotePost && { quotePost }),
|
||||
...(ancestorPosts && {
|
||||
thread: {
|
||||
ancestors: await Promise.all(
|
||||
ancestorPosts.map((ancestor) => parsePost(ancestor, false)),
|
||||
),
|
||||
ancestors: (await Promise.all(
|
||||
ancestorPosts.map((ancestor) => parsePost(ancestor, false, seenUris)),
|
||||
)).filter((post): post is ParsedPost => post !== undefined),
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
async function parseQuote(post: Post) {
|
||||
async function parseQuote(post: Post, seenUris: Set<string>) {
|
||||
if (
|
||||
!post.embed || (!post.embed.isRecord() && !post.embed.isRecordWithMedia())
|
||||
) return undefined;
|
||||
|
||||
const record = (post.embed as RecordEmbed || RecordWithMediaEmbed).record;
|
||||
const embedPost = await c.bot.getPost(record.uri);
|
||||
if (seenUris.has(record.uri)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return await parsePost(embedPost, false);
|
||||
let embedPost = postCache.get(record.uri);
|
||||
if (!embedPost) {
|
||||
embedPost = await c.bot.getPost(record.uri);
|
||||
postCache.set(record.uri, embedPost);
|
||||
}
|
||||
|
||||
return await parsePost(embedPost, false, seenUris);
|
||||
}
|
||||
|
||||
export function parsePostImages(post: Post) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue