Skip to content

Commit 03778b0

Browse files
Implement combined instance messaging for direct and remote instances
1 parent af5a645 commit 03778b0

File tree

13 files changed

+449
-382
lines changed

13 files changed

+449
-382
lines changed

src/Certify.Client/ManagementServerClient.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ public ManagementServerClient(string hubUri, ManagedInstanceInfo instanceInfo)
3131
{
3232
_hubUri = $"{hubUri}";
3333
_instanceInfo = instanceInfo;
34+
35+
}
36+
37+
private void Log(string msg)
38+
{
39+
System.Diagnostics.Debug.WriteLine(msg);
3440
}
3541

3642
public bool IsConnected()
@@ -95,11 +101,11 @@ public async Task Disconnect()
95101
}
96102
private void PerformRequestedCommand(InstanceCommandRequest cmd)
97103
{
98-
System.Diagnostics.Debug.WriteLine($"Got command from management server {cmd}");
104+
Log($"[ManagementServerClient.PerformRequestedCommand] Got command from management server {cmd.CommandId} {cmd.CommandType}");
99105

100106
if (cmd.CommandType == ManagementHubCommands.GetInstanceInfo)
101107
{
102-
SendInstanceInfo(cmd.CommandId);
108+
SendInstanceInfo(cmd.CommandId, isCommandResponse: true);
103109
}
104110
else
105111
{
@@ -108,6 +114,10 @@ private void PerformRequestedCommand(InstanceCommandRequest cmd)
108114
{
109115
if (cmd.CommandType != ManagementHubCommands.Reconnect)
110116
{
117+
task.Result.IsCommandResponse = true;
118+
task.Result.CommandType = cmd.CommandType;
119+
task.Result.CommandId = cmd.CommandId;
120+
111121
_connection.SendAsync(ManagementHubMessages.ReceiveCommandResult, task.Result).Wait();
112122
}
113123
else

src/Certify.Core/Management/CertifyManager/CertifyManager.ManagementHub.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private async Task EnsureMgmtHubConnection()
6666

6767
private void SendHeartbeatToManagementHub()
6868
{
69-
_managementServerClient.SendInstanceInfo(Guid.NewGuid(), false);
69+
_managementServerClient.SendInstanceInfo(Guid.NewGuid(), isCommandResponse: false);
7070
}
7171

7272
public ManagedInstanceInfo GetManagedInstanceInfo()
@@ -104,10 +104,12 @@ private async Task StartManagementHubConnection(string hubUri)
104104

105105
_managementServerClient.OnGetCommandResult += PerformHubCommandWithResult;
106106
_managementServerClient.OnConnectionReconnecting += _managementServerClient_OnConnectionReconnecting;
107+
108+
_serviceLog.Information("Connected to management hub {hubUri}", hubUri);
107109
}
108110
catch (Exception ex)
109111
{
110-
_serviceLog.Error(ex, "Failed to create connection to management hub {hubUri}", hubUri);
112+
_serviceLog.Error(ex, "Failed to connect to management hub {hubUri}", hubUri);
111113

112114
_managementServerClient = null;
113115
}

src/Certify.Core/Management/CertifyManager/CertifyManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using System.IO;

src/Certify.Models/Hub/ManagedInstanceInfo.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,16 @@ public class ManagedInstanceInfo
1414

1515
public List<string> Tags { get; set; } = new List<string>();
1616
public DateTimeOffset LastReported { get; set; }
17+
18+
public string ConnectionStatus { get; set; } = string.Empty;
1719
}
1820

21+
public class ConnectionStatus
22+
{
23+
public const string Connected = "connected";
24+
public const string Disconnected = "disconnected";
25+
public const string Away = "away";
26+
}
1927
public class ManagedInstanceItems
2028
{
2129
public string InstanceId { get; set; } = string.Empty;

src/Certify.Server/Certify.Server.Hub.Api/Controllers/internal/HubController.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
using Certify.Client;
22
using Certify.Models.Hub;
3+
using Certify.Server.Hub.Api.Services;
34
using Certify.Server.Hub.Api.SignalR.ManagementHub;
45
using Microsoft.AspNetCore.Authentication.JwtBearer;
56
using Microsoft.AspNetCore.Authorization;
67
using Microsoft.AspNetCore.Mvc;
7-
using Microsoft.AspNetCore.SignalR;
88

99
namespace Certify.Server.Hub.Api.Controllers
1010
{
@@ -21,21 +21,20 @@ public partial class HubController : ApiControllerBase
2121
private readonly ICertifyInternalApiClient _client;
2222

2323
private IInstanceManagementStateProvider _mgmtStateProvider;
24-
private IHubContext<InstanceManagementHub, IInstanceManagementHub> _mgmtHubContext;
25-
24+
private ManagementAPI _mgmtAPI;
2625
/// <summary>
2726
/// Constructor
2827
/// </summary>
2928
/// <param name="logger"></param>
3029
/// <param name="client"></param>
3130
/// <param name="mgmtStateProvider"></param>
3231
/// <param name="mgmtHubContext"></param>
33-
public HubController(ILogger<CertificateController> logger, ICertifyInternalApiClient client, IInstanceManagementStateProvider mgmtStateProvider, IHubContext<InstanceManagementHub, IInstanceManagementHub> mgmtHubContext)
32+
public HubController(ILogger<CertificateController> logger, ICertifyInternalApiClient client, IInstanceManagementStateProvider mgmtStateProvider, ManagementAPI mgmtAPI)
3433
{
3534
_logger = logger;
3635
_client = client;
3736
_mgmtStateProvider = mgmtStateProvider;
38-
_mgmtHubContext = mgmtHubContext;
37+
_mgmtAPI = mgmtAPI;
3938
}
4039

4140
/// <summary>
@@ -131,8 +130,8 @@ public async Task<IActionResult> GetHubManagedInstances()
131130
[ProducesResponseType(StatusCodes.Status200OK)]
132131
public async Task<IActionResult> FlushHubManagedInstances()
133132
{
134-
_mgmtStateProvider.Clear();
135-
await _mgmtHubContext.Clients.All.SendCommandRequest(new InstanceCommandRequest(ManagementHubCommands.Reconnect));
133+
_mgmtAPI.ReconnectInstances();
134+
136135
return new OkResult();
137136
}
138137

@@ -151,6 +150,7 @@ public async Task<IActionResult> GetHubInfo()
151150

152151
hubInfo.InstanceId = hubprefs.InstanceId;
153152

153+
// TODO: there is probably be a better place to set this
154154
_mgmtStateProvider.SetManagementHubInstanceId(hubInfo.InstanceId);
155155

156156
var versionInfo = await _client.GetAppVersion();

src/Certify.Server/Certify.Server.Hub.Api/Services/ManagementAPI.cs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,26 @@
1212
namespace Certify.Server.Hub.Api.Services
1313
{
1414
/// <summary>
15-
/// Management Hub API for handling commands and requests.
15+
/// Management Hub API for handling commands and requests. This sends commands to instances (local ICertifyManager instance or remote) and handles the results.
1616
/// </summary>
1717
public partial class ManagementAPI
1818
{
1919
IInstanceManagementStateProvider _mgmtStateProvider;
2020
IHubContext<InstanceManagementHub, IInstanceManagementHub> _mgmtHubContext;
2121
Certify.Management.ICertifyManager _certifyManager = default!;
2222

23+
ILogger<ManagementAPI> _log;
24+
2325
/// <summary>
2426
/// Initializes a new instance of the <see cref="ManagementAPI"/> class.
2527
/// </summary>
2628
/// <param name="mgmtStateProvider">The instance management state provider.</param>
2729
/// <param name="mgmtHubContext">The management hub context for SignalR or Direct communication.</param>
28-
public ManagementAPI(IInstanceManagementStateProvider mgmtStateProvider, IHubContext<InstanceManagementHub, IInstanceManagementHub> mgmtHubContext)
30+
public ManagementAPI(IInstanceManagementStateProvider mgmtStateProvider, IHubContext<InstanceManagementHub, IInstanceManagementHub> mgmtHubContext, ILogger<ManagementAPI> log)
2931
{
3032
_mgmtStateProvider = mgmtStateProvider;
3133
_mgmtHubContext = mgmtHubContext;
34+
_log = log;
3235
}
3336

3437
/// <summary>
@@ -37,11 +40,24 @@ public ManagementAPI(IInstanceManagementStateProvider mgmtStateProvider, IHubCon
3740
/// <param name="mgmtStateProvider">The instance management state provider.</param>
3841
/// <param name="mgmtHubContext">The management hub context for SignalR communication.</param>
3942
/// <param name="certifyManager">The in-process Certify manager instance.</param>
40-
public ManagementAPI(IInstanceManagementStateProvider mgmtStateProvider, IHubContext<InstanceManagementHub, IInstanceManagementHub> mgmtHubContext, Certify.Management.ICertifyManager certifyManager)
43+
public ManagementAPI(IInstanceManagementStateProvider mgmtStateProvider, IHubContext<InstanceManagementHub, IInstanceManagementHub> mgmtHubContext, Certify.Management.ICertifyManager certifyManager, ILogger<ManagementAPI> log)
4144
{
4245
_mgmtStateProvider = mgmtStateProvider;
4346
_mgmtHubContext = mgmtHubContext;
47+
_log = log;
4448
_certifyManager = certifyManager;
49+
50+
}
51+
52+
/// <summary>
53+
/// Flush connections and reconnect all instances.
54+
/// </summary>
55+
/// <returns></returns>
56+
public async Task ReconnectInstances()
57+
{
58+
_mgmtStateProvider.Clear();
59+
//TODO: send command to local instance if present, then send to signalr hub clients
60+
await _mgmtHubContext.Clients.All.SendCommandRequest(new InstanceCommandRequest(ManagementHubCommands.Reconnect));
4561
}
4662

4763
/// <summary>
@@ -56,14 +72,20 @@ public ManagementAPI(IInstanceManagementStateProvider mgmtStateProvider, IHubCon
5672

5773
if (connectionId == null)
5874
{
59-
throw new Exception("Instance connection info not known, cannot send commands to instance.");
75+
_log.LogError("Instance connection info not known for {instanceId}, cannot send command {cmdId} {cmdType} to instance.", instanceId, cmd.CommandId, cmd.CommandType);
6076
}
6177

62-
_mgmtStateProvider.AddAwaitedCommandRequest(cmd);
63-
64-
await _mgmtHubContext.Clients.Client(connectionId).SendCommandRequest(cmd);
65-
66-
return await _mgmtStateProvider.ConsumeAwaitedCommandResult(cmd.CommandId);
78+
if (_certifyManager != null && instanceId == _mgmtStateProvider.GetManagementHubInstanceId())
79+
{
80+
// get command result directly from in-process instance
81+
return await _certifyManager.PerformHubCommandWithResult(cmd);
82+
}
83+
else
84+
{
85+
_mgmtStateProvider.AddAwaitedCommandRequest(cmd);
86+
await _mgmtHubContext.Clients.Client(connectionId).SendCommandRequest(cmd);
87+
return await _mgmtStateProvider.ConsumeAwaitedCommandResult(cmd);
88+
}
6789
}
6890

6991
/// <summary>
@@ -80,11 +102,9 @@ private async Task SendCommandWithNoResult(string instanceId, InstanceCommandReq
80102
throw new Exception("Instance connection info not known, cannot send commands to instance.");
81103
}
82104

83-
_mgmtStateProvider.AddAwaitedCommandRequest(cmd);
84-
85105
if (_certifyManager != null && instanceId == _mgmtStateProvider.GetManagementHubInstanceId())
86106
{
87-
// get command result directly from in-process instance
107+
// send directly to in-process instance
88108
await _certifyManager.PerformHubCommandWithResult(cmd);
89109
}
90110
else
@@ -106,16 +126,7 @@ private async Task SendCommandWithNoResult(string instanceId, InstanceCommandReq
106126
InstanceCommandResult result;
107127
var cmd = new InstanceCommandRequest(commandType, args);
108128

109-
if (_certifyManager != null && instanceId == _mgmtStateProvider.GetManagementHubInstanceId())
110-
{
111-
// get command result directly from in-process instance
112-
result = await _certifyManager.PerformHubCommandWithResult(cmd);
113-
}
114-
else
115-
{
116-
// get command result via SignalR
117-
result = await GetCommandResult(instanceId, cmd);
118-
}
129+
result = await GetCommandResult(instanceId, cmd);
119130

120131
if (result?.Value != null)
121132
{
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Certify.Models.Hub;
2+
3+
namespace Certify.Server.Hub.Api.SignalR.ManagementHub
4+
{
5+
/// <summary>
6+
/// Interface for instance management hub events
7+
/// </summary>
8+
public interface IInstanceManagementHub
9+
{
10+
/// <summary>
11+
/// Send command to an instance or the current caller if instance not provided
12+
/// </summary>
13+
/// <param name="cmd"></param>
14+
/// <param name="targetInstanceId">If null, command is targetted at all instances</param>
15+
/// <param name="request"></param>
16+
/// <returns></returns>
17+
Task SendCommandRequest(InstanceCommandRequest cmd);
18+
19+
/// <summary>
20+
/// Receive command result from an instance
21+
/// </summary>
22+
/// <param name="result"></param>
23+
/// <returns></returns>
24+
Task ReceiveCommandResult(InstanceCommandResult result);
25+
26+
/// <summary>
27+
/// Receive adhoc message from an instance
28+
/// </summary>
29+
/// <param name="message"></param>
30+
/// <returns></returns>
31+
Task ReceiveInstanceMessage(InstanceMessage message);
32+
}
33+
}

0 commit comments

Comments
 (0)