Мне нужно создать JSON RPC API, который должен управлять базой данных Postgre.Мое приложение состоит из сервера и базы данных с репозиториями.
Методы, которые предоставляются, являются следствием свойства «Methods» каждого репо.
Моя проблема в том, что (я думаю) яЯ не использовал хорошую архитектуру, потому что у меня есть круговой объект в каждом репо: в каждом репо свойство 'db' включает все репо (включая его самого).Например: DevicesRepository.db = - все функции pg-обещания - все остальные репозитории (RolesRepository, ShellsRepository ...) - DevicesRepository (DevicesRepository) Это проблема?Я думаю, это означает, что у меня плохая архитектура?
У меня также есть проблема с 'this' в репо, я открою другой вопрос, если это не та же проблема
Какмой API работает:
- . / server / server.js получить методы из ./db/index.js
- . / db / index.js 'regroup' все repo.methodsв одном объекте с «Object.assign ()»
- в каждом репо я должен связать «this» (пример = DevicesRepository), иначе методы (здесь «add») не знают, что это this.db)
- потому что я связываю контекст с методом this.db, но в вызове tx контекст this.db, поэтому я больше не могу использовать this.Collections
. / Db / repos / devices.js
'use strict';
class DevicesRepository {
constructor(db, pgp) {
this.db = db;
this.pgp = pgp;
this.Collections = createColumnsets(pgp);
this.methods = {
'devices.insert': this.add.bind(this),
}
}
async add(params) {
console.log(this); //here this = DevicesRepository
var device = params.data.device;
return this.db.tx(function* (transaction) {
console.log(this); // here this = transaction = DevicesRepository.db
const system = yield transaction.systems.add(params);
device.systemid = system.systemId;
const query = this.pgp.helpers.insert(device, this.Collections.insert); // this.pgp = undefined
if(params.return) query += " RETURNING *";
return transaction.one(query);
})
.then(data => {
// hidden
})
.catch(ex => {
// hidden
});
}
}
/* hidden for brevity */
module.exports = DevicesRepository;
. / Db / repos / index.js
'use strict';
module.exports = {
// other repo are required with the same way
Devices: require('./devices'),
};
. / Db / index.js
'use strict';
const repos = require('./repos'); // ./repos/index.js
const conf = require('./conf');
// pg-promise initialization options:
const initOptions = {
//promiseLib: promise, // Use a custom promise library, instead of the default ES6 Promise:
extend(obj, dc) {
// other repo are added with the same way
obj.devices = new repos.Devices(obj, pgp);
}
};
const pgp = require('pg-promise')(initOptions);
const db = pgp(config);
const methods = Object.assign({},
db.roles.methods,
db.shells.methods,
db.systems.methods,
db.devices.methods,
);
module.exports = {
methods,
}
. / Server / server.js
const http = require('http');
const Database = require('../db'); // ./db/index.js
const path = '/api/v1', port = 9000;
const methods = Database.methods;
const requestHandler = (req, res) => {
//some lines are hidden for brevity
const body = [];
req.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
const bodyStr = Buffer.concat(body).toString();
// parse body en JSON
let request = JSON.parse(bodyStr);
requestProcessor(request).then((response) => {
sendResponse(res, response);
});
});
}
async function requestProcessor(request) {
//some lines are hidden for brevity
let response = { /* some properties */ };
try {
response.result = await Promise.resolve(methods[request.method](request.params)); // call the repo method
} catch (err) {
// hidden
}
return response;
}
const server = http.createServer(requestHandler);
server.listen(port, (err) => {
if(err) {
return Log('something bad happened', err);
}
Log(`server is listening on ${port}`);
};