Publications en échec : nouvel essai espacé au lieu de chaque minute

Une publication en échec gardait published_at à NULL et était renvoyée
à chaque passage du planificateur, soit toutes les minutes, sans fin.
Chaque essai multipliait les appels à l'API Graph, jusqu'à épuiser le
quota de l'application (code 4) puis déclencher le blocage anti-spam
de Meta (code 368).

- scheduled_posts : colonnes attempts et next_attempt_at ;
- délai croissant entre les essais (5 min → 3 h), plus long après une
  limite de débit (30 min → 4 h), abandon après 5 tentatives ;
- après une limite de débit, les autres publications de la même
  plateforme sont reportées au lieu d'aggraver le blocage ;
- reprogrammer une publication remet le compteur à zéro ;
- l'historique indique la prochaine tentative ou l'abandon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jcWbATGHxatn4V7qS3mr3
This commit is contained in:
Claude committed 2026-10-12 18:45:10 +00:00
1 parent 7f21e23a91
commit def7d8a2cb
9 files changed
+211 -9

No files matched your search

+7
View File
@@ -230,6 +230,11 @@ export const scheduledPosts = pgTable("scheduled_posts", {
// post_id définitif n'est connu qu'après interrogation du statut.
publishId: text("publish_id"),
publishStatus: text("publish_status"),
// Échecs de publication : nouvel essai à `nextAttemptAt` (délai croissant),
// abandon après quelques tentatives (il faut alors reprogrammer).
attempts: integer("attempts").notNull().default(0),
nextAttemptAt: timestamp("next_attempt_at"),
});
export const aiGenerations = pgTable("ai_generations", {
@@ -454,6 +459,8 @@ export const insertScheduledPostSchema = createInsertSchema(scheduledPosts).omit
publishedAt: true,
externalPostId: true,
error: true,
attempts: true,
nextAttemptAt: true,
});
export const insertAiGenerationSchema = createInsertSchema(aiGenerations).omit({