add redis db instead of sqlite

This commit is contained in:
ld3zian 2025-01-25 20:49:18 -07:00
parent 806f6dc07b
commit f3c566b3ad
5 changed files with 143 additions and 398 deletions

View file

@ -1,49 +1,34 @@
import Database from 'better-sqlite3';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import Redis from 'ioredis';
import type { FeedMapping } from './types';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const dbPath = join(__dirname, '../../feed-mappings.db');
// Initialize Redis client
const redis = new Redis(process.env.REDIS_URL!);
const db = new Database(dbPath);
// Initialize the database with the required table
db.exec(`
CREATE TABLE IF NOT EXISTS feed_mappings (
feed_id TEXT PRIMARY KEY,
slugs TEXT NOT NULL,
lang TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
export function storeFeedMapping(feedId: string, slugs: string[], lang: string): void {
const stmt = db.prepare('INSERT OR REPLACE INTO feed_mappings (feed_id, slugs, lang) VALUES (?, ?, ?)');
stmt.run(feedId, JSON.stringify(slugs), lang);
export async function storeFeedMapping(feedId: string, slugs: string[], lang: string): Promise<void> {
const mapping = {
slugs,
lang,
created_at: new Date().toISOString()
};
// Store with 30 day expiration
await redis.set(
feedId,
JSON.stringify(mapping),
'EX',
60 * 60 * 24 * 30 // 30 days in seconds
);
}
export function getFeedMapping(feedId: string): FeedMapping | null {
const stmt = db.prepare('SELECT slugs, lang FROM feed_mappings WHERE feed_id = ?');
const result = stmt.get(feedId);
if (!result) return null;
export async function getFeedMapping(feedId: string): Promise<FeedMapping | null> {
const mapping = await redis.get(feedId);
if (!mapping) return null;
const data = JSON.parse(mapping);
return {
slugs: JSON.parse(result.slugs),
lang: result.lang
slugs: data.slugs,
lang: data.lang
};
}
// Optional: Clean up old mappings (older than 30 days)
export function cleanupOldMappings(): void {
const stmt = db.prepare(`
DELETE FROM feed_mappings
WHERE created_at < datetime('now', '-30 days')
`);
stmt.run();
}
// Run cleanup periodically (every 24 hours)
setInterval(cleanupOldMappings, 24 * 60 * 60 * 1000);
// No need for manual cleanup as we're using TTL (expire)

View file

@ -17,8 +17,8 @@ export const POST: APIRoute = async ({ request }) => {
const dataString = `${slugs.sort().join(',')}:${lang}`;
const hash = createHash('md5').update(dataString).digest('hex').slice(0, 8);
// Store the mapping in the database
storeFeedMapping(hash, slugs, lang);
// Store the mapping in Vercel KV
await storeFeedMapping(hash, slugs, lang);
return new Response(JSON.stringify({ feedId: hash }), {
status: 200,
@ -27,7 +27,8 @@ export const POST: APIRoute = async ({ request }) => {
}
});
} catch (error) {
return new Response("Invalid request", { status: 400 });
console.error('Error creating feed:', error);
return new Response("Internal server error", { status: 500 });
}
};

View file

@ -10,7 +10,7 @@ export const GET: APIRoute = async ({ params }) => {
return new Response("Feed ID not provided", { status: 400 });
}
const mapping = getFeedMapping(feedId);
const mapping = await getFeedMapping(feedId);
if (!mapping) {
return new Response("Feed not found", { status: 404 });