Implements marketinsights api
This commit is contained in:
parent
87bda475df
commit
3d347a936d
|
@ -15,7 +15,14 @@
|
||||||
var originalValue = currentAverage;
|
var originalValue = currentAverage;
|
||||||
var originalValueWeight = ((n - 1.0f) / n);
|
var originalValueWeight = ((n - 1.0f) / n);
|
||||||
var newValueWeight = (1.0f / n);
|
var newValueWeight = (1.0f / n);
|
||||||
return (originalValue * originalValueWeight) + (newValue * newValueWeight);
|
return GetWeightedAverage(originalValue, originalValueWeight, newValue, newValueWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float GetWeightedAverage(float value1, float weight1, float value2, float weight2)
|
||||||
|
{
|
||||||
|
float totalWeight = weight1 + weight2;
|
||||||
|
if (totalWeight == 0.0f) return 0.0f;
|
||||||
|
return ((value1 * weight1) + (value2 * weight2)) / totalWeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
namespace MarketInsights
|
using Logging;
|
||||||
|
|
||||||
|
namespace MarketInsights
|
||||||
{
|
{
|
||||||
public class AppState
|
public class AppState
|
||||||
{
|
{
|
||||||
|
@ -7,7 +9,9 @@
|
||||||
Config = config;
|
Config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarketOverview MarketOverview { get; set; } = new ();
|
public bool Realtime { get; set; }
|
||||||
|
public MarketOverview MarketOverview { get; set; } = new();
|
||||||
public Configuration Config { get; }
|
public Configuration Config { get; }
|
||||||
|
public ILog Log { get; } = new ConsoleLog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +1,50 @@
|
||||||
using CodexContractsPlugin.ChainMonitor;
|
using CodexContractsPlugin;
|
||||||
using GethPlugin;
|
using CodexContractsPlugin.ChainMonitor;
|
||||||
using System.Numerics;
|
using Nethereum.Model;
|
||||||
|
using TestNetRewarder;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace MarketInsights
|
namespace MarketInsights
|
||||||
{
|
{
|
||||||
public class AverageHistory
|
public class AverageHistory : ITimeSegmentHandler
|
||||||
{
|
{
|
||||||
public readonly List<MarketTimeSegment> contributions = new List<MarketTimeSegment>();
|
private readonly List<MarketTimeSegment> contributions = new List<MarketTimeSegment>();
|
||||||
|
private readonly ChainStateChangeHandlerMux mux = new ChainStateChangeHandlerMux();
|
||||||
|
private readonly AppState appState;
|
||||||
|
private readonly int maxContributions;
|
||||||
|
private readonly ChainState chainState;
|
||||||
|
|
||||||
}
|
public AverageHistory(AppState appState, ICodexContracts contracts, int maxContributions)
|
||||||
|
|
||||||
public class ContributionBuilder : IChainStateChangeHandler
|
|
||||||
{
|
|
||||||
private readonly MarketTimeSegment segment = new MarketTimeSegment();
|
|
||||||
|
|
||||||
public void OnNewRequest(RequestEvent requestEvent)
|
|
||||||
{
|
{
|
||||||
AddRequestToAverage(segment.Submitted, requestEvent);
|
this.appState = appState;
|
||||||
|
this.maxContributions = maxContributions;
|
||||||
|
chainState = new ChainState(appState.Log, contracts, mux, appState.Config.HistoryStartUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRequestCancelled(RequestEvent requestEvent)
|
public MarketTimeSegment[] Segments { get; private set; } = Array.Empty<MarketTimeSegment>();
|
||||||
|
|
||||||
|
public Task OnNewSegment(TimeRange timeRange)
|
||||||
{
|
{
|
||||||
AddRequestToAverage(segment.Expired, requestEvent);
|
var contribution = BuildContribution(timeRange);
|
||||||
|
contributions.Add(contribution);
|
||||||
|
|
||||||
|
while (contributions.Count > maxContributions)
|
||||||
|
{
|
||||||
|
contributions.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Segments = contributions.ToArray();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRequestFailed(RequestEvent requestEvent)
|
private MarketTimeSegment BuildContribution(TimeRange timeRange)
|
||||||
{
|
{
|
||||||
AddRequestToAverage(segment.Failed, requestEvent);
|
var builder = new ContributionBuilder(timeRange);
|
||||||
}
|
mux.Handlers.Add(builder);
|
||||||
|
chainState.Update(timeRange.To);
|
||||||
public void OnRequestFinished(RequestEvent requestEvent)
|
mux.Handlers.Remove(builder);
|
||||||
{
|
return builder.GetSegment();
|
||||||
AddRequestToAverage(segment.Finished, requestEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnRequestFulfilled(RequestEvent requestEvent)
|
|
||||||
{
|
|
||||||
AddRequestToAverage(segment.Started, requestEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddRequestToAverage(ContractAverages average, RequestEvent requestEvent)
|
|
||||||
{
|
|
||||||
average.Number++;
|
|
||||||
average.Price = GetNewAverage(average.Price, average.Number, requestEvent.Request.Request.Ask.Reward);
|
|
||||||
average.Size = GetNewAverage(average.Size, average.Number, requestEvent.Request.Request.Ask.SlotSize);
|
|
||||||
average.Duration = GetNewAverage(average.Duration, average.Number, requestEvent.Request.Request.Ask.Duration);
|
|
||||||
average.Collateral = GetNewAverage(average.Collateral, average.Number, requestEvent.Request.Request.Ask.Collateral);
|
|
||||||
average.ProofProbability = GetNewAverage(average.ProofProbability, average.Number, requestEvent.Request.Request.Ask.ProofProbability);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetNewAverage(float currentAverage, int newNumberOfValues, BigInteger newValue)
|
|
||||||
{
|
|
||||||
return GetNewAverage(currentAverage, newNumberOfValues, (float)newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetNewAverage(float currentAverage, int newNumberOfValues, float newValue)
|
|
||||||
{
|
|
||||||
return RollingAverage.GetNewAverage(currentAverage, newNumberOfValues, newValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,5 +33,13 @@ namespace MarketInsights
|
||||||
return DateTimeOffset.FromUnixTimeSeconds(CheckHistoryTimestamp).UtcDateTime;
|
return DateTimeOffset.FromUnixTimeSeconds(CheckHistoryTimestamp).UtcDateTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSpan UpdateInterval
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return TimeSpan.FromMinutes(UpdateIntervalMinutes);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
using CodexContractsPlugin.ChainMonitor;
|
||||||
|
using GethPlugin;
|
||||||
|
using System.Numerics;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
|
namespace MarketInsights
|
||||||
|
{
|
||||||
|
public class ContributionBuilder : IChainStateChangeHandler
|
||||||
|
{
|
||||||
|
private readonly MarketTimeSegment segment = new MarketTimeSegment();
|
||||||
|
|
||||||
|
public ContributionBuilder(TimeRange timeRange)
|
||||||
|
{
|
||||||
|
segment = new MarketTimeSegment
|
||||||
|
{
|
||||||
|
FromUtc = timeRange.From,
|
||||||
|
ToUtc = timeRange.To
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnNewRequest(RequestEvent requestEvent)
|
||||||
|
{
|
||||||
|
AddRequestToAverage(segment.Submitted, requestEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRequestCancelled(RequestEvent requestEvent)
|
||||||
|
{
|
||||||
|
AddRequestToAverage(segment.Expired, requestEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRequestFailed(RequestEvent requestEvent)
|
||||||
|
{
|
||||||
|
AddRequestToAverage(segment.Failed, requestEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRequestFinished(RequestEvent requestEvent)
|
||||||
|
{
|
||||||
|
AddRequestToAverage(segment.Finished, requestEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRequestFulfilled(RequestEvent requestEvent)
|
||||||
|
{
|
||||||
|
AddRequestToAverage(segment.Started, requestEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarketTimeSegment GetSegment()
|
||||||
|
{
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddRequestToAverage(ContractAverages average, RequestEvent requestEvent)
|
||||||
|
{
|
||||||
|
average.Number++;
|
||||||
|
average.Price = GetNewAverage(average.Price, average.Number, requestEvent.Request.Request.Ask.Reward);
|
||||||
|
average.Size = GetNewAverage(average.Size, average.Number, requestEvent.Request.Request.Ask.SlotSize);
|
||||||
|
average.Duration = GetNewAverage(average.Duration, average.Number, requestEvent.Request.Request.Ask.Duration);
|
||||||
|
average.Collateral = GetNewAverage(average.Collateral, average.Number, requestEvent.Request.Request.Ask.Collateral);
|
||||||
|
average.ProofProbability = GetNewAverage(average.ProofProbability, average.Number, requestEvent.Request.Request.Ask.ProofProbability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetNewAverage(float currentAverage, int newNumberOfValues, BigInteger newValue)
|
||||||
|
{
|
||||||
|
return GetNewAverage(currentAverage, newNumberOfValues, (float)newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetNewAverage(float currentAverage, int newNumberOfValues, float newValue)
|
||||||
|
{
|
||||||
|
return RollingAverage.GetNewAverage(currentAverage, newNumberOfValues, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Framework\ArgsUniform\ArgsUniform.csproj" />
|
<ProjectReference Include="..\..\Framework\ArgsUniform\ArgsUniform.csproj" />
|
||||||
<ProjectReference Include="..\..\ProjectPlugins\CodexContractsPlugin\CodexContractsPlugin.csproj" />
|
<ProjectReference Include="..\..\ProjectPlugins\CodexContractsPlugin\CodexContractsPlugin.csproj" />
|
||||||
|
<ProjectReference Include="..\TestNetRewarder\TestNetRewarder.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime LastUpdatedUtc { get; set; }
|
public DateTime LastUpdatedUtc { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When false, service is busy processing history in order to catch up to the present.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsUpToDate { get; set; }
|
||||||
|
|
||||||
public MarketTimeSegment[] TimeSegments { get; set; } = Array.Empty<MarketTimeSegment>();
|
public MarketTimeSegment[] TimeSegments { get; set; } = Array.Empty<MarketTimeSegment>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using ArgsUniform;
|
using ArgsUniform;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Nethereum.Model;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace MarketInsights
|
namespace MarketInsights
|
||||||
|
@ -10,9 +11,20 @@ namespace MarketInsights
|
||||||
{
|
{
|
||||||
var uniformArgs = new ArgsUniform<Configuration>(PrintHelp, args);
|
var uniformArgs = new ArgsUniform<Configuration>(PrintHelp, args);
|
||||||
var config = uniformArgs.Parse(true);
|
var config = uniformArgs.Parse(true);
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
var appState = new AppState(config);
|
var appState = new AppState(config);
|
||||||
var updater = new Updater(appState);
|
|
||||||
|
Console.CancelKeyPress += (s, e) =>
|
||||||
|
{
|
||||||
|
appState.Log.Log("Stopping...");
|
||||||
|
cts.Cancel();
|
||||||
|
e.Cancel = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var connector = GethConnector.GethConnector.Initialize(appState.Log);
|
||||||
|
if (connector == null) throw new Exception("Invalid Geth information");
|
||||||
|
|
||||||
|
var updater = new Updater(appState, connector.CodexContracts, cts.Token);
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
@ -49,6 +61,14 @@ namespace MarketInsights
|
||||||
private static void PrintHelp()
|
private static void PrintHelp()
|
||||||
{
|
{
|
||||||
Console.WriteLine("WebAPI for generating market overview for Codex network. Comes with OpenAPI swagger endpoint.");
|
Console.WriteLine("WebAPI for generating market overview for Codex network. Comes with OpenAPI swagger endpoint.");
|
||||||
|
|
||||||
|
var nl = Environment.NewLine;
|
||||||
|
Console.WriteLine($"Required environment variables: {nl}" +
|
||||||
|
$"'GETH_HOST'{nl}",
|
||||||
|
$"'GETH_HTTP_PORT'{nl}",
|
||||||
|
$"'CODEXCONTRACTS_MARKETPLACEADDRESS'{nl}",
|
||||||
|
$"'CODEXCONTRACTS_TOKENADDRESS'{nl}",
|
||||||
|
$"'CODEXCONTRACTS_ABI'{nl}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
using CodexContractsPlugin.ChainMonitor;
|
||||||
|
using Utils;
|
||||||
|
using YamlDotNet.Core;
|
||||||
|
|
||||||
|
namespace MarketInsights
|
||||||
|
{
|
||||||
|
public class Tracker
|
||||||
|
{
|
||||||
|
private readonly AverageHistory history;
|
||||||
|
|
||||||
|
public Tracker(int numberOfSegments, AverageHistory history)
|
||||||
|
{
|
||||||
|
NumberOfSegments = numberOfSegments;
|
||||||
|
this.history = history;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int NumberOfSegments { get; }
|
||||||
|
|
||||||
|
public MarketTimeSegment? CreateMarketTimeSegment()
|
||||||
|
{
|
||||||
|
if (history.Segments.Length < NumberOfSegments) return null;
|
||||||
|
|
||||||
|
var mySegments = history.Segments.TakeLast(NumberOfSegments);
|
||||||
|
return AverageSegments(mySegments);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MarketTimeSegment AverageSegments(IEnumerable<MarketTimeSegment> mySegments)
|
||||||
|
{
|
||||||
|
var result = new MarketTimeSegment();
|
||||||
|
|
||||||
|
foreach (var segment in mySegments)
|
||||||
|
{
|
||||||
|
result.FromUtc = Min(result.FromUtc, segment.FromUtc);
|
||||||
|
result.ToUtc = Max(result.ToUtc, segment.ToUtc);
|
||||||
|
|
||||||
|
Combine(result.Submitted, segment.Submitted);
|
||||||
|
Combine(result.Expired, segment.Expired);
|
||||||
|
Combine(result.Started, segment.Started);
|
||||||
|
Combine(result.Finished, segment.Finished);
|
||||||
|
Combine(result.Failed, segment.Failed);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Combine(ContractAverages result, ContractAverages toAdd)
|
||||||
|
{
|
||||||
|
float weight1 = result.Number;
|
||||||
|
float weight2 = toAdd.Number;
|
||||||
|
|
||||||
|
result.Price = RollingAverage.GetWeightedAverage(result.Price, weight1, toAdd.Price, weight2);
|
||||||
|
result.Size = RollingAverage.GetWeightedAverage(result.Size, weight1, toAdd.Size, weight2);
|
||||||
|
result.Duration = RollingAverage.GetWeightedAverage(result.Duration, weight1, toAdd.Duration, weight2);
|
||||||
|
result.Collateral = RollingAverage.GetWeightedAverage(result.Collateral, weight1, toAdd.Collateral, weight2);
|
||||||
|
result.ProofProbability = RollingAverage.GetWeightedAverage(result.ProofProbability, weight1, toAdd.ProofProbability, weight2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime Max(DateTime a, DateTime b)
|
||||||
|
{
|
||||||
|
if (a > b) return a;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime Min(DateTime a, DateTime b)
|
||||||
|
{
|
||||||
|
if (a > b) return b;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +1,67 @@
|
||||||
|
using CodexContractsPlugin;
|
||||||
|
using TestNetRewarder;
|
||||||
|
|
||||||
namespace MarketInsights
|
namespace MarketInsights
|
||||||
{
|
{
|
||||||
public class Updater
|
public class Updater
|
||||||
{
|
{
|
||||||
|
private readonly Random random = new Random();
|
||||||
private readonly AppState appState;
|
private readonly AppState appState;
|
||||||
|
private readonly CancellationToken ct;
|
||||||
private readonly Tracker[] trackers;
|
private readonly Tracker[] trackers;
|
||||||
|
private readonly AverageHistory averageHistory;
|
||||||
|
|
||||||
public Updater(AppState appState)
|
public Updater(AppState appState, ICodexContracts contracts, CancellationToken ct)
|
||||||
{
|
{
|
||||||
this.appState = appState;
|
this.appState = appState;
|
||||||
|
this.ct = ct;
|
||||||
|
|
||||||
trackers = CreateTrackers();
|
trackers = CreateTrackers();
|
||||||
|
averageHistory = new AverageHistory(appState, contracts, trackers.Max(t => t.NumberOfSegments));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tracker[] CreateTrackers()
|
private Tracker[] CreateTrackers()
|
||||||
{
|
{
|
||||||
var tokens = appState.Config.TimeSegments.Split(";", StringSplitOptions.RemoveEmptyEntries);
|
var tokens = appState.Config.TimeSegments.Split(";", StringSplitOptions.RemoveEmptyEntries);
|
||||||
var nums = tokens.Select(t => Convert.ToInt32(t)).ToArray();
|
var nums = tokens.Select(t => Convert.ToInt32(t)).ToArray();
|
||||||
return nums.Select(n => new Tracker(n)).ToArray();
|
return nums.Select(n => new Tracker(n, averageHistory)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
|
Task.Run(Runner);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class Tracker
|
private async Task Runner()
|
||||||
{
|
|
||||||
public Tracker(int numberOfSegments)
|
|
||||||
{
|
{
|
||||||
|
var segmenter = new TimeSegmenter(
|
||||||
|
appState.Log,
|
||||||
|
segmentSize: appState.Config.UpdateInterval,
|
||||||
|
historyStartUtc: appState.Config.HistoryStartUtc,
|
||||||
|
handler: averageHistory
|
||||||
|
);
|
||||||
|
|
||||||
|
while (!ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
await segmenter.ProcessNextSegment();
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(3), ct);
|
||||||
|
|
||||||
|
var marketTimeSegments = trackers
|
||||||
|
.Select(t => t.CreateMarketTimeSegment())
|
||||||
|
.Where(t => t != null)
|
||||||
|
.Cast<MarketTimeSegment>()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
appState.MarketOverview = new MarketOverview
|
||||||
|
{
|
||||||
|
TimeSegments = marketTimeSegments,
|
||||||
|
IsUpToDate = segmenter.IsRealtime,
|
||||||
|
LastUpdatedUtc = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
|
||||||
|
var r = random.Next(appState.Config.MaxRandomIntervalSeconds);
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(r), ct);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace TestNetRewarder
|
||||||
EnsureGethOnline();
|
EnsureGethOnline();
|
||||||
|
|
||||||
Log.Log("Starting TestNet Rewarder...");
|
Log.Log("Starting TestNet Rewarder...");
|
||||||
var segmenter = new TimeSegmenter(Log, Config, processor);
|
var segmenter = new TimeSegmenter(Log, Config.Interval, Config.HistoryStartUtc, processor);
|
||||||
|
|
||||||
while (!CancellationToken.IsCancellationRequested)
|
while (!CancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,28 +15,28 @@ namespace TestNetRewarder
|
||||||
private readonly TimeSpan segmentSize;
|
private readonly TimeSpan segmentSize;
|
||||||
private DateTime latest;
|
private DateTime latest;
|
||||||
|
|
||||||
public TimeSegmenter(ILog log, Configuration configuration, ITimeSegmentHandler handler)
|
public TimeSegmenter(ILog log, TimeSpan segmentSize, DateTime historyStartUtc, ITimeSegmentHandler handler)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
if (configuration.IntervalMinutes < 0) configuration.IntervalMinutes = 1;
|
this.segmentSize = segmentSize;
|
||||||
|
latest = historyStartUtc;
|
||||||
segmentSize = configuration.Interval;
|
|
||||||
latest = configuration.HistoryStartUtc;
|
|
||||||
|
|
||||||
log.Log("Starting time segments at " + latest);
|
log.Log("Starting time segments at " + latest);
|
||||||
log.Log("Segment size: " + Time.FormatDuration(segmentSize));
|
log.Log("Segment size: " + Time.FormatDuration(segmentSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsRealtime { get; private set; } = false;
|
||||||
|
|
||||||
public async Task ProcessNextSegment()
|
public async Task ProcessNextSegment()
|
||||||
{
|
{
|
||||||
var end = latest + segmentSize;
|
var end = latest + segmentSize;
|
||||||
var waited = await WaitUntilTimeSegmentInPast(end);
|
IsRealtime = await WaitUntilTimeSegmentInPast(end);
|
||||||
|
|
||||||
if (Program.CancellationToken.IsCancellationRequested) return;
|
if (Program.CancellationToken.IsCancellationRequested) return;
|
||||||
|
|
||||||
var postfix = "(Catching up...)";
|
var postfix = "(Catching up...)";
|
||||||
if (waited) postfix = "(Real-time)";
|
if (IsRealtime) postfix = "(Real-time)";
|
||||||
log.Log($"Time segment [{latest} to {end}] {postfix}");
|
log.Log($"Time segment [{latest} to {end}] {postfix}");
|
||||||
|
|
||||||
var range = new TimeRange(latest, end);
|
var range = new TimeRange(latest, end);
|
||||||
|
|
Loading…
Reference in New Issue