This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
elliebot/src/EllieBot/_common/Impl/RemoteGrpcCoordinator.cs
Toastie 487c7865cb
Fixed greet/bye messages showing wrong message in the wrong server sometimes
Fixed the check for updates service
Version upped to 5.1.12. Updated CHANGELOG.md
2024-10-05 11:44:44 +13:00

131 lines
No EOL
3.8 KiB
C#

#nullable disable
using Grpc.Core;
using Grpc.Net.Client;
using EllieBot.Common.ModuleBehaviors;
using EllieBot.Coordinator;
namespace EllieBot.Services;
public class RemoteGrpcCoordinator : ICoordinator, IReadyExecutor
{
private readonly Coordinator.Coordinator.CoordinatorClient _coordClient;
private readonly DiscordSocketClient _client;
public RemoteGrpcCoordinator(IBotCreds creds, DiscordSocketClient client)
{
var coordUrl = string.IsNullOrWhiteSpace(creds.CoordinatorUrl) ? "http://localhost:3442" : creds.CoordinatorUrl;
var channel = GrpcChannel.ForAddress(coordUrl);
_coordClient = new(channel);
_client = client;
}
public bool RestartBot()
{
_coordClient.RestartAllShards(new());
return true;
}
public void Die(bool graceful)
=> _coordClient.Die(new()
{
Graceful = graceful
});
public bool RestartShard(int shardId)
{
_coordClient.RestartShard(new()
{
ShardId = shardId
});
return true;
}
public IList<ShardStatus> GetAllShardStatuses()
{
var res = _coordClient.GetAllStatuses(new());
return res.Statuses.ToArray()
.Map(s => new ShardStatus
{
ConnectionState = FromCoordConnState(s.State),
GuildCount = s.GuildCount,
ShardId = s.ShardId,
LastUpdate = s.LastUpdate.ToDateTime()
});
}
public int GetGuildCount()
{
var res = _coordClient.GetAllStatuses(new());
return res.Statuses.Sum(x => x.GuildCount);
}
public async Task Reload()
=> await _coordClient.ReloadAsync(new());
public Task OnReadyAsync()
{
Task.Run(async () =>
{
var gracefulImminent = false;
while (true)
{
try
{
var reply = await _coordClient.HeartbeatAsync(new()
{
State = ToCoordConnState(_client.ConnectionState),
GuildCount =
_client.ConnectionState == ConnectionState.Connected ? _client.Guilds.Count : 0,
ShardId = _client.ShardId
},
deadline: DateTime.UtcNow + TimeSpan.FromSeconds(10));
gracefulImminent = reply.GracefulImminent;
}
catch (RpcException ex)
{
if (!gracefulImminent)
{
Log.Warning(ex, "Hearbeat failed and graceful shutdown was not expected: {Message}",
ex.Message);
break;
}
Log.Information("Coordinator is restarting gracefully. Waiting...");
await Task.Delay(30_000);
}
catch (Exception ex)
{
Log.Error(ex, "Unexpected heartbeat exception: {Message}", ex.Message);
break;
}
await Task.Delay(7500);
}
Environment.Exit(5);
});
return Task.CompletedTask;
}
private ConnState ToCoordConnState(ConnectionState state)
=> state switch
{
ConnectionState.Connecting => ConnState.Connecting,
ConnectionState.Connected => ConnState.Connected,
_ => ConnState.Disconnected
};
private ConnectionState FromCoordConnState(ConnState state)
=> state switch
{
ConnState.Connecting => ConnectionState.Connecting,
ConnState.Connected => ConnectionState.Connected,
_ => ConnectionState.Disconnected
};
}