| 46 | } |
| 47 | |
| 48 | export class ScoresStorageMongoDB extends ScoresStorage { |
| 49 | #connector: MongoDBConnector; |
| 50 | #skipDefaultIndexes?: boolean; |
| 51 | #indexes?: MongoDBIndexConfig[]; |
| 52 | |
| 53 | /** Collections managed by this domain */ |
| 54 | static readonly MANAGED_COLLECTIONS = [TABLE_SCORERS] as const; |
| 55 | |
| 56 | /** Anchor is the score row's creation time, stored as a BSON date. */ |
| 57 | static override readonly retentionTables: RetentionTablesDescriptor = { |
| 58 | scorers: { table: TABLE_SCORERS, column: 'createdAt', indexed: true }, |
| 59 | }; |
| 60 | |
| 61 | constructor(config: MongoDBDomainConfig) { |
| 62 | super(); |
| 63 | this.#connector = resolveMongoDBConfig(config); |
| 64 | this.#skipDefaultIndexes = config.skipDefaultIndexes; |
| 65 | // Filter indexes to only those for collections managed by this domain |
| 66 | this.#indexes = config.indexes?.filter(idx => |
| 67 | (ScoresStorageMongoDB.MANAGED_COLLECTIONS as readonly string[]).includes(idx.collection), |
| 68 | ); |
| 69 | } |
| 70 | |
| 71 | private async getCollection(name: string) { |
| 72 | return this.#connector.getCollection(name); |
| 73 | } |
| 74 | |
| 75 | /** Delete scorer results older than the `scorers` policy's `maxAge`, batched. */ |
| 76 | async prune(policies: Record<string, TableRetentionPolicy>, options?: PruneOptions): Promise<PruneResult[]> { |
| 77 | const targets = resolveTargets({ |
| 78 | policies, |
| 79 | descriptor: ScoresStorageMongoDB.retentionTables, |
| 80 | order: ['scorers'], |
| 81 | }); |
| 82 | return runPrune({ connector: this.#connector, domain: 'scores', targets, options, logger: this.logger }); |
| 83 | } |
| 84 | |
| 85 | /** |
| 86 | * Returns default index definitions for the scores domain collections. |
| 87 | * These indexes optimize common query patterns for score lookups. |
| 88 | */ |
| 89 | getDefaultIndexDefinitions(): MongoDBIndexConfig[] { |
| 90 | return [ |
| 91 | { collection: TABLE_SCORERS, keys: { id: 1 }, options: { unique: true } }, |
| 92 | { collection: TABLE_SCORERS, keys: { scorerId: 1 } }, |
| 93 | { collection: TABLE_SCORERS, keys: { runId: 1 } }, |
| 94 | { collection: TABLE_SCORERS, keys: { entityId: 1, entityType: 1 } }, |
| 95 | { collection: TABLE_SCORERS, keys: { traceId: 1, spanId: 1 } }, |
| 96 | { collection: TABLE_SCORERS, keys: { createdAt: -1 } }, |
| 97 | { collection: TABLE_SCORERS, keys: { source: 1 } }, |
| 98 | ]; |
| 99 | } |
| 100 | |
| 101 | async createDefaultIndexes(): Promise<void> { |
| 102 | if (this.#skipDefaultIndexes) { |
| 103 | return; |
| 104 | } |
| 105 |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…