Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions apps/web/src/app/api/cron/minimax-token-health/route.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
jest.mock('@/lib/config.server', () => ({ CRON_SECRET: 'cron-secret' }));
jest.mock('@/lib/coding-plans/minimax-token-health', () => ({
sendMiniMaxTokenHealthSlackSummary: jest.fn(),
}));
jest.mock('@sentry/nextjs', () => ({ captureException: jest.fn() }));

import { captureException } from '@sentry/nextjs';
import { sendMiniMaxTokenHealthSlackSummary } from '@/lib/coding-plans/minimax-token-health';
import { GET } from './route';

const mockSendSummary = jest.mocked(sendMiniMaxTokenHealthSlackSummary);
const mockCaptureException = jest.mocked(captureException);

function request(authorization?: string) {
return new Request('http://localhost:3000/api/cron/minimax-token-health', {
headers: authorization ? { authorization } : undefined,
});
}

describe('GET /api/cron/minimax-token-health', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('rejects invalid cron authorization', async () => {
const response = await GET(request('Bearer wrong-secret'));

expect(response.status).toBe(401);
await expect(response.json()).resolves.toEqual({ error: 'Unauthorized' });
expect(mockSendSummary).not.toHaveBeenCalled();
});

it('sends the current token health summary for valid cron authorization', async () => {
mockSendSummary.mockResolvedValue({
checked: 160,
healthy: 155,
badResponse: 3,
denied: 1,
unreachable: 1,
configuration: 0,
needsFollowUp: 4,
});

const response = await GET(request('Bearer cron-secret'));

expect(response.status).toBe(200);
await expect(response.json()).resolves.toMatchObject({
success: true,
totals: { checked: 160, healthy: 155, needsFollowUp: 4 },
});
expect(mockSendSummary).toHaveBeenCalledTimes(1);
});

it('returns a failed cron response when the sweep fails', async () => {
const error = new Error('Slack unavailable');
mockSendSummary.mockRejectedValue(error);

const response = await GET(request('Bearer cron-secret'));

expect(response.status).toBe(500);
await expect(response.json()).resolves.toEqual({
success: false,
error: 'Failed to send MiniMax token health summary',
});
expect(mockCaptureException).toHaveBeenCalledWith(error, {
tags: { endpoint: 'cron/minimax-token-health' },
});
});
});
44 changes: 44 additions & 0 deletions apps/web/src/app/api/cron/minimax-token-health/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { captureException } from '@sentry/nextjs';
import { NextResponse } from 'next/server';

import { CRON_SECRET } from '@/lib/config.server';
import { isCronAuthorizationValid } from '@/lib/cron-auth';
import { sendMiniMaxTokenHealthSlackSummary } from '@/lib/coding-plans/minimax-token-health';

if (!CRON_SECRET) {
throw new Error('CRON_SECRET is not configured in environment variables');
}

// Fans out to every assigned MiniMax key at bounded concurrency
// (MINIMAX_TOKEN_HEALTH_CONCURRENCY); size the duration for that fan-out
// rather than the platform default, matching usage-daily-rollup-repairs.
export const maxDuration = 300;

export async function GET(request: Request) {
if (!isCronAuthorizationValid(request.headers.get('authorization'), CRON_SECRET)) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

try {
const totals = await sendMiniMaxTokenHealthSlackSummary();
console.info('[cron/minimax-token-health] sent', totals);

return NextResponse.json({
success: true,
totals,
timestamp: new Date().toISOString(),
});
} catch (error) {
console.error('[cron/minimax-token-health] failed', {
errorName: error instanceof Error ? error.name : 'UnknownError',
});
captureException(error, {
tags: { endpoint: 'cron/minimax-token-health' },
});

return NextResponse.json(
{ success: false, error: 'Failed to send MiniMax token health summary' },
{ status: 500 }
);
}
}
Loading