Refactor data stores, merging the Store classes

This commit is contained in:
Ske
2019-10-26 19:45:30 +02:00
parent 1ab84b54dd
commit 6a73b3bdd6
21 changed files with 540 additions and 338 deletions

View File

@@ -9,39 +9,34 @@ using Humanizer;
using NodaTime;
namespace PluralKit.Bot {
public class EmbedService {
private SystemStore _systems;
private MemberStore _members;
private SwitchStore _switches;
private MessageStore _messages;
public class EmbedService
{
private IDataStore _data;
private IDiscordClient _client;
public EmbedService(SystemStore systems, MemberStore members, IDiscordClient client, SwitchStore switches, MessageStore messages)
public EmbedService(IDiscordClient client, IDataStore data)
{
_systems = systems;
_members = members;
_client = client;
_switches = switches;
_messages = messages;
_data = data;
}
public async Task<Embed> CreateSystemEmbed(PKSystem system) {
var accounts = await _systems.GetLinkedAccountIds(system);
var accounts = await _data.GetSystemAccounts(system);
// Fetch/render info for all accounts simultaneously
var users = await Task.WhenAll(accounts.Select(async uid => (await _client.GetUserAsync(uid))?.NameAndMention() ?? $"(deleted account {uid})"));
var memberCount = await _members.MemberCount(system);
var memberCount = await _data.GetSystemMemberCount(system);
var eb = new EmbedBuilder()
.WithColor(Color.Blue)
.WithTitle(system.Name ?? null)
.WithThumbnailUrl(system.AvatarUrl ?? null)
.WithFooter($"System ID: {system.Hid} | Created on {Formats.ZonedDateTimeFormat.Format(system.Created.InZone(system.Zone))}");
var latestSwitch = await _switches.GetLatestSwitch(system);
var latestSwitch = await _data.GetLatestSwitch(system);
if (latestSwitch != null)
{
var switchMembers = (await _switches.GetSwitchMembers(latestSwitch)).ToList();
var switchMembers = (await _data.GetSwitchMembers(latestSwitch)).ToList();
if (switchMembers.Count > 0)
eb.AddField("Fronter".ToQuantity(switchMembers.Count(), ShowQuantityAs.None),
string.Join(", ", switchMembers.Select(m => m.Name)));
@@ -85,7 +80,7 @@ namespace PluralKit.Bot {
color = Color.Default;
}
var messageCount = await _members.MessageCount(member);
var messageCount = await _data.GetMemberMessageCount(member);
var eb = new EmbedBuilder()
// TODO: add URL of website when that's up
@@ -108,7 +103,7 @@ namespace PluralKit.Bot {
public async Task<Embed> CreateFronterEmbed(PKSwitch sw, DateTimeZone zone)
{
var members = (await _switches.GetSwitchMembers(sw)).ToList();
var members = (await _data.GetSwitchMembers(sw)).ToList();
var timeSinceSwitch = SystemClock.Instance.GetCurrentInstant() - sw.Timestamp;
return new EmbedBuilder()
.WithColor(members.FirstOrDefault()?.Color?.ToDiscordColor() ?? Color.Blue)
@@ -125,7 +120,7 @@ namespace PluralKit.Bot {
foreach (var sw in sws)
{
// Fetch member list and format
var members = (await _switches.GetSwitchMembers(sw)).ToList();
var members = (await _data.GetSwitchMembers(sw)).ToList();
var membersStr = members.Any() ? string.Join(", ", members.Select(m => m.Name)) : "no fronter";
var switchSince = SystemClock.Instance.GetCurrentInstant() - sw.Timestamp;
@@ -151,7 +146,7 @@ namespace PluralKit.Bot {
.Build();
}
public async Task<Embed> CreateMessageInfoEmbed(MessageStore.StoredMessage msg)
public async Task<Embed> CreateMessageInfoEmbed(FullMessage msg)
{
var channel = await _client.GetChannelAsync(msg.Message.Channel) as ITextChannel;
var serverMsg = channel != null ? await channel.GetMessageAsync(msg.Message.Mid) : null;
@@ -193,20 +188,20 @@ namespace PluralKit.Bot {
return eb.Build();
}
public Task<Embed> CreateFrontPercentEmbed(SwitchStore.PerMemberSwitchDuration frontpercent, DateTimeZone tz)
public Task<Embed> CreateFrontPercentEmbed(FrontBreakdown breakdown, DateTimeZone tz)
{
var actualPeriod = frontpercent.RangeEnd - frontpercent.RangeStart;
var actualPeriod = breakdown.RangeEnd - breakdown.RangeStart;
var eb = new EmbedBuilder()
.WithColor(Color.Blue)
.WithFooter($"Since {Formats.ZonedDateTimeFormat.Format(frontpercent.RangeStart.InZone(tz))} ({Formats.DurationFormat.Format(actualPeriod)} ago)");
.WithFooter($"Since {Formats.ZonedDateTimeFormat.Format(breakdown.RangeStart.InZone(tz))} ({Formats.DurationFormat.Format(actualPeriod)} ago)");
var maxEntriesToDisplay = 24; // max 25 fields allowed in embed - reserve 1 for "others"
// We convert to a list of pairs so we can add the no-fronter value
// Dictionary doesn't allow for null keys so we instead have a pair with a null key ;)
var pairs = frontpercent.MemberSwitchDurations.ToList();
if (frontpercent.NoFronterDuration != Duration.Zero)
pairs.Add(new KeyValuePair<PKMember, Duration>(null, frontpercent.NoFronterDuration));
var pairs = breakdown.MemberSwitchDurations.ToList();
if (breakdown.NoFronterDuration != Duration.Zero)
pairs.Add(new KeyValuePair<PKMember, Duration>(null, breakdown.NoFronterDuration));
var membersOrdered = pairs.OrderByDescending(pair => pair.Value).Take(maxEntriesToDisplay).ToList();
foreach (var pair in membersOrdered)

View File

@@ -17,10 +17,7 @@ namespace PluralKit.Bot
private DiscordShardedClient _client;
private IMetrics _metrics;
private SystemStore _systems;
private MemberStore _members;
private SwitchStore _switches;
private MessageStore _messages;
private IDataStore _data;
private WebhookCacheService _webhookCache;
@@ -28,16 +25,13 @@ namespace PluralKit.Bot
private ILogger _logger;
public PeriodicStatCollector(IDiscordClient client, IMetrics metrics, SystemStore systems, MemberStore members, SwitchStore switches, MessageStore messages, ILogger logger, WebhookCacheService webhookCache, DbConnectionCountHolder countHolder)
public PeriodicStatCollector(IDiscordClient client, IMetrics metrics, ILogger logger, WebhookCacheService webhookCache, DbConnectionCountHolder countHolder, IDataStore data)
{
_client = (DiscordShardedClient) client;
_metrics = metrics;
_systems = systems;
_members = members;
_switches = switches;
_messages = messages;
_webhookCache = webhookCache;
_countHolder = countHolder;
_data = data;
_logger = logger.ForContext<PeriodicStatCollector>();
}
@@ -65,10 +59,10 @@ namespace PluralKit.Bot
_metrics.Measure.Gauge.SetValue(BotMetrics.MembersOnline, usersOnline.Count);
// Aggregate DB stats
_metrics.Measure.Gauge.SetValue(CoreMetrics.SystemCount, await _systems.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.MemberCount, await _members.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.SwitchCount, await _switches.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.MessageCount, await _messages.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.SystemCount, await _data.GetTotalSystems());
_metrics.Measure.Gauge.SetValue(CoreMetrics.MemberCount, await _data.GetTotalMembers());
_metrics.Measure.Gauge.SetValue(CoreMetrics.SwitchCount, await _data.GetTotalSwitches());
_metrics.Measure.Gauge.SetValue(CoreMetrics.MessageCount, await _data.GetTotalMessages());
// Process info
var process = Process.GetCurrentProcess();

View File

@@ -23,7 +23,7 @@ namespace PluralKit.Bot
class ProxyService: IDisposable {
private IDiscordClient _client;
private LogChannelService _logChannel;
private MessageStore _messageStorage;
private IDataStore _data;
private EmbedService _embeds;
private ILogger _logger;
private WebhookExecutorService _webhookExecutor;
@@ -31,11 +31,11 @@ namespace PluralKit.Bot
private HttpClient _httpClient;
public ProxyService(IDiscordClient client, LogChannelService logChannel, MessageStore messageStorage, EmbedService embeds, ILogger logger, ProxyCacheService cache, WebhookExecutorService webhookExecutor)
public ProxyService(IDiscordClient client, LogChannelService logChannel, IDataStore data, EmbedService embeds, ILogger logger, ProxyCacheService cache, WebhookExecutorService webhookExecutor)
{
_client = client;
_logChannel = logChannel;
_messageStorage = messageStorage;
_data = data;
_embeds = embeds;
_cache = cache;
_webhookExecutor = webhookExecutor;
@@ -115,7 +115,7 @@ namespace PluralKit.Bot
);
// Store the message in the database, and log it in the log channel (if applicable)
await _messageStorage.Store(message.Author.Id, hookMessageId, message.Channel.Id, message.Id, match.Member);
await _data.AddMessage(message.Author.Id, hookMessageId, message.Channel.Id, message.Id, match.Member);
await _logChannel.LogMessage(match.System, match.Member, hookMessageId, message.Id, message.Channel as IGuildChannel, message.Author, match.InnerText);
// Wait a second or so before deleting the original message
@@ -184,7 +184,7 @@ namespace PluralKit.Bot
if (user == null) return;
// Find the message in the DB
var msg = await _messageStorage.Get(message.Id);
var msg = await _data.GetMessage(message.Id);
if (msg == null) return;
// DM them the message card
@@ -199,7 +199,7 @@ namespace PluralKit.Bot
public async Task HandleMessageDeletionByReaction(Cacheable<IUserMessage, ulong> message, ulong userWhoReacted)
{
// Find the message in the database
var storedMessage = await _messageStorage.Get(message.Id);
var storedMessage = await _data.GetMessage(message.Id);
if (storedMessage == null) return; // (if we can't, that's ok, no worries)
// Make sure it's the actual sender of that message deleting the message
@@ -215,7 +215,7 @@ namespace PluralKit.Bot
}
// Finally, delete it from our database.
await _messageStorage.Delete(message.Id);
await _data.DeleteMessage(message.Id);
}
public async Task HandleMessageDeletedAsync(Cacheable<IMessage, ulong> message, ISocketMessageChannel channel)
@@ -224,13 +224,13 @@ namespace PluralKit.Bot
// Non-webhook messages will never be stored anyway.
// If we're not sure (eg. message outside of cache), delete just to be sure.
if (message.HasValue && !message.Value.Author.IsWebhook) return;
await _messageStorage.Delete(message.Id);
await _data.DeleteMessage(message.Id);
}
public async Task HandleMessageBulkDeleteAsync(IReadOnlyCollection<Cacheable<IMessage, ulong>> messages, IMessageChannel channel)
{
_logger.Information("Bulk deleting {Count} messages in channel {Channel}", messages.Count, channel.Id);
await _messageStorage.BulkDelete(messages.Select(m => m.Id).ToList());
await _data.DeleteMessagesBulk(messages.Select(m => m.Id).ToList());
}
public void Dispose()