From 8800f5e62fa1c9f8a0744215db7fd3e7b7d47554 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Thu, 15 Jan 2026 09:36:53 +0000 Subject: [PATCH] core: correctly handle errors in withLocalDisplayName for postgres (rollback to savepoint) (#6577) --- src/Simplex/Chat/Store/Shared.hs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index 15ec3ec49d..c9dc87b5fa 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -581,7 +581,7 @@ withLocalDisplayName db userId displayName action = getLdnSuffix >>= (`tryCreate tryCreateName ldnSuffix attempts = do currentTs <- getCurrentTime let ldn = displayName <> (if ldnSuffix == 0 then "" else T.pack $ '_' : show ldnSuffix) - E.try (insertName ldn currentTs) >>= \case + withSavepoint db "ldn_insert" (insertName ldn currentTs) >>= \case Right () -> action ldn Left e | constraintError e -> tryCreateName (ldnSuffix + 1) (attempts - 1) @@ -597,6 +597,25 @@ withLocalDisplayName db userId displayName action = getLdnSuffix >>= (`tryCreate |] (ldn, displayName, ldnSuffix, userId, ts, ts) +-- Execute an action within a savepoint (PostgreSQL only). +-- On success, releases the savepoint. On error, rolls back to the savepoint +-- to restore the transaction to a usable state before returning the error. +withSavepoint :: DB.Connection -> Query -> IO a -> IO (Either SQLError a) +withSavepoint db name action = +#if defined(dbPostgres) + do + DB.execute_ db $ "SAVEPOINT " <> name + E.try action >>= \case + Right r -> do + DB.execute_ db $ "RELEASE SAVEPOINT " <> name + pure $ Right r + Left e -> do + DB.execute_ db $ "ROLLBACK TO SAVEPOINT " <> name + pure $ Left e +#else + E.try action +#endif + createWithRandomId :: forall a. TVar ChaChaDRG -> (ByteString -> IO a) -> ExceptT StoreError IO a createWithRandomId = createWithRandomBytes 12