Skip to content

WPB-17408 inconsistent database: unparseable emails #4578

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

Merged
merged 10 commits into from
May 20, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WIP
  • Loading branch information
jschaul committed May 14, 2025
commit 2eebf2600f3d9b00d07feee7c72ccd0daef0ae79
33 changes: 28 additions & 5 deletions tools/db/inconsistencies/src/EmailUnparseableUsers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,36 @@ import System.Logger qualified as Log
import UnliftIO (pooledMapConcurrentlyN)
import Wire.API.Team.Permission
import Wire.API.User (AccountStatus)
import Wire.API.User.EmailAddress

-- Problem statement:
-- Upon brig re-index, we look up the user table and create a
-- IndexUser which contains a field of type EmailAddress
-- libs/wire-subsystems/src/Wire/UserStore/IndexUser.hs
--
-- Parsing this fails for some cases, most likely during the conversion of the cassandra type to EmailAddress.
--
-- In August 2024 emails were refactored in https://github.com/wireapp/wire-server/pull/4206. Possibly existing emails in the database were not checked whether they conform to the new library.
--
-- email parsing from cql/bytestring is done in
-- libs/wire-api/src/Wire/API/User/EmailAddress.hs
--
--
runCommand :: Logger -> ClientState -> FilePath -> IO ()
runCommand l brig inconsistenciesFile = do
runResourceT $ undefined

runResourceT $
runConduit $
zipSources
(C.sourceList [(1 :: Int32) ..])
(transPipe (runClient brig) getUsers)
.| C.mapM
( \(i, userDetails) -> do
Log.info l (Log.field "userIds" (show ((i - 1) * pageSize + fromIntegral (length userDetails))))
pure $ mapMaybe toDoSomething userDetails
)
.| C.mapM (liftIO . pooledMapConcurrentlyN 48 (checkUser brig))
.| C.map ((<> "\n") . BS.intercalate "\n" . map (BS.toStrict . Aeson.encode) . catMaybes)
.| sinkFile inconsistenciesFile


pageSize :: Int32
Expand All @@ -33,8 +58,7 @@ getUsers :: ConduitM () [UserDetailsRow] Client ()
getUsers = paginateC cql (paramsP LocalQuorum () pageSize) x5
where
cql :: PrepQuery R () UserDetailsRow
cql = "SELECT id, activated, status, writetime(status), team, writetime(team) from user"

cql = "SELECT id, activated, status, writetime(status), email from user"

data WithWritetime a = WithWritetime
{ value :: a,
Expand All @@ -44,7 +68,6 @@ data WithWritetime a = WithWritetime

instance (ToJSON a) => ToJSON (WithWritetime a)


data UserDetails = UserDetails
{ id_ :: UserId,
activated :: Maybe Bool,
Expand Down