Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(notifications): adds index to also deduplicate notifications without source #448

Merged
merged 2 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions migrations/20240711-add-index-unique-notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';

var Sequelize = require('sequelize');

/**
* Actions summary:
*
* addIndex "notifications_type_entity_id_entity_type_receiver" to table "Notifications"
*
**/

var info = {
'revision': 29,
'name': 'add-index-unique-notifications',
'created': '2024-07-11T11:41:47.319Z',
'comment': ''
};

var migrationCommands = function (transaction) {
return [];
};
var rollbackCommands = function (transaction) {
return [{
fn: 'removeIndex',
params: [
'Notifications',
'notifications_type_entity_id_entity_type_receiver',
{
transaction: transaction
}
]
},
];
};

module.exports = {
pos: 0,
useTransaction: true,
execute: function (queryInterface, Sequelize, _commands) {
var index = this.pos;

function run(transaction) {
const commands = _commands(transaction);
return new Promise(function (resolve, reject) {
function next() {
if (index < commands.length) {
let command = commands[index];
console.log('[#' + index + '] execute: ' + command.fn);
index++;
queryInterface[command.fn].apply(queryInterface, command.params)
.then(next, reject);
} else {
resolve();
}
}

next();
});
}

if (this.useTransaction) {
return queryInterface.sequelize.transaction(run);
} else {
return run(null);
}
},
up: async function (queryInterface, Sequelize) {
const transaction = await queryInterface.sequelize.transaction();
// DROP ALL NOTIFICATIONS THAT WOULD HINDER THE INDEX
await queryInterface.sequelize.query('DELETE FROM "Notifications"\n' +
'WHERE "id" IN (\n' +
' SELECT "id"\n' +
' FROM (\n' +
' SELECT \n' +
' "id",\n' +
' ROW_NUMBER() OVER (\n' +
' PARTITION BY "type", "entityId", "entityType", "receiver"\n' +
' ORDER BY "id"\n' +
' ) AS row_num\n' +
' FROM "Notifications"\n' +
' WHERE "sourceType" IS NULL AND "sourceId" IS NULL\n' +
' ) sub\n' +
' WHERE sub.row_num > 1\n' +
');', { transaction });
// CREATE INDEX MANUALLY BECAUSE SEQUELIZE HAS ISSUES WITH WHERE IS NULL
await queryInterface.sequelize.query('CREATE UNIQUE INDEX "notifications_type_entity_id_entity_type_receiver" ON "Notifications" ("type", "entityId", "entityType", "receiver") WHERE "sourceType" IS NULL AND "sourceId" IS NULL;', { transaction });
await transaction.commit();
return this.execute(queryInterface, Sequelize, migrationCommands);
},
down: function (queryInterface, Sequelize) {
return this.execute(queryInterface, Sequelize, rollbackCommands);
},
info: info
};
22 changes: 21 additions & 1 deletion migrations/_current.json
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,26 @@
"indicesType": "UNIQUE",
"type": "UNIQUE"
}
},
"fe94400734466dc2b18423d6187d2e9aa5a1a396": {
"unique": true,
"fields": [
"type",
"entityId",
"entityType",
"receiver"
],
"where": {
"sourceType": null,
"sourceId": null
},
"name": "notifications_type_entity_id_entity_type_receiver",
"options": {
"indexName": "notifications_type_entity_id_entity_type_receiver",
"name": "notifications_type_entity_id_entity_type_receiver",
"indicesType": "UNIQUE",
"type": "UNIQUE"
}
}
}
},
Expand Down Expand Up @@ -963,5 +983,5 @@
"indexes": []
}
},
"revision": 28
"revision": 29
}
8 changes: 8 additions & 0 deletions modules/notification/models/notification.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ module.exports = (sequelize, DataTypes) => sequelize.define('Notification', {
unique: true,
fields: ['type', 'entityId', 'entityType', 'receiver', 'sourceType', 'sourceId'],
},
{
unique: true,
fields: ['type', 'entityId', 'entityType', 'receiver'],
where: { // seems not to be applied in the generated SQL query
sourceType: null,
sourceId: null,
},
},
],
timestamps: true,
});
10 changes: 9 additions & 1 deletion modules/notification/tests/notification.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ describe('Notifications', () => {
type: NOTIFICATION_TYPES.COMMENT_ON_COMMENT,
};

const testData2 = {
receiver: publicKey,
entityId: 1,
sender: 'ak_sender',
entityType: ENTITY_TYPES.COMMENT,
type: NOTIFICATION_TYPES.COMMENT_ON_COMMENT,
};

const seedDB = getDBSeedFunction([Retip, Notification, Comment]);

after(() => {
Expand Down Expand Up @@ -305,7 +313,7 @@ describe('Notifications', () => {
truncate: true,
});
createdNotification = await Notification.create(testData);
createdNotification2 = await Notification.create(testData);
createdNotification2 = await Notification.create(testData2);
});

it('it should MODIFY a single notification for a user', async () => {
Expand Down