Skip to content

Bots Inventory

In addition to the 57 job_*.js files (see jobs-inventory.md), there are 6 standalone files at the repo root that play a hybrid role: each is library-like (exports functions used by routes/routes.js) and runs its own cron.schedule(...) at the top. They are colloquially "bots".

Inventory

File LoC (approx) Cron Purpose
content_generation_bot.js 6721 bytes (cron schedule TBD) Topic-driven AI content generation: pulls tTopics, iterates tDefaultCategories, generates copy via OpenAI. Exports getmodels, getmodelcopies.
post_image_generation1_bot.js 5006 bytes TBD Image generation worker
FAQsbot.js 11642 bytes */60 * * * * (hourly) OpenAI-driven FAQ generation; getContentFromText()
quizbot.js 11255 bytes */60 * * * * (hourly) OpenAI-driven quiz generation
quotesbot.js 10685 bytes TBD OpenAI-driven quote generation
trendsbot.js 10797 bytes TBD OpenAI-driven trends-driven content

Pattern

var conf = require("./conf");
var cron = require("node-cron");
const mysql = require("sync-mysql");
const OpenAI = require('openai');
const openai = new OpenAI({ apiKey: conf.OPENAI_API_KEY });
const con = new mysql({ /* connection */ });
let isOnProcess = false;

cron.schedule("...", () => { getContentFromText(); });

async function getContentFromText() {
  if (!isOnProcess) {
    isOnProcess = true;
    // fetch a row from a queue table
    // call OpenAI
    // write the result back to DB
    isOnProcess = false;
  }
}

module.exports = { fnA, fnB };  // some bots export functions too

Why the "bot" vs "job" distinction?

In practice, these files behave just like jobs (cron-scheduled, sync-mysql, AI-calling). The bot naming likely reflects the work being more "AI generation" than "queue processing". From an operational view, treat them as jobs.

Risk: combined OpenAI rate-limit hits

All 6 bots run on */60 * * * * (hourly) — they all wake at the top of the hour and burst OpenAI calls. If they each issue 10-50 calls per tick, the combined rate at :00 could exceed OpenAI's per-account rate limit.

Recommendation: stagger the schedules. E.g., 15 * * * *, 30 * * * *, 45 * * * * for the four hourly bots so they don't dogpile.

Risk: shared isOnProcess semantics

Each file's isOnProcess is in-process. If a bot's previous tick is still running when the next tick fires, the new one is skipped. What happens if the work takes longer than the cron interval? The bot is effectively serialised. For 60-minute intervals this is unlikely, but jobs running every 1 minute (some) will start dropping ticks when work runs slow.

Imports into the main app

routes/routes.js line 19:

const { getmodels, getmodelcopies } = require("../content_generation_bot.js");

This means starting server.js also kick-starts content_generation_bot.js's cron (because module-level cron.schedule(...) runs at require-time). The main app process therefore runs the bot's cron in addition to whatever PM2 processes the bot separately. If pm2 start content_generation_bot.js is also running, you have two cron handlers for the same job in parallel — they trip each other's isOnProcess flag (or don't, since they're different processes).

Verify: check the deploy's PM2 manifest; if content_generation_bot.js is started as its own PM2 process, the import inside routes/routes.js is causing duplicate cron scheduling. Fix by either (a) not importing the cron-bearing bot file from routes/routes.js (split functions out into a library file with no cron), or (b) using a IS_WORKER env flag to no-op the cron in non-worker processes.

Recommendations

ID Recommendation Effort
B-1 Split each bot into *_bot.js (cron-only) and *_lib.js (functions imported by routes) Medium
B-2 Add a IS_WORKER env flag so bots' crons no-op when started inside the main server process Small
B-3 Stagger cron schedules to spread OpenAI calls Trivial
B-4 Add OpenAI usage tracking per bot (cost visibility) Medium
B-5 Move bots' sync-mysql to mysql2/promise Medium
B-6 Centralise prompt templates in helper/prompts/ instead of inline literals Medium