Skip to content
Merged
4 changes: 4 additions & 0 deletions .infra/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,10 @@ export const workers: Worker[] = [
topic: 'api.v1.generate-channel-digest',
subscription: 'api.generate-channel-digest',
},
{
topic: 'api.v1.generate-channel-highlight',
subscription: 'api.generate-channel-highlight',
},
];

export const personalizedDigestWorkers: Worker[] = [
Expand Down
4 changes: 4 additions & 0 deletions .infra/crons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ export const crons: Cron[] = [
name: 'channel-digests',
schedule: '17 4 * * *',
},
{
name: 'channel-highlights',
schedule: '12 * * * *',
},
{
name: 'clean-expired-better-auth-sessions',
schedule: '0 3 * * *',
Expand Down
86 changes: 86 additions & 0 deletions __tests__/cron/channelHighlights.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import type { DataSource } from 'typeorm';
import createOrGetConnection from '../../src/db';
import { ChannelHighlightDefinition } from '../../src/entity/ChannelHighlightDefinition';
import * as typedPubsub from '../../src/common/typedPubsub';
import channelHighlights from '../../src/cron/channelHighlights';
import { crons } from '../../src/cron/index';

let con: DataSource;

beforeAll(async () => {
con = await createOrGetConnection();
});

describe('channelHighlights cron', () => {
afterEach(async () => {
jest.restoreAllMocks();
await con.getRepository(ChannelHighlightDefinition).clear();
});

it('should be registered', () => {
const registeredCron = crons.find(
(item) => item.name === channelHighlights.name,
);

expect(registeredCron).toBeDefined();
});

it('should enqueue active highlight definitions', async () => {
const triggerTypedEventSpy = jest
.spyOn(typedPubsub, 'triggerTypedEvent')
.mockResolvedValue();

await con.getRepository(ChannelHighlightDefinition).save([
{
channel: 'backend',
mode: 'shadow',
candidateHorizonHours: 72,
maxItems: 10,
},
{
channel: 'vibes',
mode: 'shadow',
candidateHorizonHours: 72,
maxItems: 10,
},
{
channel: 'disabled',
mode: 'disabled',
candidateHorizonHours: 72,
maxItems: 10,
},
]);

const startedAt = Date.now();
await channelHighlights.handler(con, {} as never, {} as never);
const completedAt = Date.now();

expect(triggerTypedEventSpy.mock.calls).toEqual([
[
{},
'api.v1.generate-channel-highlight',
{
channel: 'backend',
scheduledAt: expect.any(String),
},
],
[
{},
'api.v1.generate-channel-highlight',
{
channel: 'vibes',
scheduledAt: expect.any(String),
},
],
]);

const scheduledAt = Date.parse(
triggerTypedEventSpy.mock.calls[0][2].scheduledAt,
);
expect(scheduledAt).toBeGreaterThanOrEqual(startedAt);
expect(scheduledAt).toBeLessThanOrEqual(completedAt);
expect(triggerTypedEventSpy.mock.calls[0][2].scheduledAt).toBe(
triggerTypedEventSpy.mock.calls[1][2].scheduledAt,
);
});
});
Loading
Loading