-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
refactor(server): use kysely #12857
refactor(server): use kysely #12857
Conversation
Will this fix #11868? |
Yup. |
const duplicates = await this.assetRepository.getDuplicates(auth.user.id); | ||
return duplicates.map(({ duplicateId, assets }) => ({ | ||
duplicateId, | ||
assets: assets.map((asset) => mapAsset(asset, { auth })), |
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.
why did you remove stacking?
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 don't think it makes sense for how duplicate detection works right now. It won't detect the whole stack as being a duplicate, just particular members of that stack if they're similar enough. The primary asset could be a duplicate, but others might not be and vice versa. This could be addressed in a separate PR, though.
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'm not against removing it, but I think it does make sense for those types of decisions to be transparently made, which most likely means happening in a separate PR.
83799aa
to
6639a22
Compare
92b0e58
to
2df635f
Compare
c6ee910
to
030cab8
Compare
Nice! Any changes here that would affect people using external Postgres? I don’t see any new extensions etc. |
I don't think so. It's an internal change |
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.
Some questions about the migration. What are the steps we need to do after this PR get merged? Would you like to lay out the TODO list for the team?
@@ -97,10 +97,19 @@ const mapStack = (entity: AssetEntity) => { | |||
return { | |||
id: entity.stack.id, | |||
primaryAssetId: entity.stack.primaryAssetId, | |||
assetCount: entity.stack.assetCount ?? entity.stack.assets.length, | |||
assetCount: entity.stack.assetCount ?? entity.stack.assets.length + 1, |
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.
Why does it need to append 1 here?
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 is from a while ago. I think it was because entity.stack.assetCount
includes the primary asset, but entity.stack.assets.length
does not.
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.
Is this related to the kysely change?
types: { | ||
date: { | ||
to: 1184, | ||
from: [1082, 1114, 1184], |
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.
What do these numbers mean?
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.
They're Postgres data type IDs.
server/src/db.d.ts
Outdated
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.
How does the content in this file get generated? Can we provide some developer documentation for this?
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 uses kysely-codegen
. I could have sworn I added an npm run
command for this, but maybe it got lost in a rebase at some point. I can add docs for 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.
Not done yet, so just my state of today
@@ -97,10 +97,19 @@ const mapStack = (entity: AssetEntity) => { | |||
return { | |||
id: entity.stack.id, | |||
primaryAssetId: entity.stack.primaryAssetId, | |||
assetCount: entity.stack.assetCount ?? entity.stack.assets.length, | |||
assetCount: entity.stack.assetCount ?? entity.stack.assets.length + 1, |
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.
Was that just a random bug you found along the way?
@@ -19,7 +19,8 @@ | |||
"preserveWatchOutput": true, | |||
"baseUrl": "./", | |||
"jsx": "react", | |||
"types": ["vitest/globals"] | |||
"types": ["vitest/globals"], | |||
"noErrorTruncation": 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.
What is this for?
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 Kysely types can be pretty complex, so this tells VS Code to show more of the type when you hover over something.
server/src/utils/database.ts
Outdated
builder.andWhere(`exifInfo.${key} = :${key}`, { [key]: value }); | ||
} | ||
export const UPSERT_COLUMNS = {} as { [T in keyof DB]: { [K in keyof DB[T]]: RawBuilder<unknown> } }; | ||
/** Any repository that upserts to a table using `mapUpsertColumns` should call this method in its constructor with that table. */ |
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 you help me understand the purpose of this mechanism?
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.
When an upsert is done, every field that's going to be updated has to be part of the query as excluded.{field}
. We precompute the excluded.*
for a table so mapUpsertColumns
can reference this instead of recomputing it on each upsert.
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 you help giving an example to demonstrate the idea?
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 you have a table with id
, path
, type
and perform an update on path
and type
, mapUpsertColumns
will return an object { path: sql'excluded.${sql.ref('path')}', type: sql'excluded.${sql.ref('type')}' }
. It will exclude id
from that object because it's in the conflictKeys
. If you updated only path
, then type
would not be in the object either.
I just performed a functional testing run.
|
Hi Mert, the latest update causes the web timeline to be unable to load |
I haven't been able to reproduce this. |
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
Description
This PR transitions the asset, search and view repositories from TypeORM to Kysely. The goals of this change include type safety—including for complex queries—improved performance, more transparent behavior and better code composability. Other repositories as well as dev tooling will be migrated in later PRs to limit the scope of this one.
Notes:
bytea
types are returned as hex-encoded strings in the former and asBuffer
in the latter. Timestamps likewise end with+00:00
in JSON and.000Z
without.+00:00
is more accurate if anything, but the inconsistency is a bit annoying.Testing
Over the course of working on this branch, I've tested almost everything the web app can do at one point or another. But there may be regressions since testing certain functionality or subtle issues that I haven't noticed, and I haven't tested it with the mobile app.