Доступ к записям, заблокированным другой транзакцией в надежном индексированном словаре Service Fabri c - PullRequest
0 голосов
/ 27 января 2020

В нашем приложении мы используем сервис fabri c индексированные словари для хранения данных. Мы также используем пакет Service Fabri c Queryable для добавления возможностей запросов в наши коллекции.

В нашем случае у нас есть транзакция, в которой мы делаем несколько обновлений и фиксируем все их сразу. Мы также создали индексы для некоторых свойств для более быстрого поиска данных. Благодаря этому индексированию запись создается внутри словарного индекса с индексированным свойством в качестве ключа и объектом в качестве значения. Это также операция AddOrUpdate, которая включена в ту же транзакцию. И транзакция, которая используется для выполнения этой операции обновления, получает эксклюзивную блокировку для всех вновь создаваемых записей.

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

Мы просмотрели исходный код в пакете расширений Queryable и обнаружили, что запрос, который мы выполняем в запрашиваемом словаре, создает новую транзакцию для выборки отфильтрованных записей. Но эта транзакция не может получить доступ к записям, так как предыдущая транзакция в нашем коде получила эксклюзивную блокировку записи.

Ниже приведен пример кода, описывающего наш сценарий.

public async Task MyMethod() 
{
    using (var tx = this.StateManager.CreateTransaction())
    {
         foreach(var record in records)
         {
              // Here we perform an update operation 
              // The transaction takes an exclusive lock on the created record to perform this operation and releases only after it is committed
              var result = await indexedDictionary.AddOrUpdateAsync(tx, myKey, myValue, (key, value) => myValue);

              // Creating a Queryable dictionary
              var queryableDictionary = new QueryableReliableIndexedDictionary(indexedDictionary, this.StateManager);

              // Running a query on the queryableDictionary 
              var filteredRecords = queryableDictionary.Where(x => x.indexedProperty== propertyValue).ToList();

              // The code to filter the data exists in the Service Fabric Queryable package where a new transaction is being created.
              // Once we query with where condition on the queryable dictionary, the Execute method gets called in the package where the actual filtering takes place.
              // That code looks similar to the code snippet given below.
         }

         await tx.CommitAsync();

    }        
}

Ниже приведен фрагмент кода из пакета Service Fabri c Queryable.

internal static async Task<object> Execute<TKey, TValue>(Expression expression)
{


    // This transaction is being created which tries to access the records actual dictionary
    using (var tx = stateManager.CreateTransaction())
    {
         // This statement tries to access the dictionary.. but it can't as the previous transaction has acquired an exclusive lock on the record it is trying to access
         // It waits for 4 seconds and throws a Timeout Exception
         IEnumerable<KeyValuePair<TKey, TValue>> pairs = await indexedDictionary.GetAllAsync(tx, keys, TimeSpan.FromSeconds(4), new CancellationToken()).AsEnumerable();
         values = new KeyValueToValueEnumerable<TKey, TValue>(pairs);
         await tx.CommitAsync();
    }
}

Есть ли какой-нибудь способ, которым мы можем запросить словарь с возможностью запроса без фиксации предыдущей транзакции?

1 Ответ

0 голосов
/ 30 января 2020

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

...