batch kill dead clients

This commit is contained in:
Ben
2025-11-21 18:42:00 -05:00
parent ff84d8284f
commit 6f6abe5e2d
2 changed files with 31 additions and 11 deletions
+21 -3
View File
@@ -19,13 +19,31 @@ export class ClientService {
} }
public async killDeadClients() { public async killDeadClients() {
const batchSize = 500;
return await this.clientRepository const clients = await this.clientRepository
.createQueryBuilder('client')
.where('client.deletedAt IS NULL')
.andWhere('client.updatedAt < NOW() - INTERVAL \'5 minutes\'')
.orderBy('client.id', 'ASC') // consistent lock order ← prevents deadlocks
.limit(batchSize) // small batches ← prevents lock explosion
.setLock('pessimistic_write') // adds FOR UPDATE SKIP LOCKED
.getMany();
if (clients.length === 0) {
return false; // nothing to do (caller can stop looping)
}
const ids = clients.map(c => c.id);
await this.clientRepository
.createQueryBuilder() .createQueryBuilder()
.update(ClientEntity) .update(ClientEntity)
.set({ deletedAt: () => "NOW()" }) .set({ deletedAt: () => 'NOW()' })
.where("deletedAt IS NULL AND updatedAt < NOW() - interval '5 minutes' ") .whereInIds(ids)
.execute(); .execute();
return true; // tell caller there might be more batches
} }
//public async heartbeat(id, hashRate: number, updatedAt: Date) { //public async heartbeat(id, hashRate: number, updatedAt: Date) {
+3 -1
View File
@@ -30,7 +30,9 @@ export class AppService implements OnModuleInit {
setInterval(async () => { setInterval(async () => {
console.log('Killing dead clients'); console.log('Killing dead clients');
await this.clientService.killDeadClients(); while (await this.clientService.killDeadClients()) {
console.log('Finished killing clients');
}
}, 1000 * 60 * 5); }, 1000 * 60 * 5);
setInterval(async () => { setInterval(async () => {