( deps: AdmissionDeps = defaultDeps, )
| 94 | * admitFromQueue takes a per-model advisory xact lock. |
| 95 | */ |
| 96 | export async function runAdmissionTick( |
| 97 | deps: AdmissionDeps = defaultDeps, |
| 98 | ): Promise<AdmissionTickResult> { |
| 99 | const now = (deps.now ?? (() => new Date()))() |
| 100 | // Run eviction before admission so a banned user freed from a slot in this |
| 101 | // tick frees room for a queued user to be admitted in the same tick. |
| 102 | const [expired, evictedBanned] = await Promise.all([ |
| 103 | deps.sweepExpired(now, deps.graceMs), |
| 104 | deps.evictBanned(), |
| 105 | ]) |
| 106 | |
| 107 | const models = deps.models ?? SUPPORTED_FREEBUFF_MODELS.map((m) => m.id) |
| 108 | |
| 109 | // One probe per tick covers every model — the Fireworks metrics endpoint |
| 110 | // returns all deployments in a single response. Models without a dedicated |
| 111 | // deployment (e.g. serverless) aren't in the map; treat their absence as |
| 112 | // 'healthy' so admission continues. TODO: when those models move to their |
| 113 | // own deployments, drop the absence-default and require an explicit entry. |
| 114 | const fleet = await deps.getFleetHealth() |
| 115 | |
| 116 | // Run per-model admission in parallel — they only contend on independent |
| 117 | // advisory locks and a single update each. |
| 118 | const perModel = await Promise.all( |
| 119 | models.map(async (model) => { |
| 120 | const isRegisteredModel = SUPPORTED_FREEBUFF_MODELS.some( |
| 121 | (m) => m.id === model, |
| 122 | ) |
| 123 | const health = |
| 124 | !isRegisteredModel || isFreebuffModelAvailable(model, now) |
| 125 | ? (fleet[model] ?? 'healthy') |
| 126 | : 'unhealthy' |
| 127 | const { admitted, skipped } = await deps.admitFromQueue({ |
| 128 | model, |
| 129 | sessionLengthMs: deps.sessionLengthMs, |
| 130 | now, |
| 131 | health, |
| 132 | }) |
| 133 | const depth = await deps.queueDepth({ model }) |
| 134 | return { model, admittedCount: admitted.length, depth, skipped } |
| 135 | }), |
| 136 | ) |
| 137 | |
| 138 | const activeCountByModel = await deps.activeCountsByModel() |
| 139 | const totalAdmitted = perModel.reduce((s, r) => s + r.admittedCount, 0) |
| 140 | const queueDepthByModel = Object.fromEntries( |
| 141 | perModel.map((r) => [r.model, r.depth]), |
| 142 | ) |
| 143 | const skipped = perModel.find((r) => r.skipped)?.skipped ?? null |
| 144 | |
| 145 | return { |
| 146 | expired, |
| 147 | evictedBanned, |
| 148 | admitted: totalAdmitted, |
| 149 | queueDepthByModel, |
| 150 | activeCountByModel, |
| 151 | skipped, |
| 152 | } |
| 153 | } |
no test coverage detected