fix(db): 启用冲突键排序去重并增加死锁重试机制
修改数据库管理器配置,默认启用冲突键排序去重功能,保留最大时间戳记录 增加死锁重试机制,默认重试3次,基础延迟100毫秒 添加相关测试用例验证排序去重和死锁重试功能
This commit is contained in:
@@ -931,8 +931,8 @@ class DatabaseManager {
|
|||||||
tableRef: this.config.roomStatusTable ?? 'room_status.room_status_moment',
|
tableRef: this.config.roomStatusTable ?? 'room_status.room_status_moment',
|
||||||
forceOnlineStatusOnWrite: false,
|
forceOnlineStatusOnWrite: false,
|
||||||
forceUpdateOnConflict: false,
|
forceUpdateOnConflict: false,
|
||||||
sortAndDedupByConflictKey: false,
|
sortAndDedupByConflictKey: true,
|
||||||
deadlockRetryAttempts: 0,
|
deadlockRetryAttempts: 3,
|
||||||
deadlockRetryBaseDelayMs: 100,
|
deadlockRetryBaseDelayMs: 100,
|
||||||
logPrefix: 'upsertRoomStatus',
|
logPrefix: 'upsertRoomStatus',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -692,6 +692,68 @@ describe('DatabaseManager: room_status upsert SQL', () => {
|
|||||||
assert.equal(result.rowCount, 1);
|
assert.equal(result.rowCount, 1);
|
||||||
assert.equal(calls, 3);
|
assert.equal(calls, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sorts and dedups old room_status by conflict key, keeping max ts_ms', () => {
|
||||||
|
const dm = new DatabaseManager({ host: 'x', port: 5432, user: 'x', password: 'x', database: 'x', roomStatusTable: 'room_status.room_status_moment' });
|
||||||
|
const built = dm._buildRoomStatusUpsertQuery([
|
||||||
|
{ ...buildBasePayload(), hotel_id: 2, room_id: '102', device_id: 'dev-b', ts_ms: 1000 },
|
||||||
|
{ ...buildBasePayload(), hotel_id: 1, room_id: '101', device_id: 'dev-a', ts_ms: 3000 },
|
||||||
|
{ ...buildBasePayload(), hotel_id: 2, room_id: '102', device_id: 'dev-b', ts_ms: 5000 },
|
||||||
|
], {
|
||||||
|
tableName: 'room_status.room_status_moment',
|
||||||
|
conflictColumns: ['hotel_id', 'room_id', 'device_id'],
|
||||||
|
includeGuid: true,
|
||||||
|
autoCreatePartitions: true,
|
||||||
|
tableRef: 'room_status.room_status_moment',
|
||||||
|
forceOnlineStatusOnWrite: false,
|
||||||
|
forceUpdateOnConflict: false,
|
||||||
|
sortAndDedupByConflictKey: true,
|
||||||
|
logPrefix: 'upsertRoomStatus',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(built.uniqueEvents.length, 2);
|
||||||
|
assert.equal(built.uniqueEvents[0].hotel_id, 1);
|
||||||
|
assert.equal(built.uniqueEvents[0].room_id, '101');
|
||||||
|
assert.equal(built.uniqueEvents[0].device_id, 'dev-a');
|
||||||
|
assert.equal(built.uniqueEvents[1].hotel_id, 2);
|
||||||
|
assert.equal(built.uniqueEvents[1].room_id, '102');
|
||||||
|
assert.equal(built.uniqueEvents[1].device_id, 'dev-b');
|
||||||
|
assert.equal(built.uniqueEvents[1].ts_ms, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('retries old room_status on deadlock', async () => {
|
||||||
|
const dm = new DatabaseManager({ host: 'x', port: 5432, user: 'x', password: 'x', database: 'x', roomStatusTable: 'room_status.room_status_moment' });
|
||||||
|
let calls = 0;
|
||||||
|
dm.pool = {
|
||||||
|
query: async () => {
|
||||||
|
calls += 1;
|
||||||
|
if (calls < 3) {
|
||||||
|
const err = new Error('deadlock detected');
|
||||||
|
err.code = '40P01';
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
return { rowCount: 1 };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
dm._sleep = async () => {};
|
||||||
|
|
||||||
|
const result = await dm._upsertRoomStatusToTarget([buildBasePayload()], {
|
||||||
|
tableName: 'room_status.room_status_moment',
|
||||||
|
conflictColumns: ['hotel_id', 'room_id', 'device_id'],
|
||||||
|
includeGuid: true,
|
||||||
|
autoCreatePartitions: true,
|
||||||
|
tableRef: 'room_status.room_status_moment',
|
||||||
|
forceOnlineStatusOnWrite: false,
|
||||||
|
forceUpdateOnConflict: false,
|
||||||
|
sortAndDedupByConflictKey: true,
|
||||||
|
deadlockRetryAttempts: 3,
|
||||||
|
deadlockRetryBaseDelayMs: 1,
|
||||||
|
logPrefix: 'upsertRoomStatus',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(result.rowCount, 1);
|
||||||
|
assert.equal(calls, 3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('DatabaseManager: insertHeartbeatEventsDual', () => {
|
describe('DatabaseManager: insertHeartbeatEventsDual', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user