diff --git a/apps/randomness/src/Drand.ts b/apps/randomness/src/Drand.ts index 2a0d7c22c7..7d6be9eb05 100644 --- a/apps/randomness/src/Drand.ts +++ b/apps/randomness/src/Drand.ts @@ -7,6 +7,8 @@ export enum DrandStatus { FAILED = "FAILED", } +export const FinalizedDrandStatuses = [DrandStatus.SUCCESS, DrandStatus.FAILED] + export class Drand { #round: bigint #signature: Hex diff --git a/apps/randomness/src/DrandRepository.ts b/apps/randomness/src/DrandRepository.ts index db5e94183d..2411e2119c 100644 --- a/apps/randomness/src/DrandRepository.ts +++ b/apps/randomness/src/DrandRepository.ts @@ -1,10 +1,12 @@ import { type Hex, type UUID, bigIntToZeroPadded, unknownToError } from "@happy.tech/common" import { type Result, ResultAsync } from "neverthrow" -import { Drand } from "./Drand" +import { Drand, FinalizedDrandStatuses } from "./Drand" import { DIGITS_MAX_UINT256 } from "./constants" import { db } from "./db/driver" import type { DrandRow } from "./db/types" +const PRUNE_INTERVAL_ROUNDS = 20n // 1 minute + export class DrandRepository { private cache: Drand[] = [] @@ -80,4 +82,20 @@ export class DrandRepository { unknownToError, ).map(() => undefined) } + + async pruneDrands(latestRound: bigint): Promise> { + const cutoffRound = latestRound - PRUNE_INTERVAL_ROUNDS + + this.cache = this.cache.filter( + (drand) => !(drand.round <= cutoffRound && FinalizedDrandStatuses.includes(drand.status)), + ) + return await ResultAsync.fromPromise( + db + .deleteFrom("drands") + .where("round", "<=", bigIntToZeroPadded(cutoffRound, DIGITS_MAX_UINT256)) + .where("status", "in", FinalizedDrandStatuses) + .execute(), + unknownToError, + ).map(() => undefined) + } } diff --git a/apps/randomness/src/DrandService.ts b/apps/randomness/src/DrandService.ts index b7e238db25..18f9930c1a 100644 --- a/apps/randomness/src/DrandService.ts +++ b/apps/randomness/src/DrandService.ts @@ -68,6 +68,7 @@ export class DrandService { this.handleNewDrandBeacons() setInterval(this.handleNewDrandBeacons.bind(this), periodMs) + setInterval(this.pruneDrands.bind(this), MS_IN_SECOND * 20) } async getDrandBeacon(round: bigint): Promise> { @@ -140,8 +141,14 @@ export class DrandService { this.pendingGetDrandBeaconPromises.forEach((p) => p.reject()) } + private async pruneDrands() { + const currentRound = this.currentRound() + await this.drandRepository.pruneDrands(currentRound) + } + private async _handleNewDrandBeacons() { const currentRound = this.currentRound() + const drandGaps = this.drandRepository.findRoundGapsInRange(currentRound - env.EVM_DRAND_MARGIN, currentRound) await Promise.all(