Skip to content

Commit ec3fb2c

Browse files
authored
fix(awareness-service): dedupe deliveries by content hash so envelope updates re-deliver (#989)
* fix(awareness-service): dedupe deliveries by content hash so envelope updates re-deliver (#984) * fix(awareness-service): use generated migration timestamp and safe nullable-backfill-notnull column add
1 parent ca96956 commit ec3fb2c

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
3+
/**
4+
* Dedupe deliveries by payload content, not packet id alone. Adds a
5+
* `contentHash` column to `deliveries` and swaps the unique key from
6+
* (subscriptionId, packetId) to (subscriptionId, packetId, contentHash) so that
7+
* re-ingesting an updated MetaEnvelope queues a fresh delivery instead of being
8+
* silently dropped by the old constraint.
9+
*/
10+
export class AddDeliveryContentHash1780404367748 implements MigrationInterface {
11+
name = "AddDeliveryContentHash1780404367748";
12+
13+
public async up(queryRunner: QueryRunner): Promise<void> {
14+
// Add nullable first, then backfill: a straight `ADD ... NOT NULL`
15+
// fails on any table that already has delivery rows.
16+
await queryRunner.query(
17+
`ALTER TABLE "deliveries" ADD "contentHash" character varying`,
18+
);
19+
// Backfill legacy rows with a single constant. This preserves the old
20+
// one-delivery-per-(subscription, packet) semantics for rows that
21+
// predate content-based dedup.
22+
await queryRunner.query(
23+
`UPDATE "deliveries" SET "contentHash" = '' WHERE "contentHash" IS NULL`,
24+
);
25+
await queryRunner.query(
26+
`ALTER TABLE "deliveries" ALTER COLUMN "contentHash" SET NOT NULL`,
27+
);
28+
await queryRunner.query(
29+
`ALTER TABLE "deliveries" DROP CONSTRAINT "uq_delivery_subscription_packet"`,
30+
);
31+
await queryRunner.query(
32+
`ALTER TABLE "deliveries" ADD CONSTRAINT "uq_delivery_subscription_packet_content" UNIQUE ("subscriptionId", "packetId", "contentHash")`,
33+
);
34+
}
35+
36+
public async down(queryRunner: QueryRunner): Promise<void> {
37+
await queryRunner.query(
38+
`ALTER TABLE "deliveries" DROP CONSTRAINT "uq_delivery_subscription_packet_content"`,
39+
);
40+
await queryRunner.query(
41+
`ALTER TABLE "deliveries" DROP COLUMN "contentHash"`,
42+
);
43+
await queryRunner.query(
44+
`ALTER TABLE "deliveries" ADD CONSTRAINT "uq_delivery_subscription_packet" UNIQUE ("subscriptionId", "packetId")`,
45+
);
46+
}
47+
}

0 commit comments

Comments
 (0)