Как добавить в домен node.js глобальный излучатель?

В моем приложении node.js я использовал для обработки ошибок по доменам. Архитектура приложения выглядит так:

  1. Контроллеры. Методы экспресс-вызовов вызовов контроллеров

  2. Контроллеры вызывают сервисы и используют модели

  3. Услуги звонить в репозитории

(На самом деле это очень похоже на DDD).

Итак, контроллеры создают домен и запускают его фактическое тело в домене. Службы обычно генерируют исключения, если что-то идет не так. Также контроллеры прослушивают ошибки домена и обрабатывают их. Это очень удобно, потому что мне не нужно беспокоиться об ошибке при вызове стека методов всех сервисов - я просто выбрасываю исключение и могу быть уверен, что он будет пойман в контроллере.

Но я столкнулся с проблемой, связанной с использованием PostgreSQL. Я использую модуль node-postgres и создаю pg.Client в отдельном js-файле, поэтому pg.Client похож на общий доступ для всех (в противном случае создание pg.Client для каждого запроса открывает множество активных соединений с postgres).

Проблема в том, что когда pg.Client определен в отдельном файле, он похож на глобальный объект и не входит в область видимости домена, созданную в контроллерах. Таким образом, исключения, сгенерированные из обратных вызовов pg.Client, не перехватываются доменом.

Я покажу упрощенный способ обработки запросов, чтобы было понятно. Допустим, пользователь хочет получить логин по userId:

  1. Где-то в начале pg.Client создал

  2. Получить запрос приходит на экспресс, экспресс-метод маршрутизации вызовов

  3. Маршрутизация вызывает некоторые методы контроллера

  4. Контроллер создает домен и вызывает в "domain.run" услугу

  5. Служба вызывает хранилище

  6. Репозиторий принимает pg.Client, созданный ранее, и вызывает метод SQL-запроса.

  7. Результат метода запроса SQL помещает в обратный вызов (так что этот обратный вызов вызывается pg.Client)

  8. И затем обратный вызов обрабатывается в сервисе, где мы проверяем, что мы получаем нулевое значение вместо пользовательской модели (потому что такого пользователя нет в db для данного userId) и генерируем исключение

Так что это исключение не перехватывается в домене. Технически, нам нужно использовать метод "add" для домена узла и добавить pg.Client, но, как я сказал, pg.Client является общим, поэтому он будет добавлен в разные параллельные домены.

Я приведу пример кода, чтобы сделать его более понятным. Это упрощенный метод UserService:

 login: function (email) {

                    var userRepository = new UserRepository();
                    userRepository.findByEmail(email, function (model) {
                        if (model == null)
                           throw new Error('No such user');
                    });

            }

Итак, этот метод "login" вызывается в домене. Но он создал userRepository, вызывает метод findByEmail, который будет использовать общий pg.Client вне области домена, и поэтому исключение не будет поймано в домене.

Есть идеи, как это исправить и поставить pg.Client в домен?

1 ответ

Решение

Я решил проблему. Я создаю EventEmitter в области активного домена и слушаю, скажем, событие "onCallback". При обратном вызове метода запроса (который не связан с доменом, поскольку pg.Client является своего рода глобальным и располагается вне домена), я генерирую "onCallback" из EventEmitter.

Другие вопросы по тегам