diff --git a/changelog.d/393.misc b/changelog.d/393.misc new file mode 100644 index 00000000..54104bb4 --- /dev/null +++ b/changelog.d/393.misc @@ -0,0 +1 @@ +Fix PostgreSQL errors when a metric activity is recorded twice \ No newline at end of file diff --git a/src/datastore/postgres/PgDatastore.ts b/src/datastore/postgres/PgDatastore.ts index aa3236db..309d8cc9 100644 --- a/src/datastore/postgres/PgDatastore.ts +++ b/src/datastore/postgres/PgDatastore.ts @@ -296,7 +296,10 @@ export class PgDatastore implements Datastore { date = date || new Date(); const userId = (user instanceof SlackGhost) ? user.toEntry().id : user.userId; - await this.postgresDb.none("INSERT INTO metrics_activities (user_id, room_id, date) VALUES(${userId}, ${roomId}, ${date})", { + await this.postgresDb.none( + "INSERT INTO metrics_activities (user_id, room_id, date) " + + "VALUES(${userId}, ${roomId}, ${date}) " + + "ON CONFLICT ON CONSTRAINT cons_activities_unique DO NOTHING;", { date: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`, roomId: room.toEntry().id, userId, diff --git a/src/tests/integration/SharedDatastoreTests.ts b/src/tests/integration/SharedDatastoreTests.ts index 628c6e41..87764374 100644 --- a/src/tests/integration/SharedDatastoreTests.ts +++ b/src/tests/integration/SharedDatastoreTests.ts @@ -277,4 +277,28 @@ export const doDatastoreTests = (ds: () => Datastore, roomsAfterEach: () => void }); }); }); + + describe("metrics", () => { + it("should not throw when an activity is upserted twice", async () => { + const user = SlackGhost.fromEntry(null as any, { + display_name: "A displayname", + avatar_url: "Some avatar", + id: "someid1", + slack_id: "FOOBAR", + team_id: "BARBAZ", + }, null); + const room = new BridgedRoom({} as any, { + inbound_id: "a_remote_id", + matrix_room_id: "a_matrix_id", + slack_channel_id: "a_channel_id", + slack_channel_name: "a_channel_name", + slack_team_id: "a_team_id", + slack_webhook_uri: "a_webhook_uri", + puppet_owner: undefined, + }, {} as any); + const date = new Date(); + await ds().upsertActivityMetrics(user, room, date); + await ds().upsertActivityMetrics(user, room, date); + }); + }); };