0

We have a web application using Fastify. There is a function in a handler that we need to call it from a cron job inside the same application.

index.js

async function registerRoutes(fastify) {
  fastify
    .post(
      '/statements/generate',
      {
        schema: schemas.statements
      },
      handlers.generateStatements
    )
 };

handler.js

 async function generateStatements(req, reply) {
  ...
  ...
  reply.code(200).send({...});

 }

Is there a direct way (without calling the actual endpoint by using axios or another library) to call the function generateStatements in the handler (or the route)?

I found a "hack":

 const req = {
    ...
    ...
  };

  const response = { statusCode: 200 };
  const context = {};
  const reply = new Reply(response, { context });
  reply.send = () => true; //the cron job doesn't need the response.

  await generateStatements(req, reply);

But it is not ideal at all because we might need to generate a jwt token for some business logic and will fail.

const token = await reply.jwtSign(
      { account: req.account._id },
      {
        expiresIn: '1d'
      }
    );
Jose Antonio
  • 578
  • 1
  • 8
  • 34
  • Did you try [`app.inject`](https://github.com/fastify/fastify/blob/main/docs/Guides/Testing.md#benefits-of-using-fastifyinject)? – Manuel Spigolon Jul 31 '23 at 15:23
  • @ManuelSpigolon Fastify app.inject seems focus on tests. I'm currently trying fastify-cron which uses Fastify app.inject underneath, however it has some conflicts with our existing version of Fastify and implementation of the application. – Jose Antonio Aug 01 '23 at 10:57
  • app.inject is 1000 times better than writing a fake a request/reply object tbh. that function has been created for testing, but it runs a fake http call supporting all the fastify stuff. so it is the perfect fit imho. For sure I agree with the answer about refactoring to split the business logic from the http framework – Manuel Spigolon Aug 01 '23 at 12:46

1 Answers1

0

Why do you need the reply object if you invoke your function from a cron job? You are not making a request to the server, so you don't need to

reply.code(200).send({...});

in your crone job and so you don't need the reply object at all in this case.

If you want to use the same code for both crone job and API endpoint than consider moving it to a separate function instead of mocking the reply object for a call from your cron job.

Leviathan
  • 53
  • 1
  • 7
  • Refactor the function is on the backlog but we want to avoid it (for now) because this function is returning the reply in different places, and also it's using the reply to generate a JWT token as I mentioned in my post. I won't be an easy refactor. – Jose Antonio Aug 01 '23 at 10:53
  • In that case I can only sugest 2 things: 1. Do the refactoring now as you will be doing yourself a favour in the long run (recommended); 2. Make the reply parameter optional and wrap every call of this object in if statement with checking whether this parameter exists (or you can use the optional chaining opearator before invoking a method from that object like so `reply?.code(200).send({...});`) – Leviathan Aug 02 '23 at 14:38