Подтвердить что ты не робот

Совместное использование транзакций STM и базы данных

Я использую библиотеку Haskell STM, и мне очень нравится возможность составлять транзакции и общий характер STM-типа "вы не можете получить-это-неправильный".

По уважительной причине, STM не разрешает действия IO внутри транзакции. Невозможно повторить действие ввода-вывода. (вставьте ссылку "Запустить ракеты" здесь). С другой стороны, транзакции с базами данных имеют некоторые гарантии атомарности, которые очень похожи. Есть ли принятый способ использовать их вместе?

4b9b3361

Ответ 1

Перемешивание различных видов транзакций в одно понятие транзакции называется "транзакционным повышением", и в настоящий момент в Haskell STM нет отличного способа сделать это. Тем не менее, существует способ создания действий, которые должны выполняться только для фиксации или только для повторной попытки: http://hackage.haskell.org/package/stm-io-hooks

Кроме того, вы можете попробовать проект twilight-stm, который обеспечивает явное "сумерки" между завершающими транзакциями и фактическим фиксацией. Насколько мне известно, предоставленный код скорее представляет собой ссылочную реализацию, чем настройку для производительности: http://proglang.informatik.uni-freiburg.de/projects/twilight/

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

Ответ 2

Некоторая общая помощь от тех, кто не имел дело с базами данных:

Вы можете технически использовать unsafeIOToSTM, поэтому, если вам гарантируется атомарность действием IO, которое изменяет базу данных, все должно быть хорошо. Просто напишите мост, который использует unsafeIOToSTM, а затем используйте этот мост в вашем коде, чтобы избежать использования вашего кода с небезопасными вещами.

Вы также можете использовать STM (IO a), но это не всегда соответствует вашей цели, например

do r <- atomically $ do ...
   r' <- r

или

do r <- join . atomically $ do ...

Где вы возвращаете запрос базы данных для выполнения из STM. Это безопасно, но гораздо более ограничено тем, что вы делаете с mVar и не может быть изменено из-за действия IO, которое вы возвращаете (что хорошо для безопасности, поскольку оно сохраняет атомарность)