import { assert, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as TestClock from "effect/testing/TestClock"; import * as SourceControlRateLimit from "./SourceControlRateLimit.ts"; const github = { provider: "github" as const, host: "github.com" }; it("parses Retry-After seconds and HTTP dates", () => { assert.equal(SourceControlRateLimit.retryAtFromHeader("120", 1_000), 121_000); assert.equal( SourceControlRateLimit.retryAtFromHeader("Thu, 01 Jan 1970 00:02:01 GMT", 1_000), 121_000, ); assert.isUndefined(SourceControlRateLimit.retryAtFromHeader("later", 1_000)); }); it.effect("backs off repeated rate limits until a successful request", () => Effect.gen(function* () { yield* TestClock.setTime(0); const limits = yield* SourceControlRateLimit.SourceControlRateLimit; const firstLease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease: firstLease }); const firstPause = yield* Effect.flip(limits.check(github)); assert.deepInclude(firstPause, { _tag: "SourceControlRateLimitPausedError", provider: "github", host: "github.com", retryAt: 30_000, }); assert.equal( firstPause.detail, "github requests to github.com are paused until the rate limit resets.", ); assert.equal(firstPause.message, firstPause.detail); yield* TestClock.adjust("30 seconds"); const secondLease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease: secondLease }); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 90_000); yield* TestClock.adjust("60 seconds"); const successLease = yield* limits.check(github); yield* limits.recordSuccess({ ...github, lease: successLease }); const resetLease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease: resetLease }); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 120_000); }).pipe(Effect.provide(SourceControlRateLimit.layer)), ); it.effect("honors a provider reset time", () => Effect.gen(function* () { yield* TestClock.setTime(1_000); const limits = yield* SourceControlRateLimit.SourceControlRateLimit; const lease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease, retryAt: 121_000 }); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 121_000); yield* TestClock.adjust("119999 millis"); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 121_000); yield* TestClock.adjust("1 millis"); assert.equal(yield* limits.check(github), 1); }).pipe(Effect.provide(SourceControlRateLimit.layer)), ); it.effect("lets an interactive request through without clearing an active pause", () => Effect.gen(function* () { yield* TestClock.setTime(1_000); const limits = yield* SourceControlRateLimit.SourceControlRateLimit; const lease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease, retryAt: 121_000 }); const interactiveLease = yield* limits.check(github, { allowPaused: true }); yield* limits.recordSuccess({ ...github, lease: interactiveLease }); assert.equal(interactiveLease, 1); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 121_000); yield* limits.recordRateLimit({ ...github, lease: interactiveLease, retryAt: 61_000 }); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 121_000); }).pipe(Effect.provide(SourceControlRateLimit.layer)), ); it.effect("keeps providers and hosts isolated", () => Effect.gen(function* () { const limits = yield* SourceControlRateLimit.SourceControlRateLimit; const lease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease }); assert.equal(yield* limits.check({ provider: "gitlab", host: "github.com" }), 0); assert.equal(yield* limits.check({ provider: "github", host: "github.example.com" }), 0); }).pipe(Effect.provide(SourceControlRateLimit.layer)), ); it.effect("does not let an older success clear a concurrent pause", () => Effect.gen(function* () { const limits = yield* SourceControlRateLimit.SourceControlRateLimit; const firstLease = yield* limits.check(github); const concurrentLease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease: firstLease }); yield* limits.recordSuccess({ ...github, lease: concurrentLease }); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 30_000); }).pipe(Effect.provide(SourceControlRateLimit.layer)), ); it.effect("keeps a fresh provider reset from an older request", () => Effect.gen(function* () { yield* TestClock.setTime(0); const limits = yield* SourceControlRateLimit.SourceControlRateLimit; const staleLease = yield* limits.check(github); yield* limits.recordRateLimit({ ...github, lease: staleLease }); yield* TestClock.adjust("31 seconds"); yield* limits.recordRateLimit({ ...github, lease: staleLease, retryAt: 61_000 }); assert.equal((yield* Effect.flip(limits.check(github))).retryAt, 61_000); }).pipe(Effect.provide(SourceControlRateLimit.layer)), );