FoalTS / foal

Full-featured Node.js framework 🚀
https://foalts.org/
MIT License
1.9k stars 142 forks source link

Task Scheduling In App #1210

Open jonathanroze opened 1 year ago

jonathanroze commented 1 year ago

Hi,

I wanted to know if it was planned to provide a recurring task management system directly in the app instance instead of being executed via the CLI?

In order to be able to trigger different elements in the code directly (Typically, sending a message to websockets clients?).

This would also allow to set up a "multi servers" system for the crons so that the load is distributed.

Thanks and thank for your work on FoalTS, my opinion is that it is probably the best framework ts (not chauvin at all..)

LoicPoullain commented 1 year ago

Hi 👋

This would indeed be a nice feature to have. I cannot spend much time on this at the moment but if someone is willing to implement this, I could help 🙂

I guess there are a few questions that should be answered first:

lcnvdl commented 6 months ago

Maybe this can be useful:

I use Schedule inside my FoalTS Apps.

I just make the jobs like is explained here: https://foalts.org/docs/2.x/cookbook/scheduling-jobs

And then I call the "main" function in the app.controller

// (...)
import { main as schedule } from '../scripts/schedule-jobs';
import { DataSource } from 'typeorm';
import { createDataSource } from '../db';

export class AppController implements IAppController {
  subControllers = [
// ...
  ];

  async init() {
      const ds = createDataSource();
      const connection: DataSource = await ds.initialize();
      await schedule({ connection, runAtStart: true });
  }
}

Schedule jobs.ts

// https://foalts.org/docs/cookbook/scheduling-jobs

import { scheduleJob } from 'node-schedule';
import { main as closeElderSessions } from './close-elder-sessions';
import { main as deleteOrphans } from './delete-empty-finished-sessions';
import { main as deleteOlderFinishedSessions } from './delete-older-finished-sessions';
import { DataSource } from 'typeorm';

export async function main(args?: { runAtStart?: boolean; useExistingConnection?: boolean; unit?: string; value?: number; connection?: DataSource }) {
  console.log('Scheduling the job...');

  if (args?.runAtStart) {
    await closeElderSessions(Object.assign({ unit: 'day', value: 3 }, args || {}));
    await deleteOlderFinishedSessions(args || {});
    await deleteOrphans(args || {});
  }

  //  At 3.00 am

  scheduleJob('0 3 * * *',
    async () => {
      try {
        await closeElderSessions(Object.assign({ unit: 'day', value: 3 }, args || {}));
        await deleteOlderFinishedSessions(args || {});
        await deleteOrphans(args || {});
      }
      catch (err) {
        console.error('Error running schedule');
        console.error(err);
      }
    }
  );

  console.log('Job scheduled!');
}