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),
|
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}`);
|
router.push(`/settings/bots/${data.bot.id}`);
|
||||||
|
|||||||
@@ -34,8 +34,35 @@ async function runBotTasks() {
|
|||||||
const autonomousResult = await processAllAutonomousBots();
|
const autonomousResult = await processAllAutonomousBots();
|
||||||
|
|
||||||
const posted = autonomousResult.filter(r => r.result.posted).length;
|
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) {
|
if (scheduledResult.processed > 0 || posted > 0) {
|
||||||
log('BOTS', `Processed ${scheduledResult.processed} scheduled, ${posted} autonomous posts`);
|
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) {
|
} catch (error) {
|
||||||
log('BOTS', `Error: ${error}`);
|
log('BOTS', `Error: ${error}`);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
import { db, bots, botContentSources, botContentItems } from '@/db';
|
import { db, bots, botContentSources, botContentItems } from '@/db';
|
||||||
import { eq, and } from 'drizzle-orm';
|
import { eq, and } from 'drizzle-orm';
|
||||||
import { canPost } from './rateLimiter';
|
import { canPost } from './rateLimiter';
|
||||||
|
import { triggerPost } from './posting';
|
||||||
|
import { fetchAllSourcesForBot } from './contentFetcher';
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// TYPES
|
// TYPES
|
||||||
@@ -833,6 +835,9 @@ export async function processScheduledPosts(): Promise<ProcessScheduledPostsResu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch fresh content from sources before checking availability
|
||||||
|
await fetchAllSourcesForBot(bot.id, { maxItems: 20, timeout: 15000 });
|
||||||
|
|
||||||
// Check for unprocessed content (Requirement 5.5)
|
// Check for unprocessed content (Requirement 5.5)
|
||||||
const hasContent = await hasUnprocessedContent(bot.id);
|
const hasContent = await hasUnprocessedContent(bot.id);
|
||||||
|
|
||||||
@@ -859,15 +864,26 @@ export async function processScheduledPosts(): Promise<ProcessScheduledPostsResu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, we would trigger post generation
|
// Trigger post creation with the content item
|
||||||
// This will be implemented in the posting module (Task 15)
|
const postResult = await triggerPost(bot.id, {
|
||||||
// For now, we just mark it as ready to post
|
sourceContentId: contentItem.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (postResult.success) {
|
||||||
result.details.push({
|
result.details.push({
|
||||||
botId: bot.id,
|
botId: bot.id,
|
||||||
status: 'posted',
|
status: 'posted',
|
||||||
message: `Ready to post content: ${contentItem.title}`,
|
message: `Posted: ${contentItem.title.substring(0, 50)}...`,
|
||||||
});
|
});
|
||||||
result.processed++;
|
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) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
|||||||
Reference in New Issue
Block a user