Skip to content
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

Make clientId field in ClientIds non-nullable and unique #9209

Merged
merged 13 commits into from
May 16, 2024

Conversation

Will-Howard
Copy link
Collaborator

@Will-Howard Will-Howard commented May 1, 2024

Both of these constraints are already satisfied on the EAF databases, @jimrandomh @b0b3rt could you check they are true on LW before merging this.

It should be safe to merge if the constraints aren't satisfied, the migration would fail the deployment if there are nulls in the db, and the unique constraint isn't required in the code so would just silently fail. I'm planning to add a query with an ON CONFLICT in a separate PR which will fail without the unique constraint

Creating the unique index takes at least 45 mins on dev (I gave up timing it after that point) so I would strongly recommend running this on prod before deploying

[Update after fixing the concurrently-in-migration problem: I've added a way to access the db client outside the current transaction, which allows us to run CONCURRENTLY queries in migrations, but comes at the cost of breaking atomicity for those queries]

┆Issue is synchronized with this Asana task by Unito

@Will-Howard Will-Howard requested a review from a team as a code owner May 1, 2024 14:30
@Will-Howard Will-Howard requested review from oetherington and removed request for a team May 1, 2024 14:30
@Will-Howard Will-Howard marked this pull request as draft May 1, 2024 14:30
@@ -20,7 +20,7 @@ addUniversalFields({
createdAtOptions: {canRead: ['admins']},
});

ensureIndex(ClientIds, {clientId: 1});
ensureIndex(ClientIds, {clientId: 1}, {unique: true, concurrently: true, name: "idx_ClientIds_clientId_unique"});
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for the explicit name is that the generated name doesn't include whether the index is unique or not, so it says the index already exists. Ideally we would change CreateIndexQuery so it does include this but making this backwards compatible (i.e. not duplicating all existing unique indexes) would be a pain so I haven't done it for this PR

@Will-Howard Will-Howard marked this pull request as ready for review May 2, 2024 11:03
Copy link
Collaborator

@oetherington oetherington left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks good to me, provided LW are happy

@@ -33,5 +33,11 @@ describe("CreateIndexQuery", () => {
expectedSql: 'CREATE INDEX IF NOT EXISTS "idx_TestCollection_b_ci" ON "TestCollection" USING btree ( LOWER("b") )',
expectedArgs: [],
},
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@oetherington
Copy link
Collaborator

Note that the index will need to be added to the migration now that #9219 has been merged

@Will-Howard
Copy link
Collaborator Author

Will-Howard commented May 9, 2024

It's now throwing an error when creating the index in the migration due to not being able to do CONCURRENTLY inside a transaction, I'm planning to fix it by passing a runAfterTransaction function to the migration. [Edit: I'm actually going to split this into two PRs, using this as the WIP branch for now]

@Will-Howard Will-Howard marked this pull request as draft May 9, 2024 10:51
@oetherington
Copy link
Collaborator

Sounds reasonable. I'm planning on rewriting a lot of the makemigrations script later today to account for the problems Robert found and it'll also fix the issue with create concurrent indexes in migrations. Feel free to do a quick fix here if you want, but I probably wouldn't bother spending much time on it (you could even just add a quick manual migration if it's easier).

@@ -174,7 +175,7 @@ export const updateIndexes = async <N extends CollectionNameString>(
collection: CollectionBase<N>,
): Promise<void> => {
for (const index of expectedIndexes[collection.collectionName] ?? []) {
collection._ensureIndex(index.key, index);
await collection._ensureIndex(index.key, index);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not being awaited before, I'm not sure what the behaviour would have been wrt what happens when the transaction closes

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh - it's weird that eslint din't complain. Maybe it doesn't run on this file because migrations aren't actually ever imported - umzug does some magic to read the files. If that's the case we can probably add the directory to the eslint config directly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because the type was any before, so no need to change anything with eslint

@Will-Howard Will-Howard marked this pull request as ready for review May 10, 2024 08:39
@Will-Howard Will-Howard marked this pull request as draft May 10, 2024 13:34
@Will-Howard Will-Howard force-pushed the wh-unique-client-ids-2024-04 branch 3 times, most recently from efd9ffd to 59ae397 Compare May 10, 2024 14:05
@Will-Howard Will-Howard force-pushed the wh-unique-client-ids-2024-04 branch from 57d9cb4 to 2f0b1b7 Compare May 10, 2024 15:50
@Will-Howard Will-Howard force-pushed the wh-unique-client-ids-2024-04 branch from 97f6d97 to f752085 Compare May 13, 2024 14:22
@Will-Howard Will-Howard force-pushed the wh-unique-client-ids-2024-04 branch from b4dd610 to 5ca526e Compare May 13, 2024 14:36
@Will-Howard Will-Howard marked this pull request as ready for review May 13, 2024 14:45
Copy link
Collaborator

@oetherington oetherington left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thanks - there's some annoying fidly stuff in there!

@@ -160,8 +160,8 @@ CREATE TABLE "ClientIds" (
-- Index "idx_ClientIds_schemaVersion" ON "ClientIds", hash: ec6b84a52c243854cac9404c21e54f56
CREATE INDEX IF NOT EXISTS "idx_ClientIds_schemaVersion" ON "ClientIds" USING btree ("schemaVersion");

-- Index "idx_ClientIds_clientId" ON "ClientIds", hash: b8febff6f23392c9ca4946ad2e3d7710
CREATE INDEX IF NOT EXISTS "idx_ClientIds_clientId" ON "ClientIds" USING btree ("clientId");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small note that we should probably make a follow up PR once that has been deployed to all sites that removes the old index

@@ -19,14 +19,15 @@ import { StringType } from "./Type";
class CreateIndexQuery<T extends DbObject> extends Query<T> {
private isUnique: boolean;

constructor(table: Table<T>, index: TableIndex<T>, ifNotExists = true) {
constructor(table: Table<T>, index: TableIndex<T>, ifNotExists = true, allowConcurrent=true) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than having multiple optional booleans, I think it'd be cleaner to have an object with named options

@@ -174,7 +175,7 @@ export const updateIndexes = async <N extends CollectionNameString>(
collection: CollectionBase<N>,
): Promise<void> => {
for (const index of expectedIndexes[collection.collectionName] ?? []) {
collection._ensureIndex(index.key, index);
await collection._ensureIndex(index.key, index);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh - it's weird that eslint din't complain. Maybe it doesn't run on this file because migrations aren't actually ever imported - umzug does some magic to read the files. If that's the case we can probably add the directory to the eslint config directly.

@Will-Howard Will-Howard merged commit be3b543 into master May 16, 2024
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants