feat(reliability): close messaging gateway P0 gaps

This commit is contained in:
wmq
2026-08-01 23:55:41 +08:00
parent 00b0ebb775
commit ad126606f9
15 changed files with 544 additions and 41 deletions
@@ -6,6 +6,7 @@ import {
UpdateDateColumn,
ManyToOne,
JoinColumn,
Index,
} from 'typeorm';
import { TgAccount } from './tg-account.entity';
@@ -18,6 +19,7 @@ export enum ChatType {
}
@Entity('tg_chats')
@Index('IDX_tg_chat_account_identity', ['accountId', 'tgChatId'], { unique: true })
export class TgChat {
@PrimaryGeneratedColumn('uuid')
id: string;
@@ -0,0 +1,36 @@
import { MigrationInterface, QueryRunner, TableIndex } from 'typeorm';
export class TgChatIdentityUnique1700000003000 implements MigrationInterface {
name = 'TgChatIdentityUnique1700000003000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
DELETE FROM tg_chats older
USING tg_chats newer
WHERE older."accountId" = newer."accountId"
AND older."tgChatId" = newer."tgChatId"
AND (
older."updatedAt" < newer."updatedAt"
OR (older."updatedAt" = newer."updatedAt" AND older.id < newer.id)
)
`);
const table = await queryRunner.getTable('tg_chats');
if (!table?.indices.some((index) => index.name === 'IDX_tg_chat_account_identity')) {
await queryRunner.createIndex(
'tg_chats',
new TableIndex({
name: 'IDX_tg_chat_account_identity',
columnNames: ['accountId', 'tgChatId'],
isUnique: true,
}),
);
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
const table = await queryRunner.getTable('tg_chats');
if (table?.indices.some((index) => index.name === 'IDX_tg_chat_account_identity')) {
await queryRunner.dropIndex('tg_chats', 'IDX_tg_chat_account_identity');
}
}
}