Как использовать другие репо в транзакциях - PullRequest
1 голос
/ 05 июля 2019

У меня есть несколько репозиториев с методами, и некоторые из этих методов используют транзакцию (.tx).Например, в моем DevicesRepository ниже, метод 'add' должен вставить новое устройство, что означает: 1. Вставить систему и вернуть идентификатор (SystemsRepository) 2. Вставить устройство с возвращающим systemId и получить новый идентификатор 3Вставьте другие части (другие репо), которые используют ID устройства

Моя проблема заключается в том, что в этой транзакции я не знаю, как получить доступ к другим методам репо.Я мог бы использовать другие репозитории из моего объекта Database (Database.systems.add, Database.OtherRepo.add, [...]), но если я сделаю это

tx doc

При вызове корневого объекта базы данных метод выделяет соединение из пула, выполняет обратный вызов и после завершения освобождает соединение обратно в пул.Однако при вызове внутри другой задачи или транзакции метод повторно использует родительское соединение.

task doc

При выполнении более одного запроса ввремя следует выделять и освобождать соединение только один раз, одновременно выполняя все необходимые запросы в одном сеансе соединения.Что еще более важно, транзакция может работать только в пределах одного соединения.

Спасибо!:)

PS: могу добавить, как я инициализирую БД и репозитории

. / Db / repos / devices.js

'use strict';

var Database = null, pgp = null, Collections = null;

async function add(params) {
  // I can use Database.systems.add
  return Database.tx('Insert-New-Device', async function(transaction) {
    let device = params.data.device;

    const system = await transaction.systems.add(params);
    device.systemid = system.systemId;

    const query = pgp.helpers.insert(device, Collections.insert);
    query += " RETURNING deviceId";
    device.deviceId = await transaction.one(query);

    const OtherRepoInsert = await transaction.otherRepos.add(params);
    device.otherRepos.id = OtherRepoInsert.otherReposId;

    return device
  })
  .then(data => { return data; })
  .catch(ex => { throw new Error(ex); });
}

function createColumnsets() { /* hidden for brevity (almost the same as the pg-promise-demo */ }

const DevicesRepository = {
  add: add
};


module.exports = (db) => {
  Database = db;
  pgp = db.$config.pgp;
  Collections = createColumnsets();

  return DevicesRepository;
}

. / Db / repos / systems.js

'use strict';

var Database = null, pgp = null, Collections = null;

async function add(params) {
  var system = params.data.system;
  system.archid=2;
  system.distributionid=3;

  var query = pgp.helpers.insert(system, Collections.insert);
  if(params.return) query += " RETURNING *";

  return Database.any(query)
                  .then(data => { return data; })
                  .catch(ex => { throw new Error(ex); });
}

function createColumnsets() { /* hidden for brevity (almost the same as the pg-promise-demo */ }

const SystemsRepository = {
  add: add
};

module.exports = (db) => {
  Database = db;
  pgp = db.$config.pgp;
  Collections = createColumnsets();

  return SystemsRepository;
}

Ответы [ 3 ]

0 голосов
/ 05 июля 2019

Я нашел реальную проблему.

Если вы перейдете к моему первому сообщению, вы увидите, что каждое мое репо экспортирует функцию инициализации: 1. который вызывается событием pg-обещание 'extended' 2. который принимает один параметр: контекст 3. который использует этот параметр для инициализации переменной 'pgp' в репозитории с помощью db. $ Config.pgp

Как объяснено в демоверсии , это событие происходит, когда БД загружается впервые в приложение и для каждой задачи и транзакции.

В моем случае: В первый раз, когда происходит событие (полная инициализация приложения), параметром события 'obj' является контекст базы данных (содержащий $ config, $ pool, ...), поэтому он работает Когда событие возникает для задачи или транзакции, параметром события 'obj' является Контекст задачи , где $ config не существует, поэтому событие не может расширить контекст моего репо. Выдается исключение «не может прочитать помощники свойств неопределенного», но оно не появляется и не вызывает сбой моего приложения, я не знаю почему, может быть перехвачено в событии. Вот почему я не мог использовать репо в транзакции.

Я изменил свой код так, как он работает:

. / Дб / index.js

'use strict';
/* hidden for brevity */
// pg-promise initialization options:
const initOptions = {
    promiseLib: promise,
    extend(obj, dc) {
        obj.roles = repos.Roles(obj, pgp);
        obj.shells = repos.Shells(obj, pgp);
        obj.systems = repos.Systems(obj, pgp);
        obj.devices = repos.Devices(obj, pgp);
    }
};

const pgp = require('pg-promise')(initOptions);
const db = pgp(config);

/* hidden for brevity */

. / Дб / index.js

'use strict';
/* hidden for brevity */
// pg-promise initialization options:
const initOptions = {
    promiseLib: promise,
    extend(obj, dc) {
        obj.roles = repos.Roles(obj, pgp);
        obj.shells = repos.Shells(obj, pgp);
        obj.systems = repos.Systems(obj, pgp);
        obj.devices = repos.Devices(obj, pgp);
    }
};

const pgp = require('pg-promise')(initOptions);
const db = pgp(config);

/* hidden for brevity */

. / Дб / репо / {} repoFiles .js

/* hidden for brevity */
module.exports = (db, pgpLib) => {
  Database = db;
  pgp = pgpLib;
  Collections = createColumnsets();

  return DevicesRepository;
}
0 голосов
/ 05 июля 2019

Свойство $ config предназначено для интеграции. Поэтому он существует только на корневом уровне База данных , а не внутри задач или транзакций.

Чтобы использовать пространство имен helpers , вы должны передать pgp в репозитории при их инициализации, как показано в pg-promise-demo :

 extend(obj, dc) {
        obj.users = new repos.Users(obj, pgp);
        obj.products = new repos.Products(obj, pgp);
    }
0 голосов
/ 05 июля 2019

Вы можете установить транзакцию вне вызовов, а затем передать ее этим функциям, чтобы они ее использовали.

Тем не менее, я бы порекомендовал заглянуть в библиотеку построителей запросов более высокого уровня, такую ​​как Knex.js , чтобы избавить вас от некоторых из этих (и будущих) головных болей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...