mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
fix(relay): never call a reserve cell's hosts stranded when it goes existing-only (#30609)
A reserve cell keeps no activity rows and its ledger stamps last_activity_at, so the stranded rule read its connected hosts as unserved and re-placed them.
This commit is contained in:
@@ -228,6 +228,27 @@ describe('reserve-mode census', () => {
|
||||
await restore()
|
||||
})
|
||||
|
||||
it('keeps a connected host pinned when its reserve cell goes existing-only after a ledger write', async () => {
|
||||
let now = 1_000
|
||||
const store = await setup(() => now)
|
||||
const identity = { userId: 'user-a', relayHostId: 'host000000000001' }
|
||||
const first = await store.assign(identity)
|
||||
await setReserve(store, [first.cellId])
|
||||
// The reserve ledger stamps last_activity_at and the cell keeps no activity rows.
|
||||
now += 5 * 60_000
|
||||
await database!.query('DELETE FROM relay_assignment_activity_leases WHERE user_id = ?', [identity.userId])
|
||||
await database!.query('UPDATE relay_assignments SET last_activity_at = ? WHERE user_id = ?', [now, identity.userId])
|
||||
await store.setCellAdmissionState(first.cellId, 'existing-only')
|
||||
now += 2 * 60_000
|
||||
expect(await store.assign(identity)).toMatchObject({
|
||||
cellId: first.cellId,
|
||||
assignmentEpoch: first.assignmentEpoch
|
||||
})
|
||||
const { unknown, restore } = await unknownSet(() => now)
|
||||
expect((await unknown.assign(identity)).assignmentEpoch).toBe(first.assignmentEpoch)
|
||||
await restore()
|
||||
})
|
||||
|
||||
// Only the first reserve-set read is held; it is released (or failed) by the test.
|
||||
function holdFirstRead(options: { fail?: boolean } = {}) {
|
||||
const query = database!.query.bind(database!)
|
||||
|
||||
@@ -1290,6 +1290,11 @@ export class RelayAssignmentStore {
|
||||
if (state !== 'existing-only') {
|
||||
return false
|
||||
}
|
||||
// A reserve cell keeps no activity rows and its ledger stamps last_activity_at, so zero
|
||||
// leases proves nothing; a dead one is left to the dead-reserve path and its fence.
|
||||
if (await this.mayBeReserveCell(text(existing, 'cell_id'), transaction)) {
|
||||
return false
|
||||
}
|
||||
const liveLeases = (
|
||||
await transaction.query(
|
||||
`SELECT COUNT(*) AS live FROM relay_assignment_activity_leases
|
||||
|
||||
Reference in New Issue
Block a user