Search code examples
strapi

Strapi v5 Cron Task: strapi.db.query().create Not Working as Expected


I created a background task that periodically requests an API service in cron-task in strapi v5.
I made it insert data into the DB to simply test this service, but it doesn't work well.
I confirmed that the task is called periodically, and there is no error message,
but strapi.db.query().create doesn't seem to work.

// src/api/my-data/services/my-datat.ts
import { factories, Core } from '@strapi/strapi';
export default factories.createCoreController('api::my-data.my-data', ({ strapi }: { strapi: Core.Strapi }) => ({
  async test() {
    try {
      strapi.log.debug('my-data service test');
      await strapi.db.query('api::my-data.my-data').create({
        data: {
          boardId: 12,
          cate: 'test',
          title: 'test',
          link: 'test',
          datetime: new Date().toISOString(),
          comments: 1,
        },
      });
  }
}));
// in cron-task.ts
export default {
  // *    *    *    *    *    *
  // ┬    ┬    ┬    ┬    ┬    ┬
  // │    │    │    │    │    |
  // │    │    │    │    │    └ day of week (0 - 7) (0 or 7 is Sun)
  // │    │    │    │    └───── month (1 - 12)
  // │    │    │    └────────── day of month (1 - 31)
  // │    │    └─────────────── hour (0 - 23)
  // │    └──────────────────── minute (0 - 59)
  // └───────────────────────── second (0 - 59, OPTIONAL)
  adddata: {
    task: async ({ strapi }) => {
      strapi.log.debug('Running data task...');
      const myDataService = strapi.service('api::my-data.my-data');
      await myDataService.test();
    },
    options: {
      rule: "*/1 * * * *",
    },
  },
};

Solution

  • you have an issues with your setup:

    // src/api/my-data/services/my-datat.ts // You are pointing to a service here
    import { factories, Core } from '@strapi/strapi';
    export default factories.createCoreController // You are creating a controller not a service
    

    also you have misspell here:

    // src/api/my-data/services/my-datat.ts

    my-data and my-datat.ts

    That is likely a misspell, but I have to mention that coreService and plain service are a bit different things.

    Basically coreService should be defined only once per api So:

    // src/api/my-data/services/my-data.ts
    import { factories } from "@strapi/strapi";
    
    export default factories.createCoreService(
      "api::my-data.my-data",
      ({ strapi }) => ({
        async test(ctx) {
          return strapi.db.query("api::my-data.my-data").create({
            data: {
              test: Date.now(),
            },
          });
        },
      })
    );
    
    // config/tasks.ts
    export default {
      myJob: {
        task: async ({ strapi }) => {
          console.log("TASK");
    
          const data = await strapi.service("api::my-data.my-data").test();
    
          console.log({ data });
        },
        options: {
          rule: "*/1 * * * *",
        },
      },
    };
    
    // config/server.ts
    import tasks from "./tasks";
    
    export default ({ env }) => ({
      host: env("HOST", "0.0.0.0"),
      port: env.int("PORT", 1337),
      app: {
        keys: env.array("APP_KEYS"),
      },
      cron: {
        enabled: true,
        tasks,
      },
    });
    

    Output:

    TASK
    {
      data: {
        id: 1,
        documentId: 'ry4qjid87l3jt0pusu7t4czm',
        test: '1735200900022',
        createdAt: '2024-12-26T08:15:00.023Z',
        updatedAt: '2024-12-26T08:15:00.023Z',
        publishedAt: '2024-12-26T08:15:00.025Z',
        locale: null
      }
    }