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

ThreeMammals / Ocelot / 25553538207

08 May 2026 11:39AM UTC coverage: 94.48% (+0.9%) from 93.559%
25553538207

Pull #2388

github

web-flow
Merge 6158d8eee into fe672ec02
Pull Request #2388: #2378 Deprecate `Ocelot.Provider.Consul` project

6401 of 6775 relevant lines covered (94.48%)

2478.96 hits per line

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

97.26
src/Ocelot/Configuration/Repository/FileConfigurationPoller.cs
1
using Microsoft.Extensions.Hosting;
2
using Newtonsoft.Json;
3
using Ocelot.Configuration.Creator;
4
using Ocelot.Configuration.File;
5
using Ocelot.Logging;
6

7
namespace Ocelot.Configuration.Repository;
8

9
public class FileConfigurationPoller : IFileConfigurationPoller, IHostedService, IDisposable
10
{
11
    private readonly IOcelotLogger _logger;
12
    private readonly IFileConfigurationRepository _repo;
13
    private string _previousAsJson;
14
    private Timer _timer;
15
    private volatile bool _polling;
16
    private readonly IFileConfigurationPollerOptions _options;
17
    private readonly IInternalConfigurationRepository _internalConfigRepo;
18
    private readonly IInternalConfigurationCreator _internalConfigCreator;
19

20
    public FileConfigurationPoller(
19✔
21
        IOcelotLoggerFactory factory,
19✔
22
        IFileConfigurationRepository repo,
19✔
23
        IFileConfigurationPollerOptions options,
19✔
24
        IInternalConfigurationRepository internalConfigRepo,
19✔
25
        IInternalConfigurationCreator internalConfigCreator)
19✔
26
    {
27
        _internalConfigRepo = internalConfigRepo;
19✔
28
        _internalConfigCreator = internalConfigCreator;
19✔
29
        _options = options;
19✔
30
        _logger = factory.CreateLogger<FileConfigurationPoller>();
19✔
31
        _repo = repo;
19✔
32
        _previousAsJson = string.Empty;
19✔
33
    }
19✔
34

35
    private void OnTimer(object state)
36
    {
37
        if (_polling)
245✔
38
            return;
×
39

40
        _polling = true;
245✔
41
        Poll(); // PollAsync().GetAwaiter().GetResult(); // TODO This is not good, TimerCallback must be synchronous
245✔
42
        _polling = false;
245✔
43
    }
245✔
44

45
    public async Task StartAsync(CancellationToken cancellationToken)
46
    {
47
        if (_timer is not null)
11✔
48
            return;
1✔
49

50
        _logger.LogInformation(() => $"{nameof(FileConfigurationPoller)} is starting.");
10✔
51
        int delay = await _options.DelayAsync(cancellationToken);
10✔
52
        _timer = new(OnTimer, null, delay, delay); // TODO state could be CancellationToken?
10✔
53
    }
11✔
54

55
    public Task StopAsync(CancellationToken cancellationToken)
56
    {
57
        if (_timer is null)
3✔
58
            return Task.CompletedTask;
1✔
59

60
        _logger.LogInformation(() => $"{nameof(FileConfigurationPoller)} is stopping.");
2✔
61
        return Task.Run(() => _timer.Change(Timeout.Infinite, 0), cancellationToken);
4✔
62
    }
63

64
    public void Poll()
65
    {
66
        if (_polling)
248✔
67
            return;
245✔
68

69
        _logger.LogInformation(() => $"{nameof(Poll)}: Started polling");
3✔
70
        FileConfiguration configuration;
71
        try
72
        {
73
            configuration = _repo.Get();
3✔
74
        }
2✔
75
        catch (Exception e)
1✔
76
        {
77
            _logger.LogWarning(() => $"{nameof(Poll)}: Error getting {nameof(FileConfiguration)} -> {e}.");
1✔
78
            return;
1✔
79
        }
80

81
        if (configuration is null)
2✔
82
        {
83
            _logger.LogWarning(() => $"{nameof(Poll)}: Null object while getting {nameof(FileConfiguration)} via the {_repo.GetType().Name} service.");
1✔
84
            return;
1✔
85
        }
86

87
        var asJson = ToJson(configuration);
1✔
88
        if (asJson != _previousAsJson)
1✔
89
        {
90
            var config = _internalConfigCreator.Create(configuration).GetAwaiter().GetResult(); // TODO Extend interface with sync version
1✔
91
            if (!config.IsError)
1✔
92
                _internalConfigRepo.AddOrReplace(config.Data);
1✔
93

94
            _previousAsJson = asJson;
1✔
95
        }
96

97
        _logger.LogInformation(() => $"{nameof(Poll)}: Finished polling");
1✔
98
    }
2✔
99

100
    public async Task PollAsync(CancellationToken cancellationToken = default)
101
    {
102
        if (_polling)
6✔
103
            return;
×
104

105
        _logger.LogInformation(() => $"{nameof(PollAsync)}: Started polling");
6✔
106
        FileConfiguration configuration;
107
        try
108
        {
109
            configuration = await _repo.GetAsync(cancellationToken);
6✔
110
        }
5✔
111
        catch (Exception e)
1✔
112
        {
113
            _logger.LogWarning(() => $"{nameof(PollAsync)}: Error getting {nameof(FileConfiguration)} -> {e}.");
1✔
114
            return;
1✔
115
        }
116

117
        if (configuration is null)
5✔
118
        {
119
            _logger.LogWarning(() => $"{nameof(PollAsync)}: Null object while getting {nameof(FileConfiguration)} via the {_repo.GetType().Name} service.");
1✔
120
            return;
1✔
121
        }
122

123
        var asJson = ToJson(configuration);
4✔
124
        if (asJson != _previousAsJson)
4✔
125
        {
126
            var config = await _internalConfigCreator.Create(configuration);
3✔
127
            if (!config.IsError)
3✔
128
                _internalConfigRepo.AddOrReplace(config.Data);
2✔
129

130
            _previousAsJson = asJson;
3✔
131
        }
132

133
        _logger.LogInformation(() => $"{nameof(PollAsync)}: Finished polling");
4✔
134
    }
6✔
135

136
    /// <summary>
137
    /// We could do object comparison here but performance isnt really a problem. This might be an issue one day!.
138
    /// </summary>
139
    /// <returns>hash of the config.</returns>
140
    private static string ToJson(FileConfiguration config)
141
    {
142
        var currentHash = JsonConvert.SerializeObject(config);
5✔
143
        return currentHash;
5✔
144
    }
145

146
    public void Dispose()
147
    {
148
        _timer?.Dispose();
21✔
149
        _timer = null;
21✔
150
        GC.SuppressFinalize(this);
21✔
151
    }
21✔
152
}
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