|
| 1 | +using NTorSpectator.Observer.TorIntegration; |
| 2 | +using NTorSpectator.Services; |
| 3 | +using NTorSpectator.Services.Models; |
| 4 | +using Quartz; |
| 5 | + |
| 6 | +namespace NTorSpectator.Observer.Services; |
| 7 | + |
| 8 | +public class SpectatorJob : IJob |
| 9 | +{ |
| 10 | + private readonly ILogger<SpectatorJob> _logger; |
| 11 | + private readonly ISitesCatalogue _sitesCatalogue; |
| 12 | + private readonly TorControlManager _torControl; |
| 13 | + private readonly ISiteObserver _siteObserver; |
| 14 | + |
| 15 | + public SpectatorJob(ILogger<SpectatorJob> logger, ISitesCatalogue sitesCatalogue, TorControlManager torControl, ISiteObserver siteObserver) |
| 16 | + { |
| 17 | + _logger = logger; |
| 18 | + _sitesCatalogue = sitesCatalogue; |
| 19 | + _torControl = torControl; |
| 20 | + _siteObserver = siteObserver; |
| 21 | + } |
| 22 | + |
| 23 | + public async Task Execute(IJobExecutionContext context) |
| 24 | + { |
| 25 | + var sites = await _sitesCatalogue.GetAllSites(); |
| 26 | + var siteQueue = new Queue<QueuedSite>(sites.Select(x => new QueuedSite(x, 0))); |
| 27 | + |
| 28 | + while(siteQueue.TryDequeue(out var queuedSite)) |
| 29 | + { |
| 30 | + using var _ = _logger.BeginScope(new Dictionary<string, object> { { "HiddenService", queuedSite.Site.SiteUri } }); |
| 31 | + try |
| 32 | + { |
| 33 | + var observations = await ObserveSite(queuedSite.Site.SiteUri); |
| 34 | + if (!observations.IsOk) |
| 35 | + { |
| 36 | + _logger.LogDebug("Site observed as not available"); |
| 37 | + var siteObservationsCount = queuedSite.ObservationsCount; |
| 38 | + if (siteObservationsCount < 3) |
| 39 | + { |
| 40 | + _logger.LogDebug("Site has been observed {Count} times, returning it to queue", siteObservationsCount); |
| 41 | + siteQueue.Enqueue(queuedSite with{ObservationsCount = siteObservationsCount + 1}); |
| 42 | + continue; |
| 43 | + } |
| 44 | + } |
| 45 | + await _siteObserver.AddNewObservation(queuedSite.Site.SiteUri, observations.IsOk); |
| 46 | + _logger.LogInformation("Site observed"); |
| 47 | + } |
| 48 | + catch (Exception e) |
| 49 | + { |
| 50 | + _logger.LogError(e, "Observation for site failed"); |
| 51 | + } |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + private record QueuedSite(Site Site, int ObservationsCount); |
| 56 | + |
| 57 | + private async Task<TorWatchResults> ObserveSite(string site) |
| 58 | + { |
| 59 | + var torReply = await _torControl.HsFetch(site); |
| 60 | + var positive = torReply.Count(x => x.Action == HsDescAction.Received); |
| 61 | + var negative = torReply.Count(x => x.Action == HsDescAction.Failed); |
| 62 | + return new(site, positive, negative); |
| 63 | + } |
| 64 | +} |
0 commit comments