From c971add13727c3246b1ddbd4cc0a4ebb71f2e2f1 Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 27 Feb 2025 16:17:26 -0500 Subject: [PATCH] a lot of my problems are who owns what --- ConsoleService.cs | 11 +- .../DiscordInterface/DiscordInterface.cs | 48 ++++-- Rememberer.cs | 160 +++++++++++++++--- devuitls.sh | 2 +- 4 files changed, 172 insertions(+), 49 deletions(-) diff --git a/ConsoleService.cs b/ConsoleService.cs index a54c815..1a568a3 100644 --- a/ConsoleService.cs +++ b/ConsoleService.cs @@ -5,10 +5,10 @@ namespace vassago using vassago.Models; using vassago.TwitchInterface; using vassago.ProtocolInterfaces.DiscordInterface; + using System.Runtime.CompilerServices; internal class ConsoleService : IHostedService { - public ConsoleService(IConfiguration aspConfig) { Shared.DBConnectionString = aspConfig["DBConnectionString"]; @@ -22,14 +22,15 @@ namespace vassago public async Task StartAsync(CancellationToken cancellationToken) { + var initTasks = new List(); var dbc = new ChattingContext(); - await dbc.Database.MigrateAsync(); + await dbc.Database.MigrateAsync(cancellationToken); if (DiscordTokens?.Any() ?? false) foreach (var dt in DiscordTokens) { var d = new DiscordInterface(); - await d.Init(dt); + initTasks.Add(d.Init(dt)); ProtocolInterfaces.ProtocolList.discords.Add(d); } @@ -37,9 +38,11 @@ namespace vassago foreach (var tc in TwitchConfigs) { var t = new TwitchInterface.TwitchInterface(); - await t.Init(tc); + initTasks.Add(t.Init(tc)); ProtocolInterfaces.ProtocolList.twitchs.Add(t); } + + Task.WaitAll(initTasks, cancellationToken); } public Task StopAsync(CancellationToken cancellationToken) diff --git a/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs b/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs index 875b286..efaff3f 100644 --- a/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs +++ b/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs @@ -70,7 +70,8 @@ public class DiscordInterface protocolAsChannel.DisplayName = "discord (itself)"; protocolAsChannel.SendMessage = (t) => { throw new InvalidOperationException($"protocol isn't a real channel, cannot accept text"); }; protocolAsChannel.SendFile = (f, t) => { throw new InvalidOperationException($"protocol isn't a real channel, cannot send file"); }; - Rememberer.RememberChannel(protocolAsChannel); + protocolAsChannel= Rememberer.RememberChannel(protocolAsChannel); + Console.WriteLine($"protocol as channel addeed; {protocolAsChannel}"); } finally { @@ -110,11 +111,20 @@ public class DiscordInterface } } - private void SelfConnected() + private async Task SelfConnected() { - var selfAccount = UpsertAccount(client.CurrentUser, protocolAsChannel); - selfAccount.DisplayName = client.CurrentUser.Username; - Behaver.Instance.MarkSelf(selfAccount); + await discordChannelSetup.WaitAsync(); + + try + { + var selfAccount = UpsertAccount(client.CurrentUser, protocolAsChannel); + selfAccount.DisplayName = client.CurrentUser.Username; + Behaver.Instance.MarkSelf(selfAccount); + } + finally + { + discordChannelSetup.Release(); + } } private async Task MessageReceived(SocketMessage messageParam) @@ -195,7 +205,6 @@ public class DiscordInterface Protocol = PROTOCOL }; - if (dMessage.Attachments?.Count > 0) { m.Attachments = []; @@ -209,6 +218,7 @@ public class DiscordInterface m.Timestamp = dMessage.EditedTimestamp ?? dMessage.CreatedAt; m.Channel = UpsertChannel(dMessage.Channel); m.Author = UpsertAccount(dMessage.Author, m.Channel); + Console.WriteLine($"received message; author: {m.Author.DisplayName}, {m.Author.Id}"); if (dMessage.Channel is IGuildChannel) { m.Author.DisplayName = (dMessage.Author as IGuildUser).DisplayName;//discord forgot how display names work. @@ -218,7 +228,7 @@ public class DiscordInterface m.Reply = (t) => { return dMessage.ReplyAsync(t); }; m.React = (e) => { return AttemptReact(dMessage, e); }; - Rememberer.RememberChannel(m.Channel); + Rememberer.RememberMessage(m); return m; } internal Channel UpsertChannel(IMessageChannel channel) @@ -237,7 +247,8 @@ public class DiscordInterface c.Protocol = PROTOCOL; if (channel is IGuildChannel) { - UpsertChannel((channel as IGuildChannel).Guild); + Console.WriteLine($"{channel.Name} is a guild channel. So i'm going to upsert the guild, {(channel as IGuildChannel).Guild}"); + c.ParentChannel = UpsertChannel((channel as IGuildChannel).Guild); } else if (channel is IPrivateChannel) { @@ -255,12 +266,15 @@ public class DiscordInterface c.DisplayName = "DM: " + (channel as IPrivateChannel).Recipients?.FirstOrDefault(u => u.Id != client.CurrentUser.Id).Username; break; } - Rememberer.RememberChannel(c); Channel parentChannel = null; if (channel is IGuildChannel) { parentChannel = Rememberer.SearchChannel(c => c.ExternalId == (channel as IGuildChannel).Guild.Id.ToString() && c.Protocol == PROTOCOL); + if(parentChannel is null) + { + Console.Error.WriteLine("why am I still null?"); + } } else if (channel is IPrivateChannel) { @@ -273,11 +287,11 @@ public class DiscordInterface } parentChannel.SubChannels ??= []; parentChannel.SubChannels.Add(c); - Rememberer.RememberChannel(parentChannel); c.SendMessage = (t) => { return channel.SendMessageAsync(t); }; c.SendFile = (f, t) => { return channel.SendFileAsync(f, t); }; - return c; + + return Rememberer.RememberChannel(c); } internal Channel UpsertChannel(IGuild channel) { @@ -285,7 +299,6 @@ public class DiscordInterface if (c == null) { c = new Channel(); - Rememberer.RememberChannel(c); } c.DisplayName = channel.Name; @@ -299,8 +312,8 @@ public class DiscordInterface c.SendMessage = (t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; cannot accept text"); }; c.SendFile = (f, t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; send file"); }; - Rememberer.RememberChannel(c); - return c; + + return Rememberer.RememberChannel(c); } internal static Account UpsertAccount(IUser user, Channel inChannel) { @@ -314,10 +327,9 @@ public class DiscordInterface acc.SeenInChannel = inChannel; acc.IsUser = Rememberer.SearchUser(u => u.Accounts.Any(a => a.ExternalId == acc.ExternalId && a.Protocol == acc.Protocol)); - //db.Users.FirstOrDefault(u => u.Accounts.Any(a => a.ExternalId == acc.ExternalId && a.Protocol == acc.Protocol)); - - acc.IsUser ??= new User() { Accounts = [ acc ] }; - + acc.IsUser ??= new User() { Accounts = [ acc ] }; + inChannel.Users ??= []; + inChannel.Users.Add(acc); Rememberer.RememberAccount(acc); return acc; } diff --git a/Rememberer.cs b/Rememberer.cs index 80f3f07..920e8ac 100644 --- a/Rememberer.cs +++ b/Rememberer.cs @@ -5,6 +5,7 @@ using vassago.Models; public static class Rememberer { + private static readonly SemaphoreSlim dbAccessSemaphore = new(1, 1); public static Account SearchAccount(Expression> predicate) { return (new ChattingContext()).Accounts.FirstOrDefault(predicate); @@ -31,49 +32,156 @@ public static class Rememberer } public static void RememberAccount(Account toRemember) { - var db = new ChattingContext(); - if (toRemember.Id == Guid.Empty) - db.Accounts.Add(toRemember); + dbAccessSemaphore.Wait(); + try + { + var db = new ChattingContext(); + if (toRemember.Id == Guid.Empty) + { + var parentChannel = toRemember.SeenInChannel; + var isUser = toRemember.IsUser; + toRemember.SeenInChannel = null; + toRemember.IsUser = null; + db.Accounts.Add(toRemember); + db.SaveChanges(); - db.SaveChanges(); + toRemember.SeenInChannel = parentChannel; + toRemember.IsUser = isUser; + db.SaveChanges(); + } + else + { + db.SaveChanges(); + } + } + finally + { + dbAccessSemaphore.Release(); + } } public static void RememberAttachment(Attachment toRemember) { - var db = new ChattingContext(); - if (toRemember.Id == Guid.Empty) - db.Attachments.Add(toRemember); - - db.SaveChanges(); + dbAccessSemaphore.Wait(); + try + { + var db = new ChattingContext(); + if (toRemember.Id == Guid.Empty) + { + var msg = toRemember.Message; + toRemember.Message = null; + db.Attachments.Add(toRemember); + db.SaveChanges(); + toRemember.Message = msg; + db.SaveChanges(); + } + else + { + db.SaveChanges(); + } + } + finally + { + dbAccessSemaphore.Release(); + } } - public static void RememberChannel(Channel toRemember) + public static Channel RememberChannel(Channel toRemember) { - var db = new ChattingContext(); - if (toRemember.Id == Guid.Empty) - db.Channels.Add(toRemember); + dbAccessSemaphore.Wait(); + try + { + var db = new ChattingContext(); + if (toRemember.Id == Guid.Empty) + { + var parent = toRemember.ParentChannel; + var subChannesl = toRemember.SubChannels; + var msgs = toRemember.Messages; + var accounts = toRemember.Users; + toRemember.ParentChannel = null; + toRemember.SubChannels = null; + toRemember.Messages = null; + toRemember.Users = null; + db.Channels.Add(toRemember); + db.SaveChanges(); + toRemember.ParentChannel = parent; + toRemember.SubChannels = subChannesl; + toRemember.Messages = msgs; + toRemember.Users = accounts; + db.SaveChanges(); + } - db.SaveChanges(); + db.SaveChanges(); + } + finally + { + dbAccessSemaphore.Release(); + } + return toRemember; } public static void RememberMessage(Message toRemember) { - var db = new ChattingContext(); - if (toRemember.Id == Guid.Empty) + dbAccessSemaphore.Wait(); + try { - db.Messages.Add(toRemember); + var db = new ChattingContext(); + if (toRemember.Id == Guid.Empty) + { + var author = toRemember.Author; + var channel = toRemember.Channel; + var attachments = toRemember.Attachments; + toRemember.Author = null; + toRemember.Channel = null; + toRemember.Attachments = null; + db.Messages.Add(toRemember); + db.SaveChanges(); + toRemember.Author = author; + toRemember.Channel = channel; + toRemember.Attachments = attachments; + db.SaveChanges(); + } + db.SaveChanges(); + } + finally + { + dbAccessSemaphore.Release(); } - db.SaveChanges(); } public static void RememberUser(User toRemember) { - var db = new ChattingContext(); - if (toRemember.Id == Guid.Empty) - db.Users.Add(toRemember); - - db.SaveChanges(); + dbAccessSemaphore.Wait(); + try + { + var db = new ChattingContext(); + if (toRemember.Id == Guid.Empty) + { + var accs = toRemember.Accounts; + toRemember.Accounts = null; + db.Users.Add(toRemember); + db.SaveChanges(); + toRemember.Accounts = accs; + db.SaveChanges(); + } + else + { + db.SaveChanges(); + } + } + finally + { + dbAccessSemaphore.Release(); + } } public static void ForgetUser(User toForget) { - var db = new ChattingContext(); - db.Users.Remove(toForget); - db.SaveChanges(); + dbAccessSemaphore.Wait(); + try + { + var db = new ChattingContext(); + db.Users.Remove(toForget); + db.SaveChanges(); + } + finally + { + dbAccessSemaphore.Release(); + } } } \ No newline at end of file diff --git a/devuitls.sh b/devuitls.sh index 5c603de..d0f1748 100755 --- a/devuitls.sh +++ b/devuitls.sh @@ -26,7 +26,7 @@ case "$1" in "db-fullreset") sudo -u postgres psql -c "drop database ${servicename}_dev;" - sudo -u postgres psql -c "delete user $servicename" + sudo -u postgres psql -c "drop user $servicename" $0 "initial" ;; *)