• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

net-daemon / netdaemon / 27791342827

18 Jun 2026 09:46PM UTC coverage: 84.068% (+0.2%) from 83.827%
27791342827

Pull #1389

github

web-flow
Merge 2d80d9aa1 into 0116c9815
Pull Request #1389: [codex] Improve high-event hot paths

923 of 1213 branches covered (76.09%)

Branch coverage included in aggregate %.

55 of 56 new or added lines in 2 files covered. (98.21%)

3 existing lines in 1 file now uncovered.

3425 of 3959 relevant lines covered (86.51%)

584.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.31
/src/Client/NetDaemon.HassClient/Internal/Helpers/ResultMessageHandler.cs
1
using System.Collections.Concurrent;
2

3
namespace NetDaemon.Client.Internal.Helpers;
4

5
/// <summary>
6
/// Handles the result of a 'fire and forget` Message tp Home Assistant
7
/// We mainly make sure that any Errors from HA or technical exceptions will get logged correctly
8
/// We also track the tasks so we can await for all pending tasks to finish
9
/// </summary>
10
internal class ResultMessageHandler(ILogger logger, TimeProvider _timeProvider) : IAsyncDisposable
49✔
11
{
12
    private readonly TimeSpan WaitForResultTimeout = TimeSpan.FromSeconds(20);
49✔
13
    private readonly CancellationTokenSource _tokenSource = new();
49✔
14
    private readonly ConcurrentDictionary<Task, object?> _backgroundTasks = new();
49✔
15

16
    public void HandleResult(Task<HassMessage> returnMessageTask, CommandMessage originalCommand)
17
    {
18
        var withErrorHandling = HandleResultError(returnMessageTask, originalCommand);
24✔
19

20
        // Save the task in the dictionary and remove it when it is done
21
        // this allows us to wait for all pending background tasks to finish
22
        _backgroundTasks.TryAdd(withErrorHandling, null);
24✔
23
        withErrorHandling.ContinueWith(_ => _backgroundTasks.TryRemove(withErrorHandling, out var _));
48✔
24
    }
24✔
25

26
    private async Task HandleResultError(Task<HassMessage> returnMessageTask, CommandMessage originalCommand)
27
    {
28
        try
29
        {
30
            try
31
            {
32
                await returnMessageTask.WaitAsync(WaitForResultTimeout, _timeProvider, _tokenSource.Token);
24✔
33
            }
18✔
34
            catch (TimeoutException)
3✔
35
            {
36
                logger.LogWarning("Command ({CommandType}) did not get response in timely fashion.  Sent command is {CommandMessage}",
3✔
37
                    originalCommand.Type, originalCommand.GetJsonString());
3✔
38
            }
3✔
39

40
            // We wait for the task even if there was a timeout so if we eventually do get a result it will be logged
41
            // we catch the original error
42
            var result = await returnMessageTask.ConfigureAwait(false);
21✔
43
            if (!result.Success ?? false)
20✔
44
            {
45
                logger.LogError("Failed command ({CommandType}) error: {ErrorResult}.  Sent command is {CommandMessage}",
2✔
46
                    originalCommand.Type, result.Error, originalCommand.GetJsonString());
2✔
47
            }
48
        }
20✔
49
        catch (Exception e)
4✔
50
        {
51
            logger.LogError(e, "Exception waiting for result message.  Sent command is {CommandMessage}", originalCommand.GetJsonString());
4✔
52
        }
4✔
53
    }
24✔
54

55
    public async Task WaitPendingBackgroundTasksAsync()
56
    {
57
        if (!_backgroundTasks.IsEmpty)
54✔
58
        {
59
            await Task.WhenAll(_backgroundTasks.Keys).ConfigureAwait(false);
8✔
60
        }
61
    }
54✔
62

63
    public async ValueTask DisposeAsync()
64
    {
65
        try
66
        {
67
            await WaitPendingBackgroundTasksAsync().WaitAsync(TimeSpan.FromSeconds(5), _timeProvider).ConfigureAwait(false);
48✔
68
        }
48✔
UNCOV
69
        catch (TimeoutException e)
×
70
        {
UNCOV
71
            logger.LogError(e, "One or requests are still pending while closing connection to Home Assistant");
×
UNCOV
72
        }
×
73

74
        _tokenSource.Dispose();
48✔
75
    }
48✔
76
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc