feat(bots): Add initial post trigger and improve scheduler logging
- Add initial post trigger on bot creation to establish schedule reference point - Implement background post creation in scheduled bot processor using triggerPost - Add fresh content fetching before checking availability in scheduler - Enhance scheduler logging with detailed skip reasons and error reporting - Include autonomous bot skip reasons and scheduled bot status details in logs - Add error tracking and reporting for failed bot post attempts - Improve debugging visibility for bot task execution and failures
This commit is contained in:
@@ -232,6 +232,16 @@ export default function NewBotPage() {
|
||||
body: JSON.stringify(sourcePayload),
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger the first post to establish a reference point for the schedule
|
||||
// This runs in the background - we don't wait for it
|
||||
fetch(`/api/bots/${data.bot.id}/post`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({}),
|
||||
}).catch(() => {
|
||||
// Silently fail - the bot will post on the next scheduled run
|
||||
});
|
||||
}
|
||||
|
||||
router.push(`/settings/bots/${data.bot.id}`);
|
||||
|
||||
@@ -34,8 +34,35 @@ async function runBotTasks() {
|
||||
const autonomousResult = await processAllAutonomousBots();
|
||||
|
||||
const posted = autonomousResult.filter(r => r.result.posted).length;
|
||||
const skipped = scheduledResult.skipped;
|
||||
const errors = scheduledResult.errors.length + autonomousResult.filter(r => r.error).length;
|
||||
|
||||
// Always log bot task results for debugging
|
||||
if (scheduledResult.processed > 0 || posted > 0) {
|
||||
log('BOTS', `Processed ${scheduledResult.processed} scheduled, ${posted} autonomous posts`);
|
||||
} else if (scheduledResult.details.length > 0 || autonomousResult.length > 0) {
|
||||
// Log why bots didn't post
|
||||
const reasons = scheduledResult.details
|
||||
.filter(d => d.status !== 'posted')
|
||||
.map(d => `${d.botId.slice(0, 8)}: ${d.status}${d.message ? ` (${d.message})` : ''}`)
|
||||
.slice(0, 3);
|
||||
|
||||
const autoReasons = autonomousResult
|
||||
.filter(r => !r.result.posted)
|
||||
.map(r => `${r.botHandle}: ${r.result.reason || r.error || 'unknown'}`)
|
||||
.slice(0, 3);
|
||||
|
||||
if (reasons.length > 0 || autoReasons.length > 0) {
|
||||
log('BOTS', `No posts created. Scheduled: ${scheduledResult.details.length} checked, ${skipped} skipped. Autonomous: ${autonomousResult.length} checked.`);
|
||||
if (reasons.length > 0) log('BOTS', `Scheduled skip reasons: ${reasons.join('; ')}`);
|
||||
if (autoReasons.length > 0) log('BOTS', `Autonomous skip reasons: ${autoReasons.join('; ')}`);
|
||||
}
|
||||
} else {
|
||||
log('BOTS', 'No active bots found');
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
log('BOTS', `Errors: ${scheduledResult.errors.join('; ')}`);
|
||||
}
|
||||
} catch (error) {
|
||||
log('BOTS', `Error: ${error}`);
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
import { db, bots, botContentSources, botContentItems } from '@/db';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
import { canPost } from './rateLimiter';
|
||||
import { triggerPost } from './posting';
|
||||
import { fetchAllSourcesForBot } from './contentFetcher';
|
||||
|
||||
// ============================================
|
||||
// TYPES
|
||||
@@ -833,6 +835,9 @@ export async function processScheduledPosts(): Promise<ProcessScheduledPostsResu
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch fresh content from sources before checking availability
|
||||
await fetchAllSourcesForBot(bot.id, { maxItems: 20, timeout: 15000 });
|
||||
|
||||
// Check for unprocessed content (Requirement 5.5)
|
||||
const hasContent = await hasUnprocessedContent(bot.id);
|
||||
|
||||
@@ -859,15 +864,26 @@ export async function processScheduledPosts(): Promise<ProcessScheduledPostsResu
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point, we would trigger post generation
|
||||
// This will be implemented in the posting module (Task 15)
|
||||
// For now, we just mark it as ready to post
|
||||
result.details.push({
|
||||
botId: bot.id,
|
||||
status: 'posted',
|
||||
message: `Ready to post content: ${contentItem.title}`,
|
||||
// Trigger post creation with the content item
|
||||
const postResult = await triggerPost(bot.id, {
|
||||
sourceContentId: contentItem.id,
|
||||
});
|
||||
result.processed++;
|
||||
|
||||
if (postResult.success) {
|
||||
result.details.push({
|
||||
botId: bot.id,
|
||||
status: 'posted',
|
||||
message: `Posted: ${contentItem.title.substring(0, 50)}...`,
|
||||
});
|
||||
result.processed++;
|
||||
} else {
|
||||
result.details.push({
|
||||
botId: bot.id,
|
||||
status: 'error',
|
||||
message: postResult.error || 'Failed to create post',
|
||||
});
|
||||
result.errors.push(`Bot ${bot.id}: ${postResult.error}`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
|
||||
Reference in New Issue
Block a user