В цикле коммита ShareJS существует 4 хука. Реализацию двух из них (submit и after submit) вы можете посмотреть в коде ShareJS. А двух остальных (preValidate и validate) в коде LiveDB.
Последовательность вызова хуков такова:
- ShareJS запускает submit middleware, которая имеет доступ к операции, имени коллекции, имени документа (_id для MongoDB) и connect-сессии. Эта middleware запускается асинхронно при первоначальной обработке операции, до попытки её применения. Таким образом, в ней вы можете асинхронно получить данные необходимые для контроля доступа или манипулировать операцией.
- LiveDB вызывает метод preValidate. Он получает всё доступное в submit middleware, а так же документ до выполнения операции. Этот метод вызывается синхронно в процессе коммита операции и может быть вызван многократно.
- LiveDB запускает метод validate. Он работает так же, как предыдущий, только вызывается после после произведения операции с документом.
- ShareJS запускает after submit middleware, которая получает те же данные что и submit, и так же документ после произведения операции. Это запускается асинхронно, сразу после сохранения операции и публикации её для подписчиков.
Мы потратили много времени на обсуждение деталей этих хуков и мы намеренно оставили их достаточно низкоуровневыми в рамках ShareJS/LiveDB.
Методы LiveDB намеренно сделаны синхронными. Эти методы могут быть вызваны много раз в процессе валидации, поскольку если два разных клиента одновременно изменяют один и тот же документ, выигрывает клиент сабмитящий первым и последующие попытки отклоняются до завершения операции. Добавление асинхронных вызовов для получения дополнительных данных здесь было бы неэффективным учитывая, что методы могут вызываться многократно. In addition, async calls could cause resource starvation where some servers with a slower running task could consistently lose to servers with faster tasks many times in a row. Cинхронные вызовы существенно снижают вероятность этого.
Валидация в LiveDB разделена на два метода, чтобы избежать постоянного, зачастую ненужного клонирования документа. Если вы хотите иметь единственный вызов валидации с вариантами документа до и после после операции, вы можете глубоко клонировать документ в preValidate и затем использовать его и изменённую версию в validate.
Правильный метод получения дополнительных данных для контроля доступа — использование Express middleware или ShareJS submit middleware, и добавление их сессию, которая передаётся в preValidate / validate.
Текущая реализация немного запутана и в идеале racer-access должен иметь более интуитивный API и документацию. Я рад предложениям по улучшению racer-access, но не думаю, что имеет смысл что-то менять в LiveDB.
Автор: Imbolc