Checkpoint: Préparation recette : ajout du journal classification_errors, exposition de la cause technique des fallbacks IA, enregistrement non bloquant depuis le moteur RSS, écran d’administration Erreurs IA, route protégée et migration 0013. Validation locale : 28 tests, TypeScript et build de production réussis.
This commit is contained in:
45
server/db.ts
45
server/db.ts
@@ -16,9 +16,11 @@ import {
|
||||
rssSettings,
|
||||
processedDedupKeys,
|
||||
articleReads,
|
||||
classificationErrors,
|
||||
type InsertRssFeed,
|
||||
type InsertRssSettings,
|
||||
type ImportLog,
|
||||
type ClassificationError,
|
||||
type RssFeed,
|
||||
type RssSettings,
|
||||
} from "../drizzle/schema";
|
||||
@@ -489,6 +491,49 @@ export async function getImportStats() {
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Rapport d'erreurs de classification RSS ──────────────────────────────────
|
||||
|
||||
export interface ClassificationErrorInput {
|
||||
feedId: number | null;
|
||||
feedName: string;
|
||||
feedType: "veille" | "aap";
|
||||
articleTitle: string;
|
||||
articleUrl: string | null;
|
||||
errorMessage: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enregistre un fallback IA sans interrompre le traitement du flux RSS.
|
||||
* La collecte reste opérationnelle : l'erreur est visible dans l'administration
|
||||
* tandis que l'article est classé par la règle de repli prévue.
|
||||
*/
|
||||
export async function recordClassificationError(input: ClassificationErrorInput): Promise<void> {
|
||||
const db = await getDb();
|
||||
if (!db) {
|
||||
console.error("[Classification errors] Base indisponible : erreur non journalisée");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await db.insert(classificationErrors).values(input);
|
||||
} catch (error) {
|
||||
console.error("[Classification errors] Échec de journalisation :", error);
|
||||
}
|
||||
}
|
||||
|
||||
/** Liste paginée des fallbacks IA, réservée aux administrateurs via le routeur. */
|
||||
export async function getClassificationErrors(page: number, pageSize: number): Promise<{ errors: ClassificationError[]; total: number }> {
|
||||
const db = await getDb();
|
||||
if (!db) return { errors: [], total: 0 };
|
||||
|
||||
const offset = (page - 1) * pageSize;
|
||||
const [errors, totals] = await Promise.all([
|
||||
db.select().from(classificationErrors).orderBy(desc(classificationErrors.occurredAt)).limit(pageSize).offset(offset),
|
||||
db.select({ total: count() }).from(classificationErrors),
|
||||
]);
|
||||
return { errors, total: Number(totals[0]?.total ?? 0) };
|
||||
}
|
||||
|
||||
// ─── Boîte à idées ────────────────────────────────────────────────────────────
|
||||
|
||||
export async function createIdea(data: InsertIdea) {
|
||||
|
||||
Reference in New Issue
Block a user