← Blog of oldlisper

Изменения в mongo-cl-driver

· 24.03.2013 00:00
· original author: archimag

Изменения в mongo-cl-driver

После длительного перерыва снова взялся за mongo-cl-driver и основательно его переделал.

Адаптеры

Для начала выкинул iolib. При чём, не могу сказать о ней ничего плохого, но... Во-первых, до сих пор я использовал mongo-cl-driver только в блокирующем режиме, мои надежды на то, что iolib откроет двери в мир асинхронного программирования не оправдываются - просто никто ничего такого не пишет, никакого веб-сервера и т.п. на iolib до сих пор не появилось. А между тем, Andrew Lyon активно пилит платформу на базе libevent: cl-libevent2, cl-async, drakma-async и даже асинхронный веб-сервер wookie (это при том, что кое-какой веб-сервер есть в самой libevent). Кстати, libevent отлично работает на винде.

В итоге, под впечатлением от pika добавил в mongo-cl-driver поддержку адаптеров и сейчас есть два работающих адаптера: на базе usocket и cl-async. Вернуть адаптер для iolib несложно, но пока не понятно что с ним вообще делать то.

Futures

Долго не мог решить, как же совместить в одной библиотеке синхронный и асинхронный интерфейс. Идти по пути node.js, где каждая функция представлена в двух вариантах (например, fs.readFile и fs.readFileSync) мне не хотелось. Как сделано в pika (каждый адаптер предоставляет свой набор классов) мне тоже не нравится. В итоге остановился на использовании futures : никакого разделения API на синхронный и асинхронный нет, но при использовании асинхронного адаптера возвращается не результат, а future. Сейчас мне кажется, что это очень удачный вариант, за одним но... Я пока не придумал, как нормально организовать обработку ошибок в таком варианте. cl-async-future (по моей просьбе автор выделил её в отдельную библиотеку) предоставляет API и набор макросов. Эти макросы работают просто замечательно если ошибок нет. А вот когда есть ошибки, случается что-то мутное. Пока план в том, что бы взять API и реализовать на его основе аналог Step, но этого я ещё не сделал. Собственно, поэтому пользоваться cl-async адаптером пока не стоит, но можно с ним экспериментировать.

MongoClient

Другим направлением работы было приведение драйвера в соответствии с официальными рекомендациями. В первую очередь, добавлен класс mongo:mongo-client, при создании которого указывается параметры сервера (класс mongo:server-config) и уровень Write Concern (класс mongo:write-concern).

Адаптеры наследуют от mongo:mongo-client и поэтому для создания клиента следует использовать функцию mongo:create-mongo-client:

  1. (mongo:with-client (client (mongo:create-mongo-client :usocket
  2.                                                       :server config
  3.                                                       :write-concern w))
  4.   (print (mongo:$count (mongo:collection (make-instance 'mongo:database
  5.                                                         :client client
  6.                                                         :name "blog"))
  7.                                          "posts"))))

Для упрощения задания Write Concern предопределены следующие константы:

  • mongo:+write-concern-normal+

  • mongo:+write-concern-fsync+

  • mongo:+write-concern-replicas+

  • mongo:+write-concern-journal+

  • mongo:+write-concern-fast+

  • mongo:+write-concern-crazy+

Другие изменения

У функций

  • mongo:update-op

  • mongo:insert-op

  • mongo:delete-op

опциональный параметры превращены в keys для того, что бы добавить key-параметр :write-concern.

Функция mongo:collection-count переименована в mongo:$count. Плюс добавленная функция mongo:$distinct, очень удобная, например, все тэги в этом блоге с её помощью я получаю так:

  1. (mongo:$distinct posts "tags")

Добавил функцию mongo:eval-js:

  1. (mongo:with-client (client (mongo:create-mongo-client :usocket))
  2.   (mongo:eval-js (make-instance 'mongo:database :mongo-client client :name "test")
  3.                  "function (x, y) { return x * y; }"
  4.                  :args #(2 3)))
  5. 6.0d0

Ну и ещё наверное есть пара небольших изменений, о которых сейчас не помню.