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

ThreeMammals / Ocelot / 25449655107

06 May 2026 05:05PM UTC coverage: 93.52% (-0.04%) from 93.559%
25449655107

Pull #2388

github

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

6336 of 6775 relevant lines covered (93.52%)

2974.9 hits per line

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

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

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

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

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

50
        _logger.LogInformation(() => $"{nameof(FileConfigurationPoller)} is starting.");
8✔
51
        int delay = await _options.DelayAsync(cancellationToken);
8✔
52
        _timer = new(OnTimer, null, delay, delay); // TODO state could be CancellationToken?
8✔
53
    }
9✔
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)
8✔
67
            return;
8✔
68

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

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

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

94
            _previousAsJson = asJson;
×
95
        }
96

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

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

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

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

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

130
            _previousAsJson = asJson;
×
131
        }
132

133
        _logger.LogInformation(() => $"{nameof(PollAsync)}: Finished polling");
×
134
    }
×
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);
×
143
        return currentHash;
×
144
    }
145

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