Skip to content

Add postgres interpreter for UserStore#4951

Open
akshaymankar wants to merge 21 commits into
developfrom
user-pg-migration
Open

Add postgres interpreter for UserStore#4951
akshaymankar wants to merge 21 commits into
developfrom
user-pg-migration

Conversation

@akshaymankar
Copy link
Copy Markdown
Member

@akshaymankar akshaymankar commented Jan 13, 2026

https://wearezeta.atlassian.net/browse/WPB-22747

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

@akshaymankar akshaymankar changed the title WIP Add postgres interpreter for UserStore Jan 13, 2026
@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Jan 13, 2026
@akshaymankar akshaymankar force-pushed the user-pg-migration branch 8 times, most recently from 7735235 to edefb6e Compare January 20, 2026 16:01
@akshaymankar akshaymankar force-pushed the user-pg-migration branch 3 times, most recently from 58edc5f to 272456f Compare January 26, 2026 14:24
@akshaymankar akshaymankar force-pushed the user-pg-migration branch 8 times, most recently from b5cd210 to 68b2d01 Compare March 2, 2026 09:13
@akshaymankar akshaymankar force-pushed the user-pg-migration branch 9 times, most recently from 68ef4d0 to b2719f5 Compare March 5, 2026 13:20
Comment on lines +275 to +276
-- If a user is found in deletedUsers and normal users, prefer the deleted
-- user.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isn't this a data inconsistency that should be logged?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good idea, logging this at warn level now.

lookupHandleImpl :: (PGConstraints r) => Handle -> Sem r (Maybe UserId)
lookupHandleImpl h = runStatement h selectUserIdByHandleStatement

selectUserIdByHandleStatement :: Hasql.Statement Handle (Maybe UserId)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You may reduce the scope of this. Putting helper functions in where blocks seems to be your pattern 😄

@@ -0,0 +1,64 @@
CREATE TABLE wire_user (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You're using the name wire_user instead of user by intention, right? Probably to avoid future name clashes?

Copy link
Copy Markdown
Member Author

@akshaymankar akshaymankar May 19, 2026

Choose a reason for hiding this comment

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

In postgresql user is a keyword, and so needs to be quoted. This makes writing queries very error prone. So I decided to use a different name.

select :: Hasql.Statement (UserId) (Maybe (Maybe Password, Maybe AccountStatus))
select =
dimapPG
[maybeStatement|SELECT password :: bytea?, account_status :: integer? FROM wire_user WHERE id = $1 :: uuid|]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In wire_user the password is defined as password text. I hope this won't cause troubles when read with bytea?

Copy link
Copy Markdown
Member Author

@akshaymankar akshaymankar May 19, 2026

Choose a reason for hiding this comment

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

Whoops, its a mistake. Fixed now.

Comment thread libs/wire-subsystems/src/Wire/UserStore/Postgres.hs
Comment on lines +430 to +431
language = COALESCE($6 :: text?, language),
country = COALESCE($7 :: text?, country),
Copy link
Copy Markdown
Contributor

@supersven supersven May 13, 2026

Choose a reason for hiding this comment

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

Is this equivalent to the Cassandra behaviour?

userLocaleUpdate :: PrepQuery W (Language, Maybe Country, UserId) ()
userLocaleUpdate = "UPDATE user SET language = ?, country = ? WHERE id = ?"

In case of a pre-existing value for country, don't we keep it here? E.g. what will happen if I switch from en_EN to de?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a very good catch! I'll add a test first ❤️

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

WHERE id = $1 :: uuid
|]

getIndexUsersPaginatedImpl :: (PGConstraints r) => Int32 -> Maybe UserId -> Sem r (PageWithState UserId IndexUser)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If I'm getting this correctly, this function is also used to finally create tombstones in ElasticSearch (finally in indexUserToDoc).

But, we do not query deleted_user here. Is this correct?

Transaction.statement userRow insertUser
Transaction.statement new.id deleteAssetsStatement
Transaction.statement (mkAssetRows new.id new.assets) insertAssetsStatement
for_ mbConv $ \(convId, mTeamId) -> do
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

createUserImpl of Cassandra also has the Maybe new.service in the equation. Should we adjust this guard?

[resultlessStatement|UPDATE wire_user SET searchable = $2 :: boolean WHERE id = $1 :: uuid|]

deleteServiceUserImpl :: (PGConstraints r) => ProviderId -> ServiceId -> BotId -> Sem r ()
deleteServiceUserImpl _ _ bid =
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These unused parameters may deserve a FUTUREWORK: for the time after Cassandra migration.

Copy link
Copy Markdown
Contributor

@supersven supersven left a comment

Choose a reason for hiding this comment

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

This is looking mostly looking great, however in my opinion:

  • The questions regarding potentially slightly different behaviour of Postgresql vs. Cassandra queries should be sorted out.
  • It would probably be good to have a third pair of eyeballs check the queries (comparing them to the Cassandra implementation).

As I'll be on vacation, please feel free to resolve my comments if you think they've been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants