Commit 9a583b2a authored by Dan Gershony's avatar Dan Gershony Committed by GitHub

Merge pull request #125 from dangershony/b-hearbeat

Adding a keepalive endpoint that if enabled will shutdown the node after a trashold
parents e201ad10 8cf0a91d
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;
using Breeze.Api.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Stratis.Bitcoin;
using Stratis.Bitcoin.Builder;
using Stratis.Bitcoin.Builder.Feature;
using Stratis.Bitcoin.Logging;
using Stratis.Bitcoin.Utilities;
namespace Breeze.Api
{
......@@ -14,31 +18,78 @@ namespace Breeze.Api
{
private readonly IFullNodeBuilder fullNodeBuilder;
private readonly FullNode fullNode;
private readonly ApiFeatureOptions apiFeatureOptions;
private readonly IAsyncLoopFactory asyncLoopFactory;
public ApiFeature(IFullNodeBuilder fullNodeBuilder, FullNode fullNode)
public ApiFeature(IFullNodeBuilder fullNodeBuilder, FullNode fullNode, ApiFeatureOptions apiFeatureOptions, IAsyncLoopFactory asyncLoopFactory)
{
this.fullNodeBuilder = fullNodeBuilder;
this.fullNode = fullNode;
this.apiFeatureOptions = apiFeatureOptions;
this.asyncLoopFactory = asyncLoopFactory;
}
public override void Start()
{
Logs.FullNode.LogInformation($"Api starting on url {this.fullNode.Settings.ApiUri}");
Program.Initialize(this.fullNodeBuilder.Services, this.fullNode);
this.TryStartKeepaliveMonitor();
}
/// <summary>
/// A KeepaliveMonitor when enabled will shutdown the
/// node if no one is calling the keepalive endpoint
/// during a certain trashold window
/// </summary>
public void TryStartKeepaliveMonitor()
{
if (this.apiFeatureOptions.KeepaliveMonitor?.KeepaliveInterval.TotalSeconds > 0)
{
this.asyncLoopFactory.Run("ApiFeature.KeepaliveMonitor", token =>
{
// shortened for redability
var monitor = this.apiFeatureOptions.KeepaliveMonitor;
// check the trashold to trigger a shutdown
if (monitor.LastBeat.Add(monitor.KeepaliveInterval) < DateTime.UtcNow)
this.fullNode.Stop();
return Task.CompletedTask;
},
this.fullNode.GlobalCancellation.Cancellation.Token,
repeatEvery: this.apiFeatureOptions.KeepaliveMonitor?.KeepaliveInterval,
startAfter: TimeSpans.Minute);
}
}
}
public static class ApiFeatureExtension
public class ApiFeatureOptions
{
public KeepaliveMonitor KeepaliveMonitor { get; set; }
public void Keepalive(TimeSpan timeSpan)
{
this.KeepaliveMonitor = new KeepaliveMonitor {KeepaliveInterval = timeSpan};
}
}
public static class ApiFeatureExtension
{
public static IFullNodeBuilder UseApi(this IFullNodeBuilder fullNodeBuilder)
public static IFullNodeBuilder UseApi(this IFullNodeBuilder fullNodeBuilder, Action<ApiFeatureOptions> optionsAction = null)
{
fullNodeBuilder.ConfigureFeature(features =>
// TODO: move the options in to the feature builder
var options = new ApiFeatureOptions();
optionsAction?.Invoke(options);
fullNodeBuilder.ConfigureFeature(features =>
{
features
.AddFeature<ApiFeature>()
.FeatureServices(services =>
{
services.AddSingleton(fullNodeBuilder);
services.AddSingleton(options);
});
});
......
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Breeze.Api.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using NBitcoin;
......@@ -11,10 +13,12 @@ namespace Breeze.Api.Controllers
public class NodeController : Controller
{
private readonly IFullNode fullNode;
private readonly ApiFeatureOptions apiFeatureOptions;
public NodeController(IFullNode fullNode)
public NodeController(IFullNode fullNode, ApiFeatureOptions apiFeatureOptions)
{
this.fullNode = fullNode;
this.apiFeatureOptions = apiFeatureOptions;
}
/// <summary>
......@@ -41,6 +45,21 @@ namespace Breeze.Api.Controllers
return this.Ok();
}
}
/// <summary>
/// Set the keepalive flag.
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("keepalive")]
public IActionResult Keepalive()
{
if (this.apiFeatureOptions.KeepaliveMonitor == null)
return new ObjectResult("Keepalive Disabled") {StatusCode = 405}; // (405) Method Not Allowed
this.apiFeatureOptions.KeepaliveMonitor.LastBeat = DateTime.UtcNow;
return this.Ok();
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Breeze.Api.Models
{
public class KeepaliveMonitor
{
public DateTime LastBeat { get; set; }
public TimeSpan KeepaliveInterval { get; set; }
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment