2009-02-24 4 views
9

Я должен отправить электронное письмо, написать в файл и позвонить в веб-службу. Чтобы поддерживать согласованность, все шаги должны выполняться. Если какой-либо шаг выдает исключение или ошибки, все шаги должны быть отменены.Шаблоны для реализации транзакций за пределами базы данных

Прежде чем я переведу свой собственный объект ACID engine, существуют ли общепринятые шаблоны для реализации семантики ACID на уровне объекта?

Еще лучше, существуют ли какие-либо существующие библиотеки, которые я могу использовать для платформы .NET?

Редактировать: Я знаю, что отправка электронной почты не может быть отменена, но неспособность подключиться к SMTP-серверу является причиной для уничтожения всей транзакции. Кроме того, я бы хотел, чтобы это было доступно для использования с будущими действиями.

+0

Как вы откатываете электронное письмо? – mbeckish

+0

возможно отправка отзыва :) –

+0

Отказ будет работать. Теоретически я мог вырвать его из сервера Exchange, как будто этого не произошло, но это может стать подозрительным. –

ответ

5

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

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

К сожалению, я не помню больше этого.

CSLA.NET реализует аналогичный стек отскока. Это единственный пример с кодом, который я могу придумать с головы.

3

Windows Workflow Foundation имеет концепцию compensation (с использованием Composite activity), когда семантика ACID может быть нецелесообразна. Конечно, у нее также есть поддержка транзакций ACID.

Хороший вопрос: зачем беспокоиться компенсация? Разве не одна большая ACID сделка с автоматическим откатом так же хорошо? Операция ACID равна наиболее подходящей, когда происходят операции в той же базе данных или в пределах той же информационной системы. Также наиболее подходит, когда операции заканчиваются быстро. Когда задействуются различные компании и , определение процесса с точки зрения семантики ACID часто является сложной задачей. Чтобы это было изолированное и долговечное, вы должны держать все ресурсы различных компаний заблокирован на время выполнения задания. Это часто неразумно, особенно, если задача длинная. Для этого быть последовательным и атомным, вам нужен специальный код компенсации.

1

Поскольку вы не можете отменить отправить по электронной почте, и это относительно недорогой, чтобы написать файл, я просто хотел бы сделать эти вещи в правильном порядке:

  1. Попробуйте записать файл/напишите файл. Если неуспешно, остановитесь, в противном случае продолжайте:
  2. Позвоните в веб-службу.Если это не удастся, удалите файл и остановите его, в противном случае продолжайте:
  3. Отправляйте e-mail - электронная почта является асинхронной, так что вы никогда не знали бы, было ли это отправлено или нет, поскольку большинство почтовых серверов настроено на повторную попытку в течение пары дней, если возникла ошибка, и вы никогда не получите подтверждение, что электронная почта прошла, даже если она была успешной.
+0

У вас могут быть проблемы, если веб-служба получает и обрабатывает вызов, но ответ теряется. Я столкнулся с этим с вызовом AddItem eBay, который имеет необратимый побочный эффект от стоимости денег. –

+0

В мире сетей, никогда не получая ACK, это то же самое, что и NACK, не так ли? Когда это происходит, часто требуется ручное вмешательство и неизбежно. –

3

Простейший метод, не полагающийся в значительной степени на внешнюю библиотеку, - prevalence. Периодически контрольная точка с использованием сериализации для получения моментального снимка вашего состояния, а затем вести журнал путем сериализации достаточной информации о каждой побочной операции с вашими данными, чтобы повторить ее позже. Если что-то взорвалось, перезагрузите самую последнюю контрольную точку, а затем повторно примените все записи журнала, записанные после этой точки.

Для чего-то более сложного, попробуйте software transactional memory. Это может быть несколько неуклюже для реализации на современных языках, но достаточно мощным и может также дать вам некоторые дополнительные методы параллелизма.

Для необратимых операций, таких как доступ к веб-службе или отправка электронной почты, вам необходимо использовать compensating transactions: сделать другой вызов веб-службы, чтобы отменить или обновить результаты предыдущего, или, возможно, отправить другое письмо, в котором сообщается получателю, что все пошло не так, как предполагалось.

0

Две мысли:

  • Как Jeffrey Hantin упоминает, software transactional memory (СТМ) является довольно сладким. Посмотрите, как это реализовано/использовано в Clojure; Богатые Хикки videos впечатляют.
  • Одним из важных аспектовславы GoF является «неуязвимость». реализация этого может сводиться к простому (но тем не менее полезное) предложение по Robert C. Barth
1

Одна идея заключается в использовании JMS как «двигатель», и вы можете использовать JMS транзакции (которые могут вступать в существующие операции, например, DB). Это начинает приводить к асинхронной архитектуре, управляемой событиями, что, вероятно, хорошо, если мы не говорим о простых приложениях - в этом случае вам, вероятно, не нужно задавать вопрос.

Примером этого может быть создание простой учетной записи. Для этого вы хотите сохранить данные учетной записи в БД, а также отправить пользователю электронное письмо для активации - но вы хотите, чтобы они были в одной транзакции по понятным причинам.

Вы не должны указывать код отправки электронной почты в транзакции, потому что, даже если вы можете отправить транзакцию транзакции по электронной почте - db, может произойти по той или иной причине. Вы также не должны отправлять электронную почту за пределы транзакции (после фиксации), потому что отправка электронной почты может привести к сбою, ведущему к сиротской учетной записи.

Чтобы использовать JMS в этом сценарии - поставьте JMS-код отправки в транзакции БД и присоедините его к этой транзакции. Вам гарантирована доставка сообщений. На другом конце есть что-то, потребляющее очередь отправки электронных писем. В случае сбоя отправки по электронной почте лучшим вариантом является регистрация/повышение оповещения - JMS откатится и вернет сообщение в очередь для последующего потребления. т. е. попытаться повторно отправить электронную почту, как только вы, надеюсь, исправите проблему.

Критическая вещь - запись в формате DB согласована, и в конечном итоге электронная почта отправляется.

0

Также был выпущен экспериментальный проект STM .NET. Эти проекты добавляют транзакционную память к C#. Фактически это изменяет CLR, чтобы поддержать это.

Смежные вопросы