move classes around, name caches more consistently, add more caches
This commit is contained in:
parent
e86b37ce2a
commit
e17dcf90a1
30 changed files with 443 additions and 51 deletions
47
Catalogger.Backend/Services/GuildFetchService.cs
Normal file
47
Catalogger.Backend/Services/GuildFetchService.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using System.Collections.Concurrent;
|
||||
using Catalogger.Backend.Cache;
|
||||
using Humanizer;
|
||||
using Remora.Discord.API.Abstractions.Rest;
|
||||
using Remora.Discord.API.Gateway.Commands;
|
||||
using Remora.Discord.Gateway;
|
||||
using Remora.Rest.Core;
|
||||
|
||||
namespace Catalogger.Backend.Services;
|
||||
|
||||
public class GuildFetchService(
|
||||
ILogger logger,
|
||||
DiscordGatewayClient gatewayClient,
|
||||
IDiscordRestGuildAPI guildApi,
|
||||
IInviteCache inviteCache) : BackgroundService
|
||||
{
|
||||
private readonly ILogger _logger = logger.ForContext<GuildFetchService>();
|
||||
private readonly ConcurrentQueue<Snowflake> _guilds = new();
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
using var timer = new PeriodicTimer(500.Milliseconds());
|
||||
while (await timer.WaitForNextTickAsync(stoppingToken))
|
||||
{
|
||||
if (!_guilds.TryPeek(out var guildId)) continue;
|
||||
|
||||
_logger.Debug("Fetching members and invites for guild {GuildId}", guildId);
|
||||
gatewayClient.SubmitCommand(new RequestGuildMembers(guildId, "", 0));
|
||||
var res = await guildApi.GetGuildInvitesAsync(guildId, stoppingToken);
|
||||
if (res.Error != null)
|
||||
{
|
||||
_logger.Error("Fetching invites for guild {GuildId}: {Error}", guildId, res.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
await inviteCache.SetAsync(guildId, res.Entity);
|
||||
}
|
||||
|
||||
_guilds.TryDequeue(out _);
|
||||
}
|
||||
}
|
||||
|
||||
public void EnqueueGuild(Snowflake guildId)
|
||||
{
|
||||
if (!_guilds.Contains(guildId)) _guilds.Enqueue(guildId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
using Catalogger.Backend.Extensions;
|
||||
using Remora.Discord.API;
|
||||
using Remora.Discord.API.Abstractions.Objects;
|
||||
using Remora.Rest.Core;
|
||||
|
||||
namespace Catalogger.Backend.Services;
|
||||
|
||||
public interface IWebhookCache
|
||||
{
|
||||
Task<Webhook?> GetWebhookAsync(ulong channelId);
|
||||
Task SetWebhookAsync(ulong channelId, Webhook webhook);
|
||||
|
||||
public async Task<Webhook> GetOrFetchWebhookAsync(ulong channelId, Func<Snowflake, Task<IWebhook>> fetch)
|
||||
{
|
||||
var webhook = await GetWebhookAsync(channelId);
|
||||
if (webhook != null) return webhook.Value;
|
||||
|
||||
var discordWebhook = await fetch(DiscordSnowflake.New(channelId));
|
||||
webhook = new Webhook { Id = discordWebhook.ID.ToUlong(), Token = discordWebhook.Token.Value };
|
||||
await SetWebhookAsync(channelId, webhook.Value);
|
||||
return webhook.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Webhook
|
||||
{
|
||||
public required ulong Id { get; init; }
|
||||
public required string Token { get; init; }
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Catalogger.Backend.Services;
|
||||
|
||||
public class InMemoryWebhookCache : IWebhookCache
|
||||
{
|
||||
private readonly ConcurrentDictionary<ulong, Webhook> _cache = new();
|
||||
|
||||
public Task<Webhook?> GetWebhookAsync(ulong channelId)
|
||||
{
|
||||
return _cache.TryGetValue(channelId, out var webhook)
|
||||
? Task.FromResult<Webhook?>(webhook)
|
||||
: Task.FromResult<Webhook?>(null);
|
||||
}
|
||||
|
||||
public Task SetWebhookAsync(ulong channelId, Webhook webhook)
|
||||
{
|
||||
_cache[channelId] = webhook;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
using App.Metrics;
|
||||
using Catalogger.Backend.Cache;
|
||||
using Catalogger.Backend.Cache.InMemoryCache;
|
||||
using Catalogger.Backend.Database;
|
||||
using Humanizer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
|
@ -10,9 +11,9 @@ namespace Catalogger.Backend.Services;
|
|||
|
||||
public class MetricsCollectionService(
|
||||
ILogger logger,
|
||||
GuildCacheService guildCache,
|
||||
ChannelCacheService channelCache,
|
||||
UserCacheService userCache,
|
||||
GuildCache guildCache,
|
||||
ChannelCache channelCache,
|
||||
UserCache userCache,
|
||||
IMetrics metrics,
|
||||
IServiceProvider services) : BackgroundService
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
using Catalogger.Backend.Database.Redis;
|
||||
using Humanizer;
|
||||
|
||||
namespace Catalogger.Backend.Services;
|
||||
|
||||
public class RedisWebhookCache(RedisService redisService) : IWebhookCache
|
||||
{
|
||||
public async Task<Webhook?> GetWebhookAsync(ulong channelId) =>
|
||||
await redisService.GetAsync<Webhook?>(WebhookKey(channelId));
|
||||
|
||||
public async Task SetWebhookAsync(ulong channelId, Webhook webhook) =>
|
||||
await redisService.SetAsync(WebhookKey(channelId), webhook, 24.Hours());
|
||||
|
||||
private static string WebhookKey(ulong channelId) => $"webhook:{channelId}";
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Concurrent;
|
||||
using Catalogger.Backend.Cache;
|
||||
using Catalogger.Backend.Cache.InMemoryCache;
|
||||
using Catalogger.Backend.Extensions;
|
||||
using Remora.Discord.API;
|
||||
using Remora.Discord.API.Abstractions.Objects;
|
||||
|
|
@ -14,7 +15,7 @@ public class WebhookExecutorService(
|
|||
Config config,
|
||||
ILogger logger,
|
||||
IWebhookCache webhookCache,
|
||||
ChannelCacheService channelCache,
|
||||
ChannelCache channelCache,
|
||||
IDiscordRestWebhookAPI webhookApi)
|
||||
{
|
||||
private readonly ILogger _logger = logger.ForContext<WebhookExecutorService>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue