-
Notifications
You must be signed in to change notification settings - Fork 117
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
Conversation
@@ -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"}); |
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.
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
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.
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: [], | |||
}, | |||
{ |
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.
❤️
…nique-client-ids-2024-04
Note that the index will need to be added to the migration now that #9219 has been merged |
It's now throwing an error when creating the index in the migration due to not being able to do |
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); |
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 was not being awaited before, I'm not sure what the behaviour would have been wrt what happens when the transaction closes
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.
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.
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.
It's because the type was any
before, so no need to change anything with eslint
efd9ffd
to
59ae397
Compare
57d9cb4
to
2f0b1b7
Compare
97f6d97
to
f752085
Compare
b4dd610
to
5ca526e
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.
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"); |
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.
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) { |
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.
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); |
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.
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.
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 constraintCreating 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