crash-loop-breaker.integration.test.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. // Integration test for CLAUDE.md §7.4 — after `crashLoopThreshold`
  2. // consecutive crashes within `crashLoopWindowMs` for the same
  3. // (projectId, deploymentId), the breaker trips and subsequent invokes
  4. // short-circuit with `deployment_unhealthy` until the window expires.
  5. // We confirm: (a) the early invocations crash and surface
  6. // `isolate_crashed`, (b) by the 5th call the breaker has tripped and
  7. // returns `deployment_unhealthy` without spawning a new isolate.
  8. import { describe, expect, test } from 'bun:test';
  9. import { runFixtureRepeated } from './test-helpers.js';
  10. describe('crash-loop breaker (integration)', () => {
  11. test('after 3 consecutive crashes, deployment marked unhealthy', async () => {
  12. const { results, cleanup } = await runFixtureRepeated({
  13. fnName: 'v',
  14. deploymentId: 'd1',
  15. count: 5,
  16. fnSource: `
  17. import { query } from '@briven/cli/server';
  18. export const v = query(async () => { Deno.exit(1); });
  19. `,
  20. });
  21. try {
  22. expect(results.length).toBe(5);
  23. const codes = results.filter((r) => !r.ok).map((r) => (r as { code: string }).code);
  24. // First few should be isolate_crashed; later ones should flip to deployment_unhealthy.
  25. expect(codes).toContain('isolate_crashed');
  26. // Last invocation should be the breaker tripped.
  27. const last = results[results.length - 1];
  28. expect(last.ok).toBe(false);
  29. if (!last.ok) {
  30. expect(last.code).toBe('deployment_unhealthy');
  31. }
  32. } finally {
  33. await cleanup();
  34. }
  35. }, 60_000);
  36. });