< Summary

Information
Class: Services.HangfireService.HangfireDistributedLockHelper
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/HangfireService/HangfireDistributedLockHelper.cs
Line coverage
95%
Covered lines: 23
Uncovered lines: 1
Coverable lines: 24
Total lines: 74
Line coverage: 95.8%
Branch coverage
91%
Covered branches: 11
Total branches: 12
Branch coverage: 91.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
SafeDispose(...)100%88100%
SafeDispose(...)75%4485.71%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/HangfireService/HangfireDistributedLockHelper.cs

#LineLine coverage
 1using System;
 2using Hangfire.Storage;
 3using Microsoft.Extensions.Logging;
 4
 5namespace Services.HangfireService;
 6
 7/// <summary>
 8/// Безопасное освобождение распределённых блокировок Hangfire (<see cref="IDisposable"/>) и их соединений (<see cref="I
 9/// <para>
 10/// При длительных операциях или перезапуске сервера БД соединение может быть разорвано.
 11/// В этом случае вызов <see cref="IDisposable.Dispose"/> у блокировки выполняет <c>DO RELEASE_LOCK</c>
 12/// на мёртвом сокете и выбрасывает <c>MySqlException: Failed to read the result set</c>.
 13/// Поскольку MySQL автоматически снимает блокировки при закрытии сессии, эта ошибка не должна
 14/// прерывать выполнение вызывающего кода, ломать <c>finally</c>-блоки или препятствовать закрытию соединений.
 15/// </para>
 16/// </summary>
 17public static class HangfireDistributedLockHelper
 18{
 19    /// <summary>
 20    /// Безопасно освобождает распределённую блокировку и закрывает соединение, гарантируя вызов обоих Dispose
 21    /// и обнуление ссылок.
 22    /// </summary>
 23    public static void SafeDispose(ref IDisposable? distLock, ref IStorageConnection? connection, ILogger? logger = null
 24    {
 325        if (distLock != null)
 26        {
 27            try
 28            {
 329                distLock.Dispose();
 230            }
 131            catch (Exception ex)
 32            {
 133                logger?.LogWarning(ex, "Ошибка при освобождении распределённой блокировки Hangfire (соединение могло быт
 134            }
 35            finally
 36            {
 337                distLock = null;
 338            }
 39        }
 40
 341        if (connection != null)
 42        {
 43            try
 44            {
 345                connection.Dispose();
 246            }
 147            catch (Exception ex)
 48            {
 149                logger?.LogWarning(ex, "Ошибка при закрытии соединения распределённой блокировки Hangfire");
 150            }
 51            finally
 52            {
 353                connection = null;
 354            }
 55        }
 356    }
 57
 58    /// <summary>
 59    /// Безопасно освобождает распределённую блокировку с перехватом исключений.
 60    /// </summary>
 61    public static void SafeDispose(IDisposable? distLock, ILogger? logger = null)
 62    {
 163        if (distLock == null) return;
 64
 65        try
 66        {
 167            distLock.Dispose();
 068        }
 169        catch (Exception ex)
 70        {
 171            logger?.LogWarning(ex, "Ошибка при освобождении распределённой блокировки Hangfire (соединение могло быть за
 172        }
 173    }
 74}