-
Notifications
You must be signed in to change notification settings - Fork 21
Database decoupling #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Database decoupling #145
Conversation
d770aa2
to
a59cd45
Compare
260abd7
to
f64561f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for taking the time to do this, this looks fantastic! I've read through most of it and left some quick comments below
src/components/moderation/notify-about-formerly-banned-users.ts
Outdated
Show resolved
Hide resolved
f64561f
to
cc8f805
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much again for doing this, this looks fantastic. Just a few comments
const state = await this.database.component_state.findOne({ id: "starboard" }); | ||
this.delete_emojis = state?.delete_emojis ?? []; | ||
this.ignored_emojis = state?.ignored_emojis ?? []; | ||
this.negative_emojis = state?.negative_emojis ?? []; | ||
this.repost_emojis = state?.repost_emojis ?? []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the component state doesn't exist, should we error or insert it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, I went this route because I thought it'd be slightly simpler and easier to maintain as there's only one place where state is written to the db. I would very much prefer to keep it some way that works out-of-the-box with an empty or only partially initialized db though, so erroring is imo not a great option.
import { Wheatley } from "../wheatley.js"; | ||
import { EarlyReplyMode, TextBasedCommandBuilder } from "../command-abstractions/text-based-command-builder.js"; | ||
import { TextBasedCommand } from "../command-abstractions/text-based-command.js"; | ||
import { unwrap } from "../../../utils/misc.js"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should starboard stuff be in the tccpp modules? Might GP want that some day?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say we can deal with making it a proper core component when we get there. In its current form, it is tied to the TCCPP channel structure, so I thought easier to just keep it in the tccpp module for now.
modmail_id: 1, | ||
}, | ||
}, | ||
{ upsert: true, returnDocument: "after" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we might want "before"
here for current modmail id logic but that might behave weirdly if the upsert is something you'd like to rely on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's actually what I initially did, but that then introduces the need to handle the case of the call returning null
, so this turned out to be simpler. Either way would work though, it's just an additional check.
|
||
type PurgableChannel = Exclude<Discord.TextBasedChannel, Discord.DMChannel | Discord.PartialDMChannel>; | ||
type PurgableMessages = Discord.Collection<string, Discord.Message> | string[]; | ||
type PurgeWork = [PurgableChannel, Iterable<PurgableMessages> | AsyncGenerator<PurgableMessages>]; | ||
|
||
export type message_database_entry = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am concerned with this falling out of line with the more complete definition, unless that's what you were asking about asserting the other day
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's precisely why I was asking about that thing the other day. I assume you saw what I did in the other place to take care of this?
src/wheatley.ts
Outdated
@@ -240,7 +236,7 @@ export class Wheatley { | |||
|
|||
private command_handler: CommandHandler; | |||
|
|||
database: WheatleyDatabaseProxy; | |||
database: WheatleyDatabase; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be WheatleyDatabase | null
since it's conditionally set later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I also thought that. Problem is that this then creates the necessity to handle the case of the database being null
in literally every place that does anything with the database. I assume that's why it wasn't WheatleyDatabaseProxy | null
so far either? I guess we just unwrap(this.wheatley.database)
since we currently don't really have a good way for components to fail to load in case the bot config isn't agreeable to them? Ideally, we would probably have an in-memory database mockup or smth that's used as a fallback?
src/wheatley.ts
Outdated
|
||
const bot_singleton = await proxy.wheatley.findOne({ id: "main" }); | ||
if (bot_singleton) { | ||
M.log("migrating database…"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very minor:
M.log("migrating database…"); | |
M.log("migrating database..."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can change, but I thought we're already using UTF-8 in other places so might as well 😆
cc8f805
to
792b020
Compare
792b020
to
274901a
Compare
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Another step towards untethering Wheatley from TCCPP by refactoring the hardcoded database structures into something more modular:
component_state
collection where each component can keep its own state document with a separate id.case_number
now represent the current latest id instead of the id for the next entry. This was done so we can rely on upserts and the fallback behavior of database operators to automatically create entries that do not exist.modmail.ts
intomoderation/
.migrade_db()
function during startup automatically migrates an old-format db with bot singleton to the newcomponent_state
format.wheatley
collection is left in place to avoid data loss.