+
- **Feedback & Ideas:** We ship fast. Missing something? [Request a new feature](https://github.com/stablyai/orca/issues).
- **Privacy:** See the [privacy & telemetry docs](https://www.onorca.dev/docs/telemetry) for what anonymous usage data Orca collects and how to opt out.
diff --git a/cloud/apps/relay/src/assignment-connection-headroom-postgres.test.ts b/cloud/apps/relay/src/assignment-connection-headroom-postgres.test.ts
index 6ac9521c3d6..80a74a47eeb 100644
--- a/cloud/apps/relay/src/assignment-connection-headroom-postgres.test.ts
+++ b/cloud/apps/relay/src/assignment-connection-headroom-postgres.test.ts
@@ -44,6 +44,12 @@ describePostgres('PostgreSQL assignment connection headroom', () => {
`DELETE FROM relay_assignments
WHERE user_id LIKE 'connection-headroom-postgres-%'`
)
+ // A snapshot left by an aborted run rejects the replayed watermark
+ // with stale_connection_snapshot.
+ await database.query(
+ `DELETE FROM relay_cell_connection_snapshots WHERE cell_id = ?`,
+ [cell.id]
+ )
await database.query(
`DELETE FROM relay_cell_connection_runtime WHERE cell_id = ?`,
[cell.id]
diff --git a/cloud/apps/relay/src/assignment-control-supersession-postgres.test.ts b/cloud/apps/relay/src/assignment-control-supersession-postgres.test.ts
index 10193b78cc6..cf8819686b5 100644
--- a/cloud/apps/relay/src/assignment-control-supersession-postgres.test.ts
+++ b/cloud/apps/relay/src/assignment-control-supersession-postgres.test.ts
@@ -38,6 +38,10 @@ describePostgres('PostgreSQL control supersession', () => {
[identity.userId]
)
await database.query(`DELETE FROM relay_assignments WHERE user_id = ?`, [identity.userId])
+ // A snapshot left by an aborted run rejects the replayed watermark with stale_connection_snapshot.
+ await database.query(`DELETE FROM relay_cell_connection_snapshots WHERE cell_id = ?`, [
+ cell.id
+ ])
await database.query(`DELETE FROM relay_cell_connection_runtime WHERE cell_id = ?`, [cell.id])
await database.query(`DELETE FROM relay_cell_connection_limits WHERE cell_id = ?`, [cell.id])
await database.query(`DELETE FROM relay_cell_runtime WHERE cell_id = ?`, [cell.id])
diff --git a/cloud/apps/relay/src/assignment-store.ts b/cloud/apps/relay/src/assignment-store.ts
index d0517d46746..9d240e304a7 100644
--- a/cloud/apps/relay/src/assignment-store.ts
+++ b/cloud/apps/relay/src/assignment-store.ts
@@ -3202,8 +3202,7 @@ export class RelayAssignmentStore {
)
const requestDelta = ACTIVITY_REQUEST_UNITS[kind] * (after - before)
if (requestDelta !== 0) {
- await this.lockCellInventory(transaction, 'request')
- await this.adjustCellReservation(transaction, text(row, 'cell_id'), requestDelta)
+ await this.adjustCellReservationAtomically(transaction, text(row, 'cell_id'), requestDelta)
}
})
})
@@ -3263,9 +3262,12 @@ export class RelayAssignmentStore {
}
const units = ACTIVITY_REQUEST_UNITS[input.kind]
if (existing) {
- await this.lockCellInventory(transaction, 'request')
+ // Why: a client-chosen activity id can move between cells, so lock the
+ // one or two rows this path touches in cell_id order, the same order
+ // placement takes the inventory in, and no cycle can form.
+ await this.lockCellRows(transaction, [text(existing, 'cell_id'), input.cellId])
await this.removeActivityLease(transaction, identity, existing, now)
- await this.adjustCellReservation(transaction, input.cellId, units)
+ await this.adjustCellReservationAtomically(transaction, input.cellId, units)
}
await this.adjustActivityCount(transaction, identity, input.kind, 1, expiresAt, now)
await transaction.query(
@@ -3580,8 +3582,7 @@ export class RelayAssignmentStore {
)
await this.touchAssignment(transaction, identity, expiresAt, now)
} else {
- await this.lockCellInventory(transaction, 'request')
- await this.adjustCellReservation(transaction, input.cellId, 1)
+ await this.adjustCellReservationAtomically(transaction, input.cellId, 1)
await this.adjustActivityCount(transaction, identity, 'control', 1, expiresAt, now)
await transaction.query(
`INSERT INTO relay_assignment_activity_leases
@@ -6954,6 +6955,19 @@ export class RelayAssignmentStore {
return rows
}
+ // Per-connection paths touch one or two cells. Locking exactly those rows,
+ // in the same ascending order the inventory lock uses (ORDER BY fixes the
+ // row-lock order), keeps them off the fleet-wide lock without a cycle.
+ private async lockCellRows(database: RelayDatabase, cellIds: string[]): Promise