feat(notification): basic functionality and test

This commit is contained in:
Alex Moreno 2022-07-25 08:25:10 +02:00
parent f432d64f56
commit 8048d4ce90
10 changed files with 205 additions and 15 deletions

View File

@ -0,0 +1,46 @@
module.exports = Self => {
Self.remoteMethod('clean', {
description: 'clean notifications from queue',
accessType: 'WRITE',
returns: {
type: 'object',
root: true
},
http: {
path: `/clean`,
verb: 'POST'
}
});
Self.clean = async options => {
const models = Self.app.models;
const status = ['sent', 'error'];
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const config = await models.NotificationConfig.findOne({}, myOptions);
const cleanDate = new Date();
cleanDate.setDate(cleanDate.getDate() - config.cleanDays);
await models.NotificationQueue.destroyAll({
where: {status: {inq: status}},
created: {lt: cleanDate}
}, myOptions);
if (tx) await tx.commit();
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,7 +1,9 @@
const axios = require('axios');
module.exports = Self => {
Self.remoteMethod('send', {
description: 'Send notifications from queue',
accessType: 'READ',
accessType: 'WRITE',
returns: {
type: 'object',
root: true
@ -12,24 +14,69 @@ module.exports = Self => {
}
});
Self.send = async() => {
Self.send = async options => {
// const headers = ctx.req.headers;
// const origin = headers.origin || 'http://' + headers.host;
// const auth = ctx.req.accessToken;
// console.log(origin);
const models = Self.app.models;
const status = 'pending';
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const notificationQueue = await Self.app.models.NotificationQueue.find({
where: {code: status},
include: [{
relation: 'notificationSubscription'
}]
const notificationQueue = await models.NotificationQueue.find({
where: {status: status},
include: [
{
relation: 'notification',
scope: {
include: {
relation: 'subscription',
scope: {
include: {
relation: 'user',
scope: {
fields: ['name']
}
}
}
}
}
}
]
}, myOptions);
console.log(notificationQueue);
const statusSent = 'sent';
const statusError = 'error';
for (const queue of notificationQueue) {
// console.log(queue);
// console.log(origin);
// console.log(auth);
// console.log(queue.notification().name);
// console.log(queue.params);
// const queueParams = Object.assign({}, JSON.parse(queue.params));
// queueParams.authorization = auth.id;
try {
// await print axios.get(`print`, queueParams)
await queue.updateAttribute('status', statusSent);
} catch (error) {
await queue.updateAttribute('status', statusError);
}
}
return notificationQueue;
};
};

View File

@ -0,0 +1,42 @@
const models = require('vn-loopback/server/server').models;
fdescribe('Notification Clean()', () => {
it('should delete old rows with error', async() => {
const userId = 9;
const status = 'error';
const tx = await models.NotificationQueue.beginTransaction({});
const options = {transaction: tx};
const notification = await models.Notification.findOne({}, options);
const notificationConfig = await models.NotificationConfig.findOne({});
const cleanDate = new Date();
cleanDate.setDate(cleanDate.getDate() - (notificationConfig.cleanDays + 1));
let before;
let after;
try {
const notificationDelete = await models.NotificationQueue.create({
notificationFk: notification.name,
authorFk: userId,
status: status,
created: cleanDate
}, options);
before = await models.NotificationQueue.findById(notificationDelete.id, null, options);
await models.Notification.clean(options);
after = await models.NotificationQueue.findById(notificationDelete.id, null, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(before.notificationFk).toEqual(notification.name);
expect(after).toBe(null);
});
});

View File

@ -0,0 +1,33 @@
const models = require('vn-loopback/server/server').models;
fdescribe('Notification Send()', () => {
it('should send notification', async() => {
const statusPending = 'pending';
const tx = await models.NotificationQueue.beginTransaction({});
const options = {transaction: tx};
const filter = {
where: {
status: statusPending
}
};
let before;
let after;
try {
before = await models.NotificationQueue.find(filter, options);
await models.Notification.send(options);
after = await models.NotificationQueue.find(filter, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(before.length).toEqual(1);
expect(after.length).toEqual(0);
});
});

View File

@ -1,3 +1,4 @@
module.exports = Self => {
require('../methods/notification/send')(Self);
require('../methods/notification/clean')(Self);
};

View File

@ -13,10 +13,18 @@
"description": "Identifier"
},
"name": {
"type": "string"
"type": "string",
"required": true
},
"description": {
"type": "string"
}
},
"relations": {
"subscription": {
"type": "hasMany",
"model": "NotificationSubscription",
"foreignKey": "notificationFk"
}
}
}

View File

@ -26,11 +26,12 @@
"notification": {
"type": "belongsTo",
"model": "Notification",
"foreignKey": "notificationFk"
"foreignKey": "notificationFk",
"primaryKey": "name"
},
"author": {
"type": "belongsTo",
"model": "User",
"model": "Account",
"foreignKey": "authorFk"
}
}

View File

@ -6,6 +6,18 @@
"table": "util.notificationSubscription"
}
},
"properties": {
"notificationFk": {
"type": "number",
"id": true,
"description": "Identifier"
},
"userFk": {
"type": "number",
"id": true,
"description": "Identifier"
}
},
"relations": {
"notification": {
"type": "belongsTo",
@ -14,7 +26,7 @@
},
"user": {
"type": "belongsTo",
"model": "User",
"model": "Account",
"foreignKey": "userFk"
}
}

View File

@ -1,3 +1,3 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Notification', '*', 'READ', 'ALLOW', 'ROLE', 'developer');
('Notification', '*', 'WRITE', 'ALLOW', 'ROLE', 'developer');

View File

@ -2617,7 +2617,7 @@ INSERT INTO `util`.`notificationConfig`
INSERT INTO `util`.`notification` (`id`, `name`, `description`)
VALUES
(1, 'notification one', 'notification fixture one');
(1, 'invoice', 'notification fixture one');
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
VALUES
@ -2625,7 +2625,7 @@ INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
INSERT INTO `util`.`notificationQueue` (`id`, `notificationFk`, `params`, `authorFk`, `status`, `created`)
VALUES
(1, 'notification one', 'randomParams', 9, 'pending', util.VN_CURDATE());
(1, 'invoice', '{"invoiceId": 1}', 9, 'pending', util.VN_CURDATE());
INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`)
VALUES