WPB-22969: migrate password-reset to PostGreSQL - #5412
Conversation
0aff1b4 to
794cf34
Compare
7c2a589 to
2c147ec
Compare
2c147ec to
0c9e296
Compare
0c9e296 to
b4ae5b7
Compare
| runCodensity (startDynamicBackend backend (conf "migration-to-postgresql" True)) $ \_ -> | ||
| waitForMigration domain counterName |
There was a problem hiding this comment.
We could also check code here.
| -- | Drives the password-reset store through the full cutover lifecycle | ||
| -- (cassandra -> migration-to-postgresql -> postgresql). A reset code written to | ||
| -- Cassandra before migration must be served from Postgres after the cutover and | ||
| -- still complete the reset, proving the row was backfilled. |
There was a problem hiding this comment.
I think we should try to do a write in in every step and try to read it in the next step again. This way we're also testing the writes from all 3 interpreters.
There was a problem hiding this comment.
Also we need some tests to make sure edge cases of TTL are dealt with correctly.
| CREATE TABLE IF NOT EXISTS password_reset ( | ||
| key text PRIMARY KEY, | ||
| code text NOT NULL, | ||
| "user" uuid NOT NULL, |
There was a problem hiding this comment.
| "user" uuid NOT NULL, | |
| user_id uuid NOT NULL, |
This way it is easier to detect issues in queries. I'm trying to avoid anything called "user" in postgresql because they don't error until parsing the results.
| -- | A 6-digit, zero-padded code (mirrors the Cassandra interpreter). | ||
| genPhoneCode :: (Member (Embed IO) r) => Sem r PasswordResetCode | ||
| genPhoneCode = | ||
| PasswordResetCode . unsafeFromText . pack . printf "%06d" | ||
| <$> embed @IO (randIntegerZeroToNMinusOne 1000000) |
There was a problem hiding this comment.
This is an unused function, feel free to delete it.
f2f4c17 to
518acee
Compare
|
Addressed the review feedback (rebased onto current develop, squashed to one commit
Known deviation worth a look: the backfill worker upserts rows without the per-row exclusive migration lock that the user/domainRegistration/teamFeatures/conversationCodes migrations use, so a row consumed (reset completed / invalidated) between the worker's Cassandra read and Postgres write could be re-inserted with a fresh expiry. Narrow window, but it deviates from the sibling migrations' locking pattern — happy to add |
akshaymankar
left a comment
There was a problem hiding this comment.
genPhoneCode: removed from the Postgres module's export list (kept as a non-exported local so GeneratePhoneCode stays total); the dual-write interpreter now delegates phone-code generation to the Cassandra interpreter. Note the whole phone-reset path is dead (no production callsite, resetPasswordImpl rejects phone identity) — removing it entirely (effect constructor + both copies) could be a follow-up cutover if preferred.
I meant we can delete it from the effect itself since there are no call sites.
But it was a nit anyway, so its ok if you merge this without.
| initiateReset domain >>= \u3' -> do | ||
| waitForMigration domain counterName | ||
| pure u3' |
There was a problem hiding this comment.
Unless I'm missing something, why does the waiting need to be explicitly bound? This is the same right?:
| initiateReset domain >>= \u3' -> do | |
| waitForMigration domain counterName | |
| pure u3' | |
| u3 <- initiateReset domain | |
| waitForMigration domain counterName | |
| pure u3 |
9750ae8 to
40f3a18
Compare
https://wearezeta.atlassian.net/browse/WPB-22969
Checklist
changelog.d