Maksymalny czas wykonywania metody - brak efektu

0

Mam następujący problem - w momencie próby połączenia z Azure blob, chciałbym ograniczyć czas wykonywania metody w momencie, gdy kontener blob nie jest włączony Aktualnie metoda blob.ExistsAsync() wykonuje się spokojnie ponad 30 sekund, zanim zostanie rzucony wyjątek o nieaktywnym dostępie do bazy plikowej. W tym celu zrobiłem rozszerzenia do klasy TimeSpan, z czego jedno z nich, które potrzebuję do tego zadania, to:

        public static TResult ExecuteWithTimeLimit<TResult>(this TimeSpan timeSpan, Func<TResult> codeBlock)
            where TResult : class
        {
            var task = Task.Run(codeBlock);
            if (!task.Wait(timeSpan))
            {
                throw new TimeoutException("The function has taken longer than the maximum time allowed.");
            }
            return task.Result;
        }

Którego z kolei używam dla tej metody:

  async Task<CloudBlockBlob> GetFileBlob()
            {
                return await TimeSpan.FromMilliseconds(TaskExecutionMaximumDelay).ExecuteWithTimeLimit(async () =>
                {
                    var container = GetBlobContainer(fileContainerType);
                    var blob = container.GetBlockBlobReference(fileName);

                    if (!await blob.ExistsAsync()) // tutaj wątek się blokuje
                    {
                        throw new UserFriendlyException(L("FileNotFound"));
                    }

                    await blob.FetchAttributesAsync();
                    return blob;
                });
            }

Rozwiązanie wydaje się w porządku w sytuacji, jak w środku nie dzieje się nic z wykorzystaniem await. Jednak dla przypadku wyżej rozwiązanie w ogóle nie działa. Mógłby ktoś pomóc, jak usprawnić to rozwiązanie/napisać nowe dostosowane do moich potrzeb? Siedzę już nad tym trochę czasu.

2

Ojej :D to straszne jest :D

Użyj wersji ExistsAsync(CancellationToken) która przyjmuje CancellationToken,

async Task<CloudBlockBlob> GetFileBlob()
{
    CancellationTokenSource source = new CancellationTokenSource();
    source.CancelAfter(TimeSpan.FromMilliseconds(TaskExecutionMaximumDelay));              

    var container = GetBlobContainer(fileContainerType);
    var blob = container.GetBlockBlobReference(fileName);

    if (!await blob.ExistsAsync(source.Token)) // tutaj wątek się blokuje
    {
        throw new UserFriendlyException(L("FileNotFound"));
    }

    await blob.FetchAttributesAsync();
    return blob;              
}         
0

No faktycznie z minimalizmem tutaj lepiej:d. Tylko jest pewien problem - nie mam dostępu do metody ExistsAsync(), którą mogę sobie co najwyżej zdekompilować. Z dziedziczeniem też niestety ciężko.

0

y nie rozumiem, klasa CloudBlockBlob ma tą metodę przyjmującą token ExistsAsync(CancellationToken), więc na czym ten brak dostępu polega ?

1

To wygląda na obejście klasycznego timeouta, który z defaultu jest ustawiony na 30 sek: https://docs.microsoft.com/en[...]s-for-blob-service-operations
Możesz to przecież zmienić.

0
neves napisał(a):

y nie rozumiem, klasa CloudBlockBlob ma tą metodę przyjmującą token ExistsAsync(CancellationToken), więc na czym ten brak dostępu polega ?

tutaj jest przykład wątku z tym samym problemem https://github.com/Azure/azure-storage-net/issues/382. Faktycznie, mimo że w dokumentacji Microsoft ta metoda istnieje, to dla mojego Bloba na przykład już nie ma do niej dostępu. Obszedłem to w ten sposób:

var source = new CancellationTokenSource();
                var container = GetBlobContainer(fileContainerType);
                var blob = container.GetBlockBlobReference(fileName);

                if (!await blob.ExistsAsync(new BlobRequestOptions
                {
                    MaximumExecutionTime =
                        TimeSpan.FromMilliseconds(TaskMaximumExecutionTime)
                },
                    new OperationContext(),
                    source.Token))
                {
                    throw new UserFriendlyException(L("FileNotFound"));
                }
error91 napisał(a):

To wygląda na obejście klasycznego timeouta, który z defaultu jest ustawiony na 30 sek: https://docs.microsoft.com/en[...]s-for-blob-service-operations
Możesz to przecież zmienić.

Pytanie, czy da się to ustawić np. w configu, żeby nie było konieczne za każdym razem wywoływanie tej sygnatury metody jak wyżej.

0

Nie próbowałem, ale jestem prawie pewien że ustawiasz to tylko raz: https://docs.microsoft.com/en[...]s/set-blob-service-properties

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0