Несколько лет назад я использовал RavenDB, и это был хороший опыт — с тех пор он только рос как на дрожжах. Раньше я много использовал MongoDB, мне надоел «опыт SQL», и мне нужно было что-то получше для ООП. Но теперь я FP и DDD, SQL не поможет, а Mongo раздражает меня.

Начало работы с RavenDB

Перво-наперво, нам нужна локальная среда

docker run --rm -d -p 9010:8080 -p 38888:38888 --name ravendb -e RAVEN_Setup_Mode=None -e RAVEN_License_Eula_Accepted=true -e RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork ravendb/ravendb

Там есть несколько переменных среды, и они необходимы. RAVEN_Setup_Mode=None Это выбирает безопасность во время установки, по сути, просит RavenDB запуститься без процесса настройки — удалите, и вам придется проходить через мастер настройки каждый раз, когда вы создаете контейнер, болезненно для автоматизации. "Больше информации…"

RAVEN_License_Eula_Accepted=true Опять же, еще один процесс настройки. RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork Это связано с тем, что по умолчанию включена проверка подлинности TLS и сертификата, что делает сервер доступным без проверки подлинности. "Больше информации…"

Подключение к RavenDB

Есть пример C#, который я придумал:

Я использую классы и интерфейсы, потому что DI по-прежнему прост, и я перехожу к F# — не нужно возиться с монадами и влезать в ад множественных монад.

.AddSingleton<IRavenClientFactory, RavenClientFactory>(fun sp ->
  let configurationSection = config.GetSection("Raven")
  let url = configurationSection.GetValue("Url")
  let dbName = configurationSection.GetValue("Database")
  new RavenClientFactory([ url ], dbName)
)

Чтение из RavenDB

Я создал простую оболочку для чтения и записи. Не более чем просто справиться с дополнительными ортогональными проблемами, которые появятся позже.

Не беспокойтесь о ErrorResponse<'t>, это просто размеченный союз, который позволяет мне превращать исключения и другие события в полезную информацию для понимания на границе API. Таким образом, если это временная ошибка, я могу вернуть 500 и попросить клиента повторить попытку или что-то в этом роде…

В этом нет ничего сверхъестественного, просто довольно стандартные вещи.

Интересное время

Итак, давайте углубимся в некоторые более интересные аспекты.

  1. Я хочу автоматическое создание базы данных
  2. Бесшовная интеграция с объектами домена и объектами значений

Автоматическое создание базы данных

Почему? Во время локальной разработки я переключаюсь между компьютерами, иногда я использую свой «большой» компьютер — он же Tower PC — иногда мне нравится сидеть и смотреть телевизор во время кодирования — как я делаю сейчас, пока пишу этот блог. Каждый раз я хочу, чтобы моя база данных и другие ресурсы моих API/веб-сайтов могли автоматически генерировать исходные данные и т. д.

Оказывается, в RavenDB создание новой базы данных немного громоздко. В отличие от SQL или Mongo, где простой запуск запроса либо создаст базу данных, либо автоматически сгенерирует коллекцию, RavenDB требует взаимодействия с Maintenance API. По этой ссылке вы увидите пример C#, давайте сделаем его забавным.

Здесь вы увидите Retries, небольшую обертку вокруг Полли, которую я написал.

Это начинается с checkForDatabase, который возвращает Result<unit, unit>, по сути, если он возвращает Error (), нам нужно создать базу данных.

Затем мы createIfNotExists -> tryCreateDatabase . tryCreateDatabase пожары CreateDatabaseOperation . Если это вызывает исключение ConcurrencyException, мы можем его игнорировать, потому что оно уже создается где-то еще. Если исключение RavenException, то, вероятно, это связано с тем, что сервер еще не готов, и его просто нужно повторить, пока он не завершится успешно. Он никогда не терпел неудачу в 20 повторных попытках, так что это кажется разумным.

env — это IWebHostEnvironment, чтобы я мог проверить, находимся ли мы в режиме разработки. Сделано так себе ravenClientFactory.InitialiseDatabase env .

Так вот, в значительной степени dunzo'd ...

Полная интеграция с DDD

Что ж, придется подождать до следующего раза... :D