mirror of
https://github.com/strapi/strapi.git
synced 2025-09-03 05:39:36 +00:00
chore: replace node-schedule with strapi.cron service
This commit is contained in:
parent
7f13d09efd
commit
e648c19c20
@ -1,12 +1,6 @@
|
|||||||
import { createAuditLogsLifecycleService } from '../lifecycles';
|
import { createAuditLogsLifecycleService } from '../lifecycles';
|
||||||
import { scheduleJob } from 'node-schedule';
|
|
||||||
|
|
||||||
import '@strapi/types';
|
import '@strapi/types';
|
||||||
|
|
||||||
jest.mock('node-schedule', () => ({
|
|
||||||
scheduleJob: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('Audit logs service', () => {
|
describe('Audit logs service', () => {
|
||||||
const mockSubscribe = jest.fn();
|
const mockSubscribe = jest.fn();
|
||||||
|
|
||||||
@ -37,6 +31,10 @@ describe('Audit logs service', () => {
|
|||||||
get: jest.fn(() => ({
|
get: jest.fn(() => ({
|
||||||
deleteExpiredEvents: jest.fn(),
|
deleteExpiredEvents: jest.fn(),
|
||||||
})),
|
})),
|
||||||
|
cron: {
|
||||||
|
add: jest.fn(),
|
||||||
|
remove: jest.fn(),
|
||||||
|
},
|
||||||
config: {
|
config: {
|
||||||
get(key: any) {
|
get(key: any) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
@ -103,15 +101,18 @@ describe('Audit logs service', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create a cron job that executed one time a day', async () => {
|
it('should create a cron job that executed one time a day', async () => {
|
||||||
// @ts-expect-error scheduleJob
|
// Mock Strapi EE feature to be enabled for this test
|
||||||
const mockScheduleJob = scheduleJob.mockImplementationOnce(
|
jest.mocked(strapi.ee.features.isEnabled).mockReturnValueOnce(true);
|
||||||
jest.fn((rule, callback) => callback())
|
|
||||||
);
|
|
||||||
|
|
||||||
const lifecycle = createAuditLogsLifecycleService(strapi);
|
const lifecycle = createAuditLogsLifecycleService(strapi);
|
||||||
await lifecycle.register();
|
await lifecycle.register();
|
||||||
|
|
||||||
expect(mockScheduleJob).toHaveBeenCalledTimes(1);
|
// Verify that strapi.cron.add was called with the correct job configuration
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith('0 0 * * *', expect.any(Function));
|
expect(strapi.cron.add).toHaveBeenCalledWith({
|
||||||
|
deleteExpiredAuditLogs: {
|
||||||
|
task: expect.any(Function),
|
||||||
|
options: '0 0 * * *',
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { Core } from '@strapi/types';
|
import type { Core } from '@strapi/types';
|
||||||
import { scheduleJob } from 'node-schedule';
|
|
||||||
|
|
||||||
const DEFAULT_RETENTION_DAYS = 90;
|
const DEFAULT_RETENTION_DAYS = 90;
|
||||||
|
|
||||||
@ -156,9 +155,15 @@ const createAuditLogsLifecycleService = (strapi: Core.Strapi) => {
|
|||||||
|
|
||||||
// Manage audit logs auto deletion
|
// Manage audit logs auto deletion
|
||||||
const retentionDays = getRetentionDays(strapi);
|
const retentionDays = getRetentionDays(strapi);
|
||||||
state.deleteExpiredJob = scheduleJob('0 0 * * *', () => {
|
|
||||||
const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);
|
strapi.cron.add({
|
||||||
auditLogsService.deleteExpiredEvents(expirationDate);
|
deleteExpiredAuditLogs: {
|
||||||
|
task: async () => {
|
||||||
|
const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);
|
||||||
|
auditLogsService.deleteExpiredEvents(expirationDate);
|
||||||
|
},
|
||||||
|
options: '0 0 * * *',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@ -173,9 +178,7 @@ const createAuditLogsLifecycleService = (strapi: Core.Strapi) => {
|
|||||||
state.eventHubUnsubscribe();
|
state.eventHubUnsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.deleteExpiredJob) {
|
strapi.cron.remove('deleteExpiredAuditLogs');
|
||||||
state.deleteExpiredJob.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
@ -118,7 +118,6 @@
|
|||||||
"koa-static": "5.0.0",
|
"koa-static": "5.0.0",
|
||||||
"koa2-ratelimit": "^1.1.3",
|
"koa2-ratelimit": "^1.1.3",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"node-schedule": "2.1.1",
|
|
||||||
"ora": "5.4.1",
|
"ora": "5.4.1",
|
||||||
"p-map": "4.0.0",
|
"p-map": "4.0.0",
|
||||||
"passport-local": "1.0.0",
|
"passport-local": "1.0.0",
|
||||||
|
@ -88,7 +88,6 @@
|
|||||||
"markdown-it-mark": "^3.0.1",
|
"markdown-it-mark": "^3.0.1",
|
||||||
"markdown-it-sub": "^1.0.0",
|
"markdown-it-sub": "^1.0.0",
|
||||||
"markdown-it-sup": "1.0.0",
|
"markdown-it-sup": "1.0.0",
|
||||||
"node-schedule": "2.1.1",
|
|
||||||
"prismjs": "1.30.0",
|
"prismjs": "1.30.0",
|
||||||
"qs": "6.11.1",
|
"qs": "6.11.1",
|
||||||
"react-dnd": "16.0.1",
|
"react-dnd": "16.0.1",
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
import type { UID } from '@strapi/types';
|
import type { UID } from '@strapi/types';
|
||||||
import { scheduleJob } from 'node-schedule';
|
|
||||||
import { HISTORY_VERSION_UID } from '../../constants';
|
import { HISTORY_VERSION_UID } from '../../constants';
|
||||||
import { createLifecyclesService } from '../lifecycles';
|
import { createLifecyclesService } from '../lifecycles';
|
||||||
|
|
||||||
jest.mock('node-schedule', () => ({
|
|
||||||
scheduleJob: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const mockGetRequestContext = jest.fn(() => {
|
const mockGetRequestContext = jest.fn(() => {
|
||||||
return {
|
return {
|
||||||
state: {
|
state: {
|
||||||
@ -73,6 +68,9 @@ const mockStrapi = {
|
|||||||
config: {
|
config: {
|
||||||
get: () => undefined,
|
get: () => undefined,
|
||||||
},
|
},
|
||||||
|
cron: {
|
||||||
|
add: jest.fn(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// @ts-expect-error - ignore
|
// @ts-expect-error - ignore
|
||||||
mockStrapi.documents.use = jest.fn();
|
mockStrapi.documents.use = jest.fn();
|
||||||
@ -93,14 +91,15 @@ describe('history lifecycles service', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create a cron job that runs once a day', async () => {
|
it('should create a cron job that runs once a day', async () => {
|
||||||
// @ts-expect-error - this is a mock
|
|
||||||
const mockScheduleJob = scheduleJob.mockImplementationOnce(
|
|
||||||
jest.fn((rule, callback) => callback())
|
|
||||||
);
|
|
||||||
|
|
||||||
await lifecyclesService.bootstrap();
|
await lifecyclesService.bootstrap();
|
||||||
|
|
||||||
expect(mockScheduleJob).toHaveBeenCalledTimes(1);
|
expect(mockStrapi.cron.add).toHaveBeenCalledTimes(1);
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith('historyDaily', '0 0 * * *', expect.any(Function));
|
expect(mockStrapi.cron.add).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
deleteHistoryDaily: expect.objectContaining({
|
||||||
|
task: expect.any(Function),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,8 +3,6 @@ import { contentTypes } from '@strapi/utils';
|
|||||||
|
|
||||||
import { omit, castArray } from 'lodash/fp';
|
import { omit, castArray } from 'lodash/fp';
|
||||||
|
|
||||||
import { scheduleJob } from 'node-schedule';
|
|
||||||
|
|
||||||
import { getService } from '../utils';
|
import { getService } from '../utils';
|
||||||
import { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';
|
import { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';
|
||||||
|
|
||||||
@ -93,10 +91,8 @@ const getSchemas = (uid: UID.CollectionType) => {
|
|||||||
|
|
||||||
const createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {
|
const createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {
|
||||||
const state: {
|
const state: {
|
||||||
deleteExpiredJob: ReturnType<typeof scheduleJob> | null;
|
|
||||||
isInitialized: boolean;
|
isInitialized: boolean;
|
||||||
} = {
|
} = {
|
||||||
deleteExpiredJob: null,
|
|
||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,33 +172,37 @@ const createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Schedule a job to delete expired history versions every day at midnight
|
// Schedule a job to delete expired history versions every day at midnight
|
||||||
state.deleteExpiredJob = scheduleJob('historyDaily', '0 0 * * *', () => {
|
strapi.cron.add({
|
||||||
const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;
|
deleteHistoryDaily: {
|
||||||
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
async task() {
|
||||||
|
const retentionDaysInMilliseconds =
|
||||||
|
serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;
|
||||||
|
const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
|
||||||
|
|
||||||
strapi.db
|
strapi.db
|
||||||
.query(HISTORY_VERSION_UID)
|
.query(HISTORY_VERSION_UID)
|
||||||
.deleteMany({
|
.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
created_at: {
|
created_at: {
|
||||||
$lt: expirationDate,
|
$lt: expirationDate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
strapi.log.error('Error deleting expired history versions', error.message);
|
strapi.log.error('Error deleting expired history versions', error.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
options: '0 0 * * *',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
state.isInitialized = true;
|
state.isInitialized = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
async destroy() {
|
async destroy() {
|
||||||
if (state.deleteExpiredJob) {
|
strapi.cron.remove('deleteHistoryDaily');
|
||||||
state.deleteExpiredJob.cancel();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -68,7 +68,6 @@
|
|||||||
"date-fns-tz": "2.0.1",
|
"date-fns-tz": "2.0.1",
|
||||||
"formik": "2.4.5",
|
"formik": "2.4.5",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"node-schedule": "2.1.1",
|
|
||||||
"qs": "6.11.1",
|
"qs": "6.11.1",
|
||||||
"react-intl": "6.6.2",
|
"react-intl": "6.6.2",
|
||||||
"react-redux": "8.1.3",
|
"react-redux": "8.1.3",
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import { Job } from 'node-schedule';
|
|
||||||
import type { Core } from '@strapi/types';
|
import type { Core } from '@strapi/types';
|
||||||
|
|
||||||
import { Release } from '../../shared/contracts/releases';
|
import { Release } from '../../shared/contracts/releases';
|
||||||
import { getService } from './utils';
|
import { getService } from './utils';
|
||||||
|
|
||||||
export const destroy = async ({ strapi }: { strapi: Core.Strapi }) => {
|
export const destroy = async ({ strapi }: { strapi: Core.Strapi }) => {
|
||||||
const scheduledJobs: Map<Release['id'], Job> = getService('scheduling', {
|
const scheduledJobs: Map<Release['id'], string> = getService('scheduling', {
|
||||||
strapi,
|
strapi,
|
||||||
}).getAll();
|
}).getAll();
|
||||||
|
|
||||||
for (const [, job] of scheduledJobs) {
|
for (const [, taskName] of scheduledJobs) {
|
||||||
job.cancel();
|
strapi.cron.remove(taskName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { scheduleJob } from 'node-schedule';
|
|
||||||
import createSchedulingService from '../scheduling';
|
import createSchedulingService from '../scheduling';
|
||||||
|
|
||||||
const baseStrapiMock = {
|
const baseStrapiMock = {
|
||||||
@ -7,13 +6,17 @@ const baseStrapiMock = {
|
|||||||
isEnabled: jest.fn().mockReturnValue(true),
|
isEnabled: jest.fn().mockReturnValue(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
cron: {
|
||||||
|
add: jest.fn(),
|
||||||
|
remove: jest.fn(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.mock('node-schedule', () => ({
|
|
||||||
scheduleJob: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('Scheduling service', () => {
|
describe('Scheduling service', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
describe('set', () => {
|
describe('set', () => {
|
||||||
it('should throw an error if the release does not exist', async () => {
|
it('should throw an error if the release does not exist', async () => {
|
||||||
const strapiMock = {
|
const strapiMock = {
|
||||||
@ -33,10 +36,6 @@ describe('Scheduling service', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should cancel the previous job if it exists and create the new one', async () => {
|
it('should cancel the previous job if it exists and create the new one', async () => {
|
||||||
const mockScheduleJob = jest.fn().mockReturnValue({ cancel: jest.fn() });
|
|
||||||
// @ts-expect-error - scheduleJob is a mock
|
|
||||||
scheduleJob.mockImplementation(mockScheduleJob);
|
|
||||||
|
|
||||||
const strapiMock = {
|
const strapiMock = {
|
||||||
...baseStrapiMock,
|
...baseStrapiMock,
|
||||||
db: {
|
db: {
|
||||||
@ -53,21 +52,17 @@ describe('Scheduling service', () => {
|
|||||||
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
||||||
const scheduledJobs = await schedulingService.set('1', oldJobDate);
|
const scheduledJobs = await schedulingService.set('1', oldJobDate);
|
||||||
expect(scheduledJobs.size).toBe(1);
|
expect(scheduledJobs.size).toBe(1);
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith(oldJobDate, expect.any(Function));
|
expect(strapiMock.cron.add).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
const oldJob = scheduledJobs.get('1')!;
|
const oldTaskName = scheduledJobs.get('1')!;
|
||||||
|
|
||||||
await schedulingService.set('1', newJobDate);
|
await schedulingService.set('1', newJobDate);
|
||||||
|
|
||||||
expect(oldJob.cancel).toHaveBeenCalled();
|
expect(strapiMock.cron.remove).toHaveBeenCalledWith(oldTaskName);
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith(newJobDate, expect.any(Function));
|
expect(strapiMock.cron.add).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new job', async () => {
|
it('should create a new job', async () => {
|
||||||
const mockScheduleJob = jest.fn().mockReturnValue({ cancel: jest.fn() });
|
|
||||||
// @ts-expect-error - scheduleJob is a mock
|
|
||||||
scheduleJob.mockImplementation(mockScheduleJob);
|
|
||||||
|
|
||||||
const strapiMock = {
|
const strapiMock = {
|
||||||
...baseStrapiMock,
|
...baseStrapiMock,
|
||||||
db: {
|
db: {
|
||||||
@ -83,16 +78,12 @@ describe('Scheduling service', () => {
|
|||||||
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
||||||
const scheduledJobs = await schedulingService.set('1', date);
|
const scheduledJobs = await schedulingService.set('1', date);
|
||||||
expect(scheduledJobs.size).toBe(1);
|
expect(scheduledJobs.size).toBe(1);
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith(date, expect.any(Function));
|
expect(strapiMock.cron.add).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('cancel', () => {
|
describe('cancel', () => {
|
||||||
it('should cancel the job if it exists', async () => {
|
it('should cancel the job if it exists', async () => {
|
||||||
const mockScheduleJob = jest.fn().mockReturnValue({ cancel: jest.fn() });
|
|
||||||
// @ts-expect-error - scheduleJob is a mock
|
|
||||||
scheduleJob.mockImplementation(mockScheduleJob);
|
|
||||||
|
|
||||||
const strapiMock = {
|
const strapiMock = {
|
||||||
...baseStrapiMock,
|
...baseStrapiMock,
|
||||||
db: {
|
db: {
|
||||||
@ -108,19 +99,18 @@ describe('Scheduling service', () => {
|
|||||||
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
||||||
const scheduledJobs = await schedulingService.set('1', date);
|
const scheduledJobs = await schedulingService.set('1', date);
|
||||||
expect(scheduledJobs.size).toBe(1);
|
expect(scheduledJobs.size).toBe(1);
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith(date, expect.any(Function));
|
expect(strapiMock.cron.add).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
const taskName = scheduledJobs.get('1')!;
|
||||||
schedulingService.cancel('1');
|
schedulingService.cancel('1');
|
||||||
|
|
||||||
|
expect(strapiMock.cron.remove).toHaveBeenCalledWith(taskName);
|
||||||
expect(scheduledJobs.size).toBe(0);
|
expect(scheduledJobs.size).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getAll', () => {
|
describe('getAll', () => {
|
||||||
it('should return all the scheduled jobs', async () => {
|
it('should return all the scheduled jobs', async () => {
|
||||||
const mockScheduleJob = jest.fn().mockReturnValue({ cancel: jest.fn() });
|
|
||||||
// @ts-expect-error - scheduleJob is a mock
|
|
||||||
scheduleJob.mockImplementation(mockScheduleJob);
|
|
||||||
|
|
||||||
const strapiMock = {
|
const strapiMock = {
|
||||||
...baseStrapiMock,
|
...baseStrapiMock,
|
||||||
db: {
|
db: {
|
||||||
@ -141,10 +131,6 @@ describe('Scheduling service', () => {
|
|||||||
|
|
||||||
describe('syncFromDatabase', () => {
|
describe('syncFromDatabase', () => {
|
||||||
it('should sync the scheduled jobs from the database', async () => {
|
it('should sync the scheduled jobs from the database', async () => {
|
||||||
const mockScheduleJob = jest.fn().mockReturnValue({ cancel: jest.fn() });
|
|
||||||
// @ts-expect-error - scheduleJob is a mock
|
|
||||||
scheduleJob.mockImplementation(mockScheduleJob);
|
|
||||||
|
|
||||||
const strapiMock = {
|
const strapiMock = {
|
||||||
...baseStrapiMock,
|
...baseStrapiMock,
|
||||||
db: {
|
db: {
|
||||||
@ -161,7 +147,7 @@ describe('Scheduling service', () => {
|
|||||||
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
const schedulingService = createSchedulingService({ strapi: strapiMock });
|
||||||
const scheduledJobs = await schedulingService.syncFromDatabase();
|
const scheduledJobs = await schedulingService.syncFromDatabase();
|
||||||
expect(scheduledJobs.size).toBe(1);
|
expect(scheduledJobs.size).toBe(1);
|
||||||
expect(mockScheduleJob).toHaveBeenCalledWith(expect.any(Date), expect.any(Function));
|
expect(strapiMock.cron.add).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { scheduleJob, Job } from 'node-schedule';
|
|
||||||
import type { Core } from '@strapi/types';
|
import type { Core } from '@strapi/types';
|
||||||
|
|
||||||
import { errors } from '@strapi/utils';
|
import { errors } from '@strapi/utils';
|
||||||
@ -7,7 +6,7 @@ import { getService } from '../utils';
|
|||||||
import { RELEASE_MODEL_UID } from '../constants';
|
import { RELEASE_MODEL_UID } from '../constants';
|
||||||
|
|
||||||
const createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {
|
const createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {
|
||||||
const scheduledJobs = new Map<Release['id'], Job>();
|
const scheduledJobs = new Map<Release['id'], string>();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async set(releaseId: Release['id'], scheduleDate: Date) {
|
async set(releaseId: Release['id'], scheduleDate: Date) {
|
||||||
@ -19,29 +18,34 @@ const createSchedulingService = ({ strapi }: { strapi: Core.Strapi }) => {
|
|||||||
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const job = scheduleJob(scheduleDate, async () => {
|
const taskName = `publishRelease_${releaseId}`;
|
||||||
try {
|
|
||||||
await getService('release', { strapi }).publish(releaseId);
|
|
||||||
// @TODO: Trigger webhook with success message
|
|
||||||
} catch (error) {
|
|
||||||
// @TODO: Trigger webhook with error message
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cancel(releaseId);
|
strapi.cron.add({
|
||||||
|
[taskName]: {
|
||||||
|
async task() {
|
||||||
|
try {
|
||||||
|
await getService('release', { strapi }).publish(releaseId);
|
||||||
|
// @TODO: Trigger webhook with success message
|
||||||
|
} catch (error) {
|
||||||
|
// @TODO: Trigger webhook with error message
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: scheduleDate,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (scheduledJobs.has(releaseId)) {
|
if (scheduledJobs.has(releaseId)) {
|
||||||
this.cancel(releaseId);
|
this.cancel(releaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduledJobs.set(releaseId, job);
|
scheduledJobs.set(releaseId, taskName);
|
||||||
|
|
||||||
return scheduledJobs;
|
return scheduledJobs;
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel(releaseId: Release['id']) {
|
cancel(releaseId: Release['id']) {
|
||||||
if (scheduledJobs.has(releaseId)) {
|
if (scheduledJobs.has(releaseId)) {
|
||||||
scheduledJobs.get(releaseId)!.cancel();
|
strapi.cron.remove(scheduledJobs.get(releaseId)!);
|
||||||
scheduledJobs.delete(releaseId);
|
scheduledJobs.delete(releaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ describe('metrics', () => {
|
|||||||
});
|
});
|
||||||
test('Initializes a middleware', () => {
|
test('Initializes a middleware', () => {
|
||||||
const use = jest.fn();
|
const use = jest.fn();
|
||||||
|
const add = jest.fn();
|
||||||
|
|
||||||
const metricsInstance = metrics({
|
const metricsInstance = metrics({
|
||||||
config: {
|
config: {
|
||||||
@ -32,6 +33,9 @@ describe('metrics', () => {
|
|||||||
requestContext: {
|
requestContext: {
|
||||||
get: jest.fn(() => ({})),
|
get: jest.fn(() => ({})),
|
||||||
},
|
},
|
||||||
|
cron: {
|
||||||
|
add,
|
||||||
|
},
|
||||||
fetch,
|
fetch,
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
@ -44,6 +48,7 @@ describe('metrics', () => {
|
|||||||
|
|
||||||
test('Does not init middleware if disabled', () => {
|
test('Does not init middleware if disabled', () => {
|
||||||
const use = jest.fn();
|
const use = jest.fn();
|
||||||
|
const add = jest.fn();
|
||||||
|
|
||||||
const metricsInstance = metrics({
|
const metricsInstance = metrics({
|
||||||
config: {
|
config: {
|
||||||
@ -67,6 +72,9 @@ describe('metrics', () => {
|
|||||||
requestContext: {
|
requestContext: {
|
||||||
get: jest.fn(() => ({})),
|
get: jest.fn(() => ({})),
|
||||||
},
|
},
|
||||||
|
cron: {
|
||||||
|
add,
|
||||||
|
},
|
||||||
fetch,
|
fetch,
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
@ -100,6 +108,9 @@ describe('metrics', () => {
|
|||||||
requestContext: {
|
requestContext: {
|
||||||
get: jest.fn(() => ({})),
|
get: jest.fn(() => ({})),
|
||||||
},
|
},
|
||||||
|
cron: {
|
||||||
|
add: jest.fn(),
|
||||||
|
},
|
||||||
fetch,
|
fetch,
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
@ -147,6 +158,9 @@ describe('metrics', () => {
|
|||||||
root: process.cwd(),
|
root: process.cwd(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
cron: {
|
||||||
|
add: jest.fn(),
|
||||||
|
},
|
||||||
requestContext: {
|
requestContext: {
|
||||||
get: jest.fn(() => ({})),
|
get: jest.fn(() => ({})),
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
* You can learn more at https://docs.strapi.io/developer-docs/latest/getting-started/usage-information.html
|
* You can learn more at https://docs.strapi.io/developer-docs/latest/getting-started/usage-information.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Job, scheduleJob } from 'node-schedule';
|
|
||||||
import type { Core } from '@strapi/types';
|
import type { Core } from '@strapi/types';
|
||||||
|
|
||||||
import wrapWithRateLimit from './rate-limiter';
|
import wrapWithRateLimit from './rate-limiter';
|
||||||
@ -25,7 +24,6 @@ const createTelemetryInstance = (strapi: Core.Strapi) => {
|
|||||||
const isDisabled =
|
const isDisabled =
|
||||||
!uuid || isTruthy(process.env.STRAPI_TELEMETRY_DISABLED) || isTruthy(telemetryDisabled);
|
!uuid || isTruthy(process.env.STRAPI_TELEMETRY_DISABLED) || isTruthy(telemetryDisabled);
|
||||||
|
|
||||||
const crons: Job[] = [];
|
|
||||||
const sender = createSender(strapi);
|
const sender = createSender(strapi);
|
||||||
const sendEvent = wrapWithRateLimit(sender, { limitedEvents: LIMITED_EVENTS });
|
const sendEvent = wrapWithRateLimit(sender, { limitedEvents: LIMITED_EVENTS });
|
||||||
|
|
||||||
@ -36,8 +34,12 @@ const createTelemetryInstance = (strapi: Core.Strapi) => {
|
|||||||
|
|
||||||
register() {
|
register() {
|
||||||
if (!isDisabled) {
|
if (!isDisabled) {
|
||||||
const pingCron = scheduleJob('0 0 12 * * *', () => sendEvent('ping'));
|
strapi.cron.add({
|
||||||
crons.push(pingCron);
|
sendPingEvent: {
|
||||||
|
task: () => sendEvent('ping'),
|
||||||
|
options: '0 0 12 * * *',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
strapi.server.use(createMiddleware({ sendEvent }));
|
strapi.server.use(createMiddleware({ sendEvent }));
|
||||||
}
|
}
|
||||||
@ -45,15 +47,14 @@ const createTelemetryInstance = (strapi: Core.Strapi) => {
|
|||||||
|
|
||||||
bootstrap() {},
|
bootstrap() {},
|
||||||
|
|
||||||
destroy() {
|
|
||||||
// Clear open handles
|
|
||||||
crons.forEach((cron) => cron.cancel());
|
|
||||||
},
|
|
||||||
|
|
||||||
async send(event: string, payload: Record<string, unknown> = {}) {
|
async send(event: string, payload: Record<string, unknown> = {}) {
|
||||||
if (isDisabled) return true;
|
if (isDisabled) return true;
|
||||||
return sendEvent(event, payload);
|
return sendEvent(event, payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
// Clean up resources if needed
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8692,7 +8692,6 @@ __metadata:
|
|||||||
koa2-ratelimit: "npm:^1.1.3"
|
koa2-ratelimit: "npm:^1.1.3"
|
||||||
lodash: "npm:4.17.21"
|
lodash: "npm:4.17.21"
|
||||||
msw: "npm:1.3.0"
|
msw: "npm:1.3.0"
|
||||||
node-schedule: "npm:2.1.1"
|
|
||||||
ora: "npm:5.4.1"
|
ora: "npm:5.4.1"
|
||||||
p-map: "npm:4.0.0"
|
p-map: "npm:4.0.0"
|
||||||
passport-local: "npm:1.0.0"
|
passport-local: "npm:1.0.0"
|
||||||
@ -8804,7 +8803,6 @@ __metadata:
|
|||||||
markdown-it-sub: "npm:^1.0.0"
|
markdown-it-sub: "npm:^1.0.0"
|
||||||
markdown-it-sup: "npm:1.0.0"
|
markdown-it-sup: "npm:1.0.0"
|
||||||
msw: "npm:1.3.0"
|
msw: "npm:1.3.0"
|
||||||
node-schedule: "npm:2.1.1"
|
|
||||||
prismjs: "npm:1.30.0"
|
prismjs: "npm:1.30.0"
|
||||||
qs: "npm:6.11.1"
|
qs: "npm:6.11.1"
|
||||||
react: "npm:18.3.1"
|
react: "npm:18.3.1"
|
||||||
@ -8855,7 +8853,6 @@ __metadata:
|
|||||||
koa: "npm:2.16.1"
|
koa: "npm:2.16.1"
|
||||||
lodash: "npm:4.17.21"
|
lodash: "npm:4.17.21"
|
||||||
msw: "npm:1.3.0"
|
msw: "npm:1.3.0"
|
||||||
node-schedule: "npm:2.1.1"
|
|
||||||
qs: "npm:6.11.1"
|
qs: "npm:6.11.1"
|
||||||
react: "npm:18.3.1"
|
react: "npm:18.3.1"
|
||||||
react-dom: "npm:18.3.1"
|
react-dom: "npm:18.3.1"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user