feat: remote await events from gateway

This commit is contained in:
alyssa 2025-03-29 17:55:01 +00:00
parent 64ff69723c
commit 15c992c572
17 changed files with 439 additions and 30 deletions

View file

@ -1,7 +1,10 @@
using Serilog;
using System.Net;
using System.Text;
using System.Text.Json;
using NodaTime;
using Myriad.Serialization;
using Myriad.Types;
@ -12,6 +15,7 @@ public class HttpDiscordCache: IDiscordCache
private readonly ILogger _logger;
private readonly HttpClient _client;
private readonly Uri _cacheEndpoint;
private readonly string? _eventTarget;
private readonly int _shardCount;
private readonly ulong _ownUserId;
@ -21,11 +25,12 @@ public class HttpDiscordCache: IDiscordCache
public EventHandler<(bool?, string)> OnDebug;
public HttpDiscordCache(ILogger logger, HttpClient client, string cacheEndpoint, int shardCount, ulong ownUserId, bool useInnerCache)
public HttpDiscordCache(ILogger logger, HttpClient client, string cacheEndpoint, string? eventTarget, int shardCount, ulong ownUserId, bool useInnerCache)
{
_logger = logger;
_client = client;
_cacheEndpoint = new Uri(cacheEndpoint);
_eventTarget = eventTarget;
_shardCount = shardCount;
_ownUserId = ownUserId;
_jsonSerializerOptions = new JsonSerializerOptions().ConfigureForMyriad();
@ -65,6 +70,68 @@ public class HttpDiscordCache: IDiscordCache
return JsonSerializer.Deserialize<T>(plaintext, _jsonSerializerOptions);
}
private Task AwaitEvent(ulong guildId, object data)
=> AwaitEventShard((int)((guildId >> 22) % (ulong)_shardCount), data);
private async Task AwaitEventShard(int shardId, object data)
{
if (_eventTarget == null)
throw new Exception("missing event target for remote await event");
var cluster = _cacheEndpoint.Authority;
// todo: there should not be infra-specific code here
if (cluster.Contains(".service.consul") || cluster.Contains("process.pluralkit-gateway.internal"))
// int(((guild_id >> 22) % shard_count) / 16)
cluster = $"cluster{shardId / 16}.{cluster}";
var response = await _client.PostAsync(
$"{_cacheEndpoint.Scheme}://{cluster}/await_event",
new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8)
);
if (response.StatusCode != HttpStatusCode.NoContent)
throw new Exception($"failed to await event from gateway: {response.StatusCode}");
}
public async Task AwaitReaction(ulong guildId, ulong messageId, ulong userId, Duration? timeout)
{
var obj = new
{
message_id = messageId,
user_id = userId,
target = _eventTarget!,
timeout = timeout?.TotalSeconds,
};
await AwaitEvent(guildId, obj);
}
public async Task AwaitMessage(ulong guildId, ulong channelId, ulong authorId, Duration? timeout, string[] options = null)
{
var obj = new
{
channel_id = channelId,
author_id = authorId,
target = _eventTarget!,
timeout = timeout?.TotalSeconds,
options = options,
};
await AwaitEvent(guildId, obj);
}
public async Task AwaitInteraction(int shardId, string id, Duration? timeout)
{
var obj = new
{
id = id,
target = _eventTarget!,
timeout = timeout?.TotalSeconds,
};
await AwaitEventShard(shardId, obj);
}
public async Task<Guild?> TryGetGuild(ulong guildId)
{
var hres = await QueryCache<Guild?>($"/guilds/{guildId}", guildId);