Вложенные транзакции в StatefulService для сохранения асинхронного состояния прерванной транзакции
У меня есть ReliableQueue<MyTask>
который помещен в другую область, и я убираю задачи из транзакции, а затем хочу выполнить некоторые долгосрочные вычисления для каждой задачи.
Проблема в том, что в случае прерывания моей транзакции в очереди я не хочу потерять экземпляр длинного вычисления. Он будет работать в фоновом режиме, независимо, и я просто хочу проверить, завершено ли оно, или еще раз, когда я попытаюсь обработать задачи.
Сегмент кода:
public void protected override async Task RunAsync(CancellationToken cancellationToken)
{
var queue = await StateManager.GetOrAddAsync<IReliableQueue<MyTask>>(...);
while(!cancellationToken.IsCancellationRequested)
{
using (var transaction = ...)
{
var myTaskConditional = await queue.TryDequeueAsync(transaction);
if (!myTaskConditional.HasValue)
{
break;
}
await DoLongProcessing(myTaskConditional)
await transaction.CommitAsync();
}
}
}
private async void DoLongProcessing(MyTask myTask) {
var dict = await StateManager.GetOrAddAsync<IReliableDictionary<Guid,Guid>>(...);
Conditional<Guid> guidConditional;
using (var transaction = ...)
{
guidConditional = await dict.TryGetValueAsync(myTask.TaskGuid);
if (guidConditional.HasValue) {
await transaction.CommitAsync();
// continue handling knowing we already started, continue to wait for
await WaitForClaulcationFinish(guidConditional.Value);
}
else {
// start handling knowing we never handled this task, create new guid and store it in dict
var runGuid = await StartRunningCalculation(runGuid);
await dict.AddAsync(myTask.TaskGuid, runGuid);
await transaction.CommitAsync();
await WaitForClaulcationFinish(runGuid);
}
}
}
Моя проблема: я использую вложенные транзакции, и это не рекомендуется.
Есть ли здесь риск тупика, если я использую транзакции исключительно для ReliableQueue
или же ReliableDictionary
по отдельности?
Есть ли лучший замысел для того, чего я пытаюсь достичь?
1 ответ
Вы не должны делать ничего, что долго выполняется внутри транзакции. Посмотрите на службу очередей с приоритетами, которую я опубликовал. Извлеките элемент из очереди, поместите его в коллекции во время выполнения работы, затем, когда закончите, поместите его обратно в очередь или завершите работу.