core: improve queries performance; delay first chat item expiration cycle on start (#2521)
This commit is contained in:
parent
cc75b75d4e
commit
128883b8a3
@ -99,6 +99,7 @@ library
|
|||||||
Simplex.Chat.Migrations.M20230511_reactions
|
Simplex.Chat.Migrations.M20230511_reactions
|
||||||
Simplex.Chat.Migrations.M20230519_item_deleted_ts
|
Simplex.Chat.Migrations.M20230519_item_deleted_ts
|
||||||
Simplex.Chat.Migrations.M20230526_indexes
|
Simplex.Chat.Migrations.M20230526_indexes
|
||||||
|
Simplex.Chat.Migrations.M20230529_indexes
|
||||||
Simplex.Chat.Mobile
|
Simplex.Chat.Mobile
|
||||||
Simplex.Chat.Mobile.WebRTC
|
Simplex.Chat.Mobile.WebRTC
|
||||||
Simplex.Chat.Options
|
Simplex.Chat.Options
|
||||||
|
@ -69,7 +69,7 @@ import Simplex.Messaging.Agent.Client (AgentStatsKey (..), temporaryAgentError)
|
|||||||
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..), createAgentStore, defaultAgentConfig)
|
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..), createAgentStore, defaultAgentConfig)
|
||||||
import Simplex.Messaging.Agent.Lock
|
import Simplex.Messaging.Agent.Lock
|
||||||
import Simplex.Messaging.Agent.Protocol
|
import Simplex.Messaging.Agent.Protocol
|
||||||
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, SQLiteStore (dbNew), execSQL, upMigration)
|
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, SQLiteStore (dbNew), execSQL, upMigration, withTransactionCtx)
|
||||||
import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations
|
import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations
|
||||||
import Simplex.Messaging.Client (defaultNetworkConfig)
|
import Simplex.Messaging.Client (defaultNetworkConfig)
|
||||||
import qualified Simplex.Messaging.Crypto as C
|
import qualified Simplex.Messaging.Crypto as C
|
||||||
@ -222,7 +222,7 @@ cfgServers = \case
|
|||||||
startChatController :: forall m. ChatMonad' m => Bool -> Bool -> Bool -> m (Async ())
|
startChatController :: forall m. ChatMonad' m => Bool -> Bool -> Bool -> m (Async ())
|
||||||
startChatController subConns enableExpireCIs startXFTPWorkers = do
|
startChatController subConns enableExpireCIs startXFTPWorkers = do
|
||||||
asks smpAgent >>= resumeAgentClient
|
asks smpAgent >>= resumeAgentClient
|
||||||
users <- fromRight [] <$> runExceptT (withStore' getUsers)
|
users <- fromRight [] <$> runExceptT (withStoreCtx' (Just "startChatController, getUsers") getUsers)
|
||||||
restoreCalls
|
restoreCalls
|
||||||
s <- asks agentAsync
|
s <- asks agentAsync
|
||||||
readTVarIO s >>= maybe (start s users) (pure . fst)
|
readTVarIO s >>= maybe (start s users) (pure . fst)
|
||||||
@ -254,7 +254,7 @@ startChatController subConns enableExpireCIs startXFTPWorkers = do
|
|||||||
_ -> pure ()
|
_ -> pure ()
|
||||||
startExpireCIs users =
|
startExpireCIs users =
|
||||||
forM_ users $ \user -> do
|
forM_ users $ \user -> do
|
||||||
ttl <- fromRight Nothing <$> runExceptT (withStore' (`getChatItemTTL` user))
|
ttl <- fromRight Nothing <$> runExceptT (withStoreCtx' (Just "startExpireCIs, getChatItemTTL") (`getChatItemTTL` user))
|
||||||
forM_ ttl $ \_ -> do
|
forM_ ttl $ \_ -> do
|
||||||
startExpireCIThread user
|
startExpireCIThread user
|
||||||
setExpireCIFlag user True
|
setExpireCIFlag user True
|
||||||
@ -279,14 +279,14 @@ startFilesToReceive users = do
|
|||||||
|
|
||||||
startReceiveUserFiles :: forall m. ChatMonad m => User -> m ()
|
startReceiveUserFiles :: forall m. ChatMonad m => User -> m ()
|
||||||
startReceiveUserFiles user = do
|
startReceiveUserFiles user = do
|
||||||
filesToReceive <- withStore' (`getRcvFilesToReceive` user)
|
filesToReceive <- withStoreCtx' (Just "startReceiveUserFiles, getRcvFilesToReceive") (`getRcvFilesToReceive` user)
|
||||||
forM_ filesToReceive $ \ft ->
|
forM_ filesToReceive $ \ft ->
|
||||||
flip catchError (toView . CRChatError (Just user)) $
|
flip catchError (toView . CRChatError (Just user)) $
|
||||||
toView =<< receiveFile' user ft Nothing Nothing
|
toView =<< receiveFile' user ft Nothing Nothing
|
||||||
|
|
||||||
restoreCalls :: ChatMonad' m => m ()
|
restoreCalls :: ChatMonad' m => m ()
|
||||||
restoreCalls = do
|
restoreCalls = do
|
||||||
savedCalls <- fromRight [] <$> runExceptT (withStore' $ \db -> getCalls db)
|
savedCalls <- fromRight [] <$> runExceptT (withStoreCtx' (Just "restoreCalls, getCalls") $ \db -> getCalls db)
|
||||||
let callsMap = M.fromList $ map (\call@Call {contactId} -> (contactId, call)) savedCalls
|
let callsMap = M.fromList $ map (\call@Call {contactId} -> (contactId, call)) savedCalls
|
||||||
calls <- asks currentCalls
|
calls <- asks currentCalls
|
||||||
atomically $ writeTVar calls callsMap
|
atomically $ writeTVar calls callsMap
|
||||||
@ -363,11 +363,11 @@ processChatCommand = \case
|
|||||||
withStore $ \db -> overwriteProtocolServers db user servers
|
withStore $ \db -> overwriteProtocolServers db user servers
|
||||||
coupleDaysAgo t = (`addUTCTime` t) . fromInteger . negate . (+ (2 * day)) <$> randomRIO (0, day)
|
coupleDaysAgo t = (`addUTCTime` t) . fromInteger . negate . (+ (2 * day)) <$> randomRIO (0, day)
|
||||||
day = 86400
|
day = 86400
|
||||||
ListUsers -> CRUsersList <$> withStore' getUsersInfo
|
ListUsers -> CRUsersList <$> withStoreCtx' (Just "ListUsers, getUsersInfo") getUsersInfo
|
||||||
APISetActiveUser userId' viewPwd_ -> withUser $ \user -> do
|
APISetActiveUser userId' viewPwd_ -> withUser $ \user -> do
|
||||||
user' <- privateGetUser userId'
|
user' <- privateGetUser userId'
|
||||||
validateUserPassword user user' viewPwd_
|
validateUserPassword user user' viewPwd_
|
||||||
withStore' $ \db -> setActiveUser db userId'
|
withStoreCtx' (Just "APISetActiveUser, setActiveUser") $ \db -> setActiveUser db userId'
|
||||||
setActive ActiveNone
|
setActive ActiveNone
|
||||||
let user'' = user' {activeUser = True}
|
let user'' = user' {activeUser = True}
|
||||||
asks currentUser >>= atomically . (`writeTVar` Just user'')
|
asks currentUser >>= atomically . (`writeTVar` Just user'')
|
||||||
@ -421,14 +421,14 @@ processChatCommand = \case
|
|||||||
APIActivateChat -> withUser $ \_ -> do
|
APIActivateChat -> withUser $ \_ -> do
|
||||||
restoreCalls
|
restoreCalls
|
||||||
withAgent foregroundAgent
|
withAgent foregroundAgent
|
||||||
withStore' getUsers >>= void . forkIO . startFilesToReceive
|
withStoreCtx' (Just "APIActivateChat, getUsers") getUsers >>= void . forkIO . startFilesToReceive
|
||||||
setAllExpireCIFlags True
|
setAllExpireCIFlags True
|
||||||
ok_
|
ok_
|
||||||
APISuspendChat t -> do
|
APISuspendChat t -> do
|
||||||
setAllExpireCIFlags False
|
setAllExpireCIFlags False
|
||||||
withAgent (`suspendAgent` t)
|
withAgent (`suspendAgent` t)
|
||||||
ok_
|
ok_
|
||||||
ResubscribeAllConnections -> withStore' getUsers >>= subscribeUsers >> ok_
|
ResubscribeAllConnections -> withStoreCtx' (Just "ResubscribeAllConnections, getUsers") getUsers >>= subscribeUsers >> ok_
|
||||||
-- has to be called before StartChat
|
-- has to be called before StartChat
|
||||||
SetTempFolder tf -> do
|
SetTempFolder tf -> do
|
||||||
createDirectoryIfMissing True tf
|
createDirectoryIfMissing True tf
|
||||||
@ -458,7 +458,7 @@ processChatCommand = \case
|
|||||||
ExecChatStoreSQL query -> CRSQLResult <$> withStore' (`execSQL` query)
|
ExecChatStoreSQL query -> CRSQLResult <$> withStore' (`execSQL` query)
|
||||||
ExecAgentStoreSQL query -> CRSQLResult <$> withAgent (`execAgentStoreSQL` query)
|
ExecAgentStoreSQL query -> CRSQLResult <$> withAgent (`execAgentStoreSQL` query)
|
||||||
APIGetChats userId withPCC -> withUserId userId $ \user ->
|
APIGetChats userId withPCC -> withUserId userId $ \user ->
|
||||||
CRApiChats user <$> withStore' (\db -> getChatPreviews db user withPCC)
|
CRApiChats user <$> withStoreCtx' (Just "APIGetChats, getChatPreviews") (\db -> getChatPreviews db user withPCC)
|
||||||
APIGetChat (ChatRef cType cId) pagination search -> withUser $ \user -> case cType of
|
APIGetChat (ChatRef cType cId) pagination search -> withUser $ \user -> case cType of
|
||||||
-- TODO optimize queries calculating ChatStats, currently they're disabled
|
-- TODO optimize queries calculating ChatStats, currently they're disabled
|
||||||
CTDirect -> do
|
CTDirect -> do
|
||||||
@ -1063,7 +1063,7 @@ processChatCommand = \case
|
|||||||
SetChatItemTTL newTTL_ -> withUser' $ \User {userId} -> do
|
SetChatItemTTL newTTL_ -> withUser' $ \User {userId} -> do
|
||||||
processChatCommand $ APISetChatItemTTL userId newTTL_
|
processChatCommand $ APISetChatItemTTL userId newTTL_
|
||||||
APIGetChatItemTTL userId -> withUserId userId $ \user -> do
|
APIGetChatItemTTL userId -> withUserId userId $ \user -> do
|
||||||
ttl <- withStore' (`getChatItemTTL` user)
|
ttl <- withStoreCtx' (Just "APIGetChatItemTTL, getChatItemTTL") (`getChatItemTTL` user)
|
||||||
pure $ CRChatItemTTL user ttl
|
pure $ CRChatItemTTL user ttl
|
||||||
GetChatItemTTL -> withUser' $ \User {userId} -> do
|
GetChatItemTTL -> withUser' $ \User {userId} -> do
|
||||||
processChatCommand $ APIGetChatItemTTL userId
|
processChatCommand $ APIGetChatItemTTL userId
|
||||||
@ -1220,7 +1220,7 @@ processChatCommand = \case
|
|||||||
DeleteMyAddress -> withUser $ \User {userId} ->
|
DeleteMyAddress -> withUser $ \User {userId} ->
|
||||||
processChatCommand $ APIDeleteMyAddress userId
|
processChatCommand $ APIDeleteMyAddress userId
|
||||||
APIShowMyAddress userId -> withUserId userId $ \user ->
|
APIShowMyAddress userId -> withUserId userId $ \user ->
|
||||||
CRUserContactLink user <$> withStore (`getUserAddress` user)
|
CRUserContactLink user <$> withStoreCtx (Just "APIShowMyAddress, getUserAddress") (`getUserAddress` user)
|
||||||
ShowMyAddress -> withUser $ \User {userId} ->
|
ShowMyAddress -> withUser $ \User {userId} ->
|
||||||
processChatCommand $ APIShowMyAddress userId
|
processChatCommand $ APIShowMyAddress userId
|
||||||
APISetProfileAddress userId False -> withUserId userId $ \user@User {profile = p} -> do
|
APISetProfileAddress userId False -> withUserId userId $ \user@User {profile = p} -> do
|
||||||
@ -1936,12 +1936,14 @@ startExpireCIThread user@User {userId} = do
|
|||||||
_ -> pure ()
|
_ -> pure ()
|
||||||
where
|
where
|
||||||
runExpireCIs = do
|
runExpireCIs = do
|
||||||
|
delay <- asks (initialCleanupManagerDelay . config)
|
||||||
|
liftIO $ threadDelay' delay
|
||||||
interval <- asks $ ciExpirationInterval . config
|
interval <- asks $ ciExpirationInterval . config
|
||||||
forever $ do
|
forever $ do
|
||||||
flip catchError (toView . CRChatError (Just user)) $ do
|
flip catchError (toView . CRChatError (Just user)) $ do
|
||||||
expireFlags <- asks expireCIFlags
|
expireFlags <- asks expireCIFlags
|
||||||
atomically $ TM.lookup userId expireFlags >>= \b -> unless (b == Just True) retry
|
atomically $ TM.lookup userId expireFlags >>= \b -> unless (b == Just True) retry
|
||||||
ttl <- withStore' (`getChatItemTTL` user)
|
ttl <- withStoreCtx' (Just "startExpireCIThread, getChatItemTTL") (`getChatItemTTL` user)
|
||||||
forM_ ttl $ \t -> expireChatItems user t False
|
forM_ ttl $ \t -> expireChatItems user t False
|
||||||
liftIO $ threadDelay' interval
|
liftIO $ threadDelay' interval
|
||||||
|
|
||||||
@ -2065,11 +2067,11 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, xftpRcvFile, fileI
|
|||||||
(Nothing, Just connReq) -> do
|
(Nothing, Just connReq) -> do
|
||||||
connIds <- joinAgentConnectionAsync user True connReq . directMessage $ XFileAcpt fName
|
connIds <- joinAgentConnectionAsync user True connReq . directMessage $ XFileAcpt fName
|
||||||
filePath <- getRcvFilePath fileId filePath_ fName True
|
filePath <- getRcvFilePath fileId filePath_ fName True
|
||||||
withStore $ \db -> acceptRcvFileTransfer db user fileId connIds ConnJoined filePath
|
withStoreCtx (Just "acceptFileReceive, acceptRcvFileTransfer") $ \db -> acceptRcvFileTransfer db user fileId connIds ConnJoined filePath
|
||||||
-- XFTP
|
-- XFTP
|
||||||
(Just _xftpRcvFile, _) -> do
|
(Just _xftpRcvFile, _) -> do
|
||||||
filePath <- getRcvFilePath fileId filePath_ fName False
|
filePath <- getRcvFilePath fileId filePath_ fName False
|
||||||
(ci, rfd) <- withStore $ \db -> do
|
(ci, rfd) <- withStoreCtx (Just "acceptFileReceive, xftpAcceptRcvFT ...") $ \db -> do
|
||||||
-- marking file as accepted and reading description in the same transaction
|
-- marking file as accepted and reading description in the same transaction
|
||||||
-- to prevent race condition with appending description
|
-- to prevent race condition with appending description
|
||||||
ci <- xftpAcceptRcvFT db user fileId filePath
|
ci <- xftpAcceptRcvFT db user fileId filePath
|
||||||
@ -2079,13 +2081,13 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, xftpRcvFile, fileI
|
|||||||
pure ci
|
pure ci
|
||||||
-- group & direct file protocol
|
-- group & direct file protocol
|
||||||
_ -> do
|
_ -> do
|
||||||
chatRef <- withStore $ \db -> getChatRefByFileId db user fileId
|
chatRef <- withStoreCtx (Just "acceptFileReceive, getChatRefByFileId") $ \db -> getChatRefByFileId db user fileId
|
||||||
case (chatRef, grpMemberId) of
|
case (chatRef, grpMemberId) of
|
||||||
(ChatRef CTDirect contactId, Nothing) -> do
|
(ChatRef CTDirect contactId, Nothing) -> do
|
||||||
ct <- withStore $ \db -> getContact db user contactId
|
ct <- withStoreCtx (Just "acceptFileReceive, getContact") $ \db -> getContact db user contactId
|
||||||
acceptFile CFCreateConnFileInvDirect $ \msg -> void $ sendDirectContactMessage ct msg
|
acceptFile CFCreateConnFileInvDirect $ \msg -> void $ sendDirectContactMessage ct msg
|
||||||
(ChatRef CTGroup groupId, Just memId) -> do
|
(ChatRef CTGroup groupId, Just memId) -> do
|
||||||
GroupMember {activeConn} <- withStore $ \db -> getGroupMember db user groupId memId
|
GroupMember {activeConn} <- withStoreCtx (Just "acceptFileReceive, getGroupMember") $ \db -> getGroupMember db user groupId memId
|
||||||
case activeConn of
|
case activeConn of
|
||||||
Just conn -> do
|
Just conn -> do
|
||||||
acceptFile CFCreateConnFileInvGroup $ \msg -> void $ sendDirectMessage conn msg $ GroupId groupId
|
acceptFile CFCreateConnFileInvGroup $ \msg -> void $ sendDirectMessage conn msg $ GroupId groupId
|
||||||
@ -2099,7 +2101,7 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, xftpRcvFile, fileI
|
|||||||
if
|
if
|
||||||
| inline -> do
|
| inline -> do
|
||||||
-- accepting inline
|
-- accepting inline
|
||||||
ci <- withStore $ \db -> acceptRcvInlineFT db user fileId filePath
|
ci <- withStoreCtx (Just "acceptFile, acceptRcvInlineFT") $ \db -> acceptRcvInlineFT db user fileId filePath
|
||||||
sharedMsgId <- withStore $ \db -> getSharedMsgIdByFileId db userId fileId
|
sharedMsgId <- withStore $ \db -> getSharedMsgIdByFileId db userId fileId
|
||||||
send $ XFileAcptInv sharedMsgId Nothing fName
|
send $ XFileAcptInv sharedMsgId Nothing fName
|
||||||
pure ci
|
pure ci
|
||||||
@ -2107,7 +2109,7 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, xftpRcvFile, fileI
|
|||||||
| otherwise -> do
|
| otherwise -> do
|
||||||
-- accepting via a new connection
|
-- accepting via a new connection
|
||||||
connIds <- createAgentConnectionAsync user cmdFunction True SCMInvitation
|
connIds <- createAgentConnectionAsync user cmdFunction True SCMInvitation
|
||||||
withStore $ \db -> acceptRcvFileTransfer db user fileId connIds ConnNew filePath
|
withStoreCtx (Just "acceptFile, acceptRcvFileTransfer") $ \db -> acceptRcvFileTransfer db user fileId connIds ConnNew filePath
|
||||||
receiveInline :: m Bool
|
receiveInline :: m Bool
|
||||||
receiveInline = do
|
receiveInline = do
|
||||||
ChatConfig {fileChunkSize, inlineFiles = InlineFilesConfig {receiveChunks, offerChunks}} <- asks config
|
ChatConfig {fileChunkSize, inlineFiles = InlineFilesConfig {receiveChunks, offerChunks}} <- asks config
|
||||||
@ -2124,11 +2126,11 @@ receiveViaCompleteFD user fileId RcvFileDescr {fileDescrText, fileDescrComplete}
|
|||||||
rd <- parseFileDescription fileDescrText
|
rd <- parseFileDescription fileDescrText
|
||||||
aFileId <- withAgent $ \a -> xftpReceiveFile a (aUserId user) rd
|
aFileId <- withAgent $ \a -> xftpReceiveFile a (aUserId user) rd
|
||||||
startReceivingFile user fileId
|
startReceivingFile user fileId
|
||||||
withStore' $ \db -> updateRcvFileAgentId db fileId (Just $ AgentRcvFileId aFileId)
|
withStoreCtx' (Just "receiveViaCompleteFD, updateRcvFileAgentId") $ \db -> updateRcvFileAgentId db fileId (Just $ AgentRcvFileId aFileId)
|
||||||
|
|
||||||
startReceivingFile :: ChatMonad m => User -> FileTransferId -> m ()
|
startReceivingFile :: ChatMonad m => User -> FileTransferId -> m ()
|
||||||
startReceivingFile user fileId = do
|
startReceivingFile user fileId = do
|
||||||
ci <- withStore $ \db -> do
|
ci <- withStoreCtx (Just "startReceivingFile, updateRcvFileStatus ...") $ \db -> do
|
||||||
liftIO $ updateRcvFileStatus db fileId FSConnected
|
liftIO $ updateRcvFileStatus db fileId FSConnected
|
||||||
liftIO $ updateCIFileStatus db user fileId $ CIFSRcvTransfer 0 1
|
liftIO $ updateCIFileStatus db user fileId $ CIFSRcvTransfer 0 1
|
||||||
getChatItemByFileId db user fileId
|
getChatItemByFileId db user fileId
|
||||||
@ -2237,7 +2239,7 @@ agentSubscriber = do
|
|||||||
type AgentBatchSubscribe m = AgentClient -> [ConnId] -> ExceptT AgentErrorType m (Map ConnId (Either AgentErrorType ()))
|
type AgentBatchSubscribe m = AgentClient -> [ConnId] -> ExceptT AgentErrorType m (Map ConnId (Either AgentErrorType ()))
|
||||||
|
|
||||||
subscribeUserConnections :: forall m. ChatMonad m => AgentBatchSubscribe m -> User -> m ()
|
subscribeUserConnections :: forall m. ChatMonad m => AgentBatchSubscribe m -> User -> m ()
|
||||||
subscribeUserConnections agentBatchSubscribe user = do
|
subscribeUserConnections agentBatchSubscribe user@User {userId} = do
|
||||||
-- get user connections
|
-- get user connections
|
||||||
ce <- asks $ subscriptionEvents . config
|
ce <- asks $ subscriptionEvents . config
|
||||||
(ctConns, cts) <- getContactConns
|
(ctConns, cts) <- getContactConns
|
||||||
@ -2258,32 +2260,32 @@ subscribeUserConnections agentBatchSubscribe user = do
|
|||||||
where
|
where
|
||||||
getContactConns :: m ([ConnId], Map ConnId Contact)
|
getContactConns :: m ([ConnId], Map ConnId Contact)
|
||||||
getContactConns = do
|
getContactConns = do
|
||||||
cts <- withStore_ getUserContacts
|
cts <- withStore_ ("subscribeUserConnections " <> show userId <> ", getUserContacts") getUserContacts
|
||||||
let connIds = map contactConnId cts
|
let connIds = map contactConnId cts
|
||||||
pure (connIds, M.fromList $ zip connIds cts)
|
pure (connIds, M.fromList $ zip connIds cts)
|
||||||
getUserContactLinkConns :: m ([ConnId], Map ConnId UserContact)
|
getUserContactLinkConns :: m ([ConnId], Map ConnId UserContact)
|
||||||
getUserContactLinkConns = do
|
getUserContactLinkConns = do
|
||||||
(cs, ucs) <- unzip <$> withStore_ getUserContactLinks
|
(cs, ucs) <- unzip <$> withStore_ ("subscribeUserConnections " <> show userId <> ", getUserContactLinks") getUserContactLinks
|
||||||
let connIds = map aConnId cs
|
let connIds = map aConnId cs
|
||||||
pure (connIds, M.fromList $ zip connIds ucs)
|
pure (connIds, M.fromList $ zip connIds ucs)
|
||||||
getGroupMemberConns :: m ([Group], [ConnId], Map ConnId GroupMember)
|
getGroupMemberConns :: m ([Group], [ConnId], Map ConnId GroupMember)
|
||||||
getGroupMemberConns = do
|
getGroupMemberConns = do
|
||||||
gs <- withStore_ getUserGroups
|
gs <- withStore_ ("subscribeUserConnections " <> show userId <> ", getUserGroups") getUserGroups
|
||||||
let mPairs = concatMap (\(Group _ ms) -> mapMaybe (\m -> (,m) <$> memberConnId m) ms) gs
|
let mPairs = concatMap (\(Group _ ms) -> mapMaybe (\m -> (,m) <$> memberConnId m) ms) gs
|
||||||
pure (gs, map fst mPairs, M.fromList mPairs)
|
pure (gs, map fst mPairs, M.fromList mPairs)
|
||||||
getSndFileTransferConns :: m ([ConnId], Map ConnId SndFileTransfer)
|
getSndFileTransferConns :: m ([ConnId], Map ConnId SndFileTransfer)
|
||||||
getSndFileTransferConns = do
|
getSndFileTransferConns = do
|
||||||
sfts <- withStore_ getLiveSndFileTransfers
|
sfts <- withStore_ ("subscribeUserConnections " <> show userId <> ", getLiveSndFileTransfers") getLiveSndFileTransfers
|
||||||
let connIds = map sndFileTransferConnId sfts
|
let connIds = map sndFileTransferConnId sfts
|
||||||
pure (connIds, M.fromList $ zip connIds sfts)
|
pure (connIds, M.fromList $ zip connIds sfts)
|
||||||
getRcvFileTransferConns :: m ([ConnId], Map ConnId RcvFileTransfer)
|
getRcvFileTransferConns :: m ([ConnId], Map ConnId RcvFileTransfer)
|
||||||
getRcvFileTransferConns = do
|
getRcvFileTransferConns = do
|
||||||
rfts <- withStore_ getLiveRcvFileTransfers
|
rfts <- withStore_ ("subscribeUserConnections " <> show userId <> ", getLiveRcvFileTransfers") getLiveRcvFileTransfers
|
||||||
let rftPairs = mapMaybe (\ft -> (,ft) <$> liveRcvFileTransferConnId ft) rfts
|
let rftPairs = mapMaybe (\ft -> (,ft) <$> liveRcvFileTransferConnId ft) rfts
|
||||||
pure (map fst rftPairs, M.fromList rftPairs)
|
pure (map fst rftPairs, M.fromList rftPairs)
|
||||||
getPendingContactConns :: m ([ConnId], Map ConnId PendingContactConnection)
|
getPendingContactConns :: m ([ConnId], Map ConnId PendingContactConnection)
|
||||||
getPendingContactConns = do
|
getPendingContactConns = do
|
||||||
pcs <- withStore_ getPendingContactConnections
|
pcs <- withStore_ ("subscribeUserConnections " <> show userId <> ", getPendingContactConnections") getPendingContactConnections
|
||||||
let connIds = map aConnId' pcs
|
let connIds = map aConnId' pcs
|
||||||
pure (connIds, M.fromList $ zip connIds pcs)
|
pure (connIds, M.fromList $ zip connIds pcs)
|
||||||
contactSubsToView :: Map ConnId (Either AgentErrorType ()) -> Map ConnId Contact -> Bool -> m ()
|
contactSubsToView :: Map ConnId (Either AgentErrorType ()) -> Map ConnId Contact -> Bool -> m ()
|
||||||
@ -2334,8 +2336,8 @@ subscribeUserConnections agentBatchSubscribe user = do
|
|||||||
rcvFileSubsToView rs = mapM_ (toView . uncurry (CRRcvFileSubError user)) . filterErrors . resultsFor rs
|
rcvFileSubsToView rs = mapM_ (toView . uncurry (CRRcvFileSubError user)) . filterErrors . resultsFor rs
|
||||||
pendingConnSubsToView :: Map ConnId (Either AgentErrorType ()) -> Map ConnId PendingContactConnection -> m ()
|
pendingConnSubsToView :: Map ConnId (Either AgentErrorType ()) -> Map ConnId PendingContactConnection -> m ()
|
||||||
pendingConnSubsToView rs = toView . CRPendingSubSummary user . map (uncurry PendingSubStatus) . resultsFor rs
|
pendingConnSubsToView rs = toView . CRPendingSubSummary user . map (uncurry PendingSubStatus) . resultsFor rs
|
||||||
withStore_ :: (DB.Connection -> User -> IO [a]) -> m [a]
|
withStore_ :: String -> (DB.Connection -> User -> IO [a]) -> m [a]
|
||||||
withStore_ a = withStore' (`a` user) `catchError` \e -> toView (CRChatError (Just user) e) $> []
|
withStore_ ctx a = withStoreCtx' (Just ctx) (`a` user) `catchError` \e -> toView (CRChatError (Just user) e) $> []
|
||||||
filterErrors :: [(a, Maybe ChatError)] -> [(a, ChatError)]
|
filterErrors :: [(a, Maybe ChatError)] -> [(a, ChatError)]
|
||||||
filterErrors = mapMaybe (\(a, e_) -> (a,) <$> e_)
|
filterErrors = mapMaybe (\(a, e_) -> (a,) <$> e_)
|
||||||
resultsFor :: Map ConnId (Either AgentErrorType ()) -> Map ConnId a -> [(a, Maybe ChatError)]
|
resultsFor :: Map ConnId (Either AgentErrorType ()) -> Map ConnId a -> [(a, Maybe ChatError)]
|
||||||
@ -2358,7 +2360,7 @@ cleanupManager = do
|
|||||||
forever $ do
|
forever $ do
|
||||||
flip catchError (toView . CRChatError Nothing) $ do
|
flip catchError (toView . CRChatError Nothing) $ do
|
||||||
waitChatStarted
|
waitChatStarted
|
||||||
users <- withStore' getUsers
|
users <- withStoreCtx' (Just "cleanupManager, getUsers 1") getUsers
|
||||||
let (us, us') = partition activeUser users
|
let (us, us') = partition activeUser users
|
||||||
forM_ us $ cleanupUser interval
|
forM_ us $ cleanupUser interval
|
||||||
forM_ us' $ cleanupUser interval
|
forM_ us' $ cleanupUser interval
|
||||||
@ -2367,7 +2369,7 @@ cleanupManager = do
|
|||||||
where
|
where
|
||||||
runWithoutInitialDelay cleanupInterval = flip catchError (toView . CRChatError Nothing) $ do
|
runWithoutInitialDelay cleanupInterval = flip catchError (toView . CRChatError Nothing) $ do
|
||||||
waitChatStarted
|
waitChatStarted
|
||||||
users <- withStore' getUsers
|
users <- withStoreCtx' (Just "cleanupManager, getUsers 2") getUsers
|
||||||
let (us, us') = partition activeUser users
|
let (us, us') = partition activeUser users
|
||||||
forM_ us $ \u -> cleanupTimedItems cleanupInterval u `catchError` (toView . CRChatError (Just u))
|
forM_ us $ \u -> cleanupTimedItems cleanupInterval u `catchError` (toView . CRChatError (Just u))
|
||||||
forM_ us' $ \u -> cleanupTimedItems cleanupInterval u `catchError` (toView . CRChatError (Just u))
|
forM_ us' $ \u -> cleanupTimedItems cleanupInterval u `catchError` (toView . CRChatError (Just u))
|
||||||
@ -2376,12 +2378,12 @@ cleanupManager = do
|
|||||||
cleanupTimedItems cleanupInterval user = do
|
cleanupTimedItems cleanupInterval user = do
|
||||||
ts <- liftIO getCurrentTime
|
ts <- liftIO getCurrentTime
|
||||||
let startTimedThreadCutoff = addUTCTime cleanupInterval ts
|
let startTimedThreadCutoff = addUTCTime cleanupInterval ts
|
||||||
timedItems <- withStore' $ \db -> getTimedItems db user startTimedThreadCutoff
|
timedItems <- withStoreCtx' (Just "cleanupManager, getTimedItems") $ \db -> getTimedItems db user startTimedThreadCutoff
|
||||||
forM_ timedItems $ \(itemRef, deleteAt) -> startTimedItemThread user itemRef deleteAt `catchError` const (pure ())
|
forM_ timedItems $ \(itemRef, deleteAt) -> startTimedItemThread user itemRef deleteAt `catchError` const (pure ())
|
||||||
cleanupMessages = do
|
cleanupMessages = do
|
||||||
ts <- liftIO getCurrentTime
|
ts <- liftIO getCurrentTime
|
||||||
let cutoffTs = addUTCTime (- (30 * nominalDay)) ts
|
let cutoffTs = addUTCTime (- (30 * nominalDay)) ts
|
||||||
withStore' (`deleteOldMessages` cutoffTs)
|
withStoreCtx' (Just "cleanupManager, deleteOldMessages") (`deleteOldMessages` cutoffTs)
|
||||||
|
|
||||||
startProximateTimedItemThread :: ChatMonad m => User -> (ChatRef, ChatItemId) -> UTCTime -> m ()
|
startProximateTimedItemThread :: ChatMonad m => User -> (ChatRef, ChatItemId) -> UTCTime -> m ()
|
||||||
startProximateTimedItemThread user itemRef deleteAt = do
|
startProximateTimedItemThread user itemRef deleteAt = do
|
||||||
@ -2412,10 +2414,10 @@ deleteTimedItem user (ChatRef cType chatId, itemId) deleteAt = do
|
|||||||
waitChatStarted
|
waitChatStarted
|
||||||
case cType of
|
case cType of
|
||||||
CTDirect -> do
|
CTDirect -> do
|
||||||
(ct, ci) <- withStore $ \db -> (,) <$> getContact db user chatId <*> getDirectChatItem db user chatId itemId
|
(ct, ci) <- withStoreCtx (Just "deleteTimedItem, getContact ...") $ \db -> (,) <$> getContact db user chatId <*> getDirectChatItem db user chatId itemId
|
||||||
deleteDirectCI user ct ci True True >>= toView
|
deleteDirectCI user ct ci True True >>= toView
|
||||||
CTGroup -> do
|
CTGroup -> do
|
||||||
(gInfo, ci) <- withStore $ \db -> (,) <$> getGroupInfo db user chatId <*> getGroupChatItem db user chatId itemId
|
(gInfo, ci) <- withStoreCtx (Just "deleteTimedItem, getGroupInfo ...") $ \db -> (,) <$> getGroupInfo db user chatId <*> getGroupChatItem db user chatId itemId
|
||||||
deletedTs <- liftIO getCurrentTime
|
deletedTs <- liftIO getCurrentTime
|
||||||
deleteGroupCI user gInfo ci True True Nothing deletedTs >>= toView
|
deleteGroupCI user gInfo ci True True Nothing deletedTs >>= toView
|
||||||
_ -> toView . CRChatError (Just user) . ChatError $ CEInternalError "bad deleteTimedItem cType"
|
_ -> toView . CRChatError (Just user) . ChatError $ CEInternalError "bad deleteTimedItem cType"
|
||||||
@ -2433,9 +2435,9 @@ expireChatItems user@User {userId} ttl sync = do
|
|||||||
let expirationDate = addUTCTime (-1 * fromIntegral ttl) currentTs
|
let expirationDate = addUTCTime (-1 * fromIntegral ttl) currentTs
|
||||||
-- this is to keep group messages created during last 12 hours even if they're expired according to item_ts
|
-- this is to keep group messages created during last 12 hours even if they're expired according to item_ts
|
||||||
createdAtCutoff = addUTCTime (-43200 :: NominalDiffTime) currentTs
|
createdAtCutoff = addUTCTime (-43200 :: NominalDiffTime) currentTs
|
||||||
contacts <- withStore' (`getUserContacts` user)
|
contacts <- withStoreCtx' (Just "expireChatItems, getUserContacts") (`getUserContacts` user)
|
||||||
loop contacts $ processContact expirationDate
|
loop contacts $ processContact expirationDate
|
||||||
groups <- withStore' (`getUserGroupDetails` user)
|
groups <- withStoreCtx' (Just "expireChatItems, getUserGroupDetails") (`getUserGroupDetails` user)
|
||||||
loop groups $ processGroup expirationDate createdAtCutoff
|
loop groups $ processGroup expirationDate createdAtCutoff
|
||||||
where
|
where
|
||||||
loop :: [a] -> (a -> m ()) -> m ()
|
loop :: [a] -> (a -> m ()) -> m ()
|
||||||
@ -2453,16 +2455,16 @@ expireChatItems user@User {userId} ttl sync = do
|
|||||||
when (expire == Just True) $ threadDelay 100000 >> a
|
when (expire == Just True) $ threadDelay 100000 >> a
|
||||||
processContact :: UTCTime -> Contact -> m ()
|
processContact :: UTCTime -> Contact -> m ()
|
||||||
processContact expirationDate ct = do
|
processContact expirationDate ct = do
|
||||||
filesInfo <- withStore' $ \db -> getContactExpiredFileInfo db user ct expirationDate
|
filesInfo <- withStoreCtx' (Just "processContact, getContactExpiredFileInfo") $ \db -> getContactExpiredFileInfo db user ct expirationDate
|
||||||
deleteFilesAndConns user filesInfo
|
deleteFilesAndConns user filesInfo
|
||||||
withStore' $ \db -> deleteContactExpiredCIs db user ct expirationDate
|
withStoreCtx' (Just "processContact, deleteContactExpiredCIs") $ \db -> deleteContactExpiredCIs db user ct expirationDate
|
||||||
processGroup :: UTCTime -> UTCTime -> GroupInfo -> m ()
|
processGroup :: UTCTime -> UTCTime -> GroupInfo -> m ()
|
||||||
processGroup expirationDate createdAtCutoff gInfo = do
|
processGroup expirationDate createdAtCutoff gInfo = do
|
||||||
filesInfo <- withStore' $ \db -> getGroupExpiredFileInfo db user gInfo expirationDate createdAtCutoff
|
filesInfo <- withStoreCtx' (Just "processGroup, getGroupExpiredFileInfo") $ \db -> getGroupExpiredFileInfo db user gInfo expirationDate createdAtCutoff
|
||||||
deleteFilesAndConns user filesInfo
|
deleteFilesAndConns user filesInfo
|
||||||
withStore' $ \db -> deleteGroupExpiredCIs db user gInfo expirationDate createdAtCutoff
|
withStoreCtx' (Just "processGroup, deleteGroupExpiredCIs") $ \db -> deleteGroupExpiredCIs db user gInfo expirationDate createdAtCutoff
|
||||||
membersToDelete <- withStore' $ \db -> getGroupMembersForExpiration db user gInfo
|
membersToDelete <- withStoreCtx' (Just "processGroup, getGroupMembersForExpiration") $ \db -> getGroupMembersForExpiration db user gInfo
|
||||||
forM_ membersToDelete $ \m -> withStore' $ \db -> deleteGroupMember db user m
|
forM_ membersToDelete $ \m -> withStoreCtx' (Just "processGroup, deleteGroupMember") $ \db -> deleteGroupMember db user m
|
||||||
|
|
||||||
processAgentMessage :: forall m. ChatMonad m => ACorrId -> ConnId -> ACommand 'Agent 'AEConn -> m ()
|
processAgentMessage :: forall m. ChatMonad m => ACorrId -> ConnId -> ACommand 'Agent 'AEConn -> m ()
|
||||||
processAgentMessage _ connId (DEL_RCVQ srv qId err_) =
|
processAgentMessage _ connId (DEL_RCVQ srv qId err_) =
|
||||||
@ -4423,13 +4425,13 @@ mkChatItem cd ciId content file quotedItem sharedMsgId itemTimed live itemTs cur
|
|||||||
deleteDirectCI :: ChatMonad m => User -> Contact -> CChatItem 'CTDirect -> Bool -> Bool -> m ChatResponse
|
deleteDirectCI :: ChatMonad m => User -> Contact -> CChatItem 'CTDirect -> Bool -> Bool -> m ChatResponse
|
||||||
deleteDirectCI user ct ci@(CChatItem msgDir deletedItem@ChatItem {file}) byUser timed = do
|
deleteDirectCI user ct ci@(CChatItem msgDir deletedItem@ChatItem {file}) byUser timed = do
|
||||||
deleteCIFile user file
|
deleteCIFile user file
|
||||||
withStore' $ \db -> deleteDirectChatItem db user ct ci
|
withStoreCtx' (Just "deleteDirectCI, deleteDirectChatItem") $ \db -> deleteDirectChatItem db user ct ci
|
||||||
pure $ CRChatItemDeleted user (AChatItem SCTDirect msgDir (DirectChat ct) deletedItem) Nothing byUser timed
|
pure $ CRChatItemDeleted user (AChatItem SCTDirect msgDir (DirectChat ct) deletedItem) Nothing byUser timed
|
||||||
|
|
||||||
deleteGroupCI :: ChatMonad m => User -> GroupInfo -> CChatItem 'CTGroup -> Bool -> Bool -> Maybe GroupMember -> UTCTime -> m ChatResponse
|
deleteGroupCI :: ChatMonad m => User -> GroupInfo -> CChatItem 'CTGroup -> Bool -> Bool -> Maybe GroupMember -> UTCTime -> m ChatResponse
|
||||||
deleteGroupCI user gInfo ci@(CChatItem msgDir deletedItem@ChatItem {file}) byUser timed byGroupMember_ deletedTs = do
|
deleteGroupCI user gInfo ci@(CChatItem msgDir deletedItem@ChatItem {file}) byUser timed byGroupMember_ deletedTs = do
|
||||||
deleteCIFile user file
|
deleteCIFile user file
|
||||||
toCi <- withStore' $ \db ->
|
toCi <- withStoreCtx' (Just "deleteGroupCI, deleteGroupChatItem ...") $ \db ->
|
||||||
case byGroupMember_ of
|
case byGroupMember_ of
|
||||||
Nothing -> deleteGroupChatItem db user gInfo ci $> Nothing
|
Nothing -> deleteGroupChatItem db user gInfo ci $> Nothing
|
||||||
Just m -> Just <$> updateGroupChatItemModerated db user gInfo ci m deletedTs
|
Just m -> Just <$> updateGroupChatItemModerated db user gInfo ci m deletedTs
|
||||||
@ -4713,11 +4715,20 @@ withStoreCtx' ctx_ action = withStoreCtx ctx_ $ liftIO . action
|
|||||||
withStoreCtx :: ChatMonad m => Maybe String -> (DB.Connection -> ExceptT StoreError IO a) -> m a
|
withStoreCtx :: ChatMonad m => Maybe String -> (DB.Connection -> ExceptT StoreError IO a) -> m a
|
||||||
withStoreCtx ctx_ action = do
|
withStoreCtx ctx_ action = do
|
||||||
ChatController {chatStore} <- ask
|
ChatController {chatStore} <- ask
|
||||||
liftEitherError ChatErrorStore $
|
liftEitherError ChatErrorStore $ case ctx_ of
|
||||||
withTransaction chatStore (runExceptT . action) `E.catch` handleInternal
|
Nothing -> withTransaction chatStore (runExceptT . action) `E.catch` handleInternal ""
|
||||||
|
Just _ -> withTransaction chatStore (runExceptT . action) `E.catch` handleInternal ""
|
||||||
|
-- uncomment to debug store performance
|
||||||
|
-- Just ctx -> do
|
||||||
|
-- t1 <- liftIO getCurrentTime
|
||||||
|
-- putStrLn $ "withStoreCtx start :: " <> show t1 <> " :: " <> ctx
|
||||||
|
-- r <- withTransactionCtx ctx_ chatStore (runExceptT . action) `E.catch` handleInternal (" (" <> ctx <> ")")
|
||||||
|
-- t2 <- liftIO getCurrentTime
|
||||||
|
-- putStrLn $ "withStoreCtx end :: " <> show t2 <> " :: " <> ctx <> " :: duration=" <> show (diffToMilliseconds $ diffUTCTime t2 t1)
|
||||||
|
-- pure r
|
||||||
where
|
where
|
||||||
handleInternal :: E.SomeException -> IO (Either StoreError a)
|
handleInternal :: String -> E.SomeException -> IO (Either StoreError a)
|
||||||
handleInternal e = pure . Left . SEInternalError $ show e <> maybe "" (\ctx -> " (" <> ctx <> ")") ctx_
|
handleInternal ctxStr e = pure . Left . SEInternalError $ show e <> ctxStr
|
||||||
|
|
||||||
chatCommandP :: Parser ChatCommand
|
chatCommandP :: Parser ChatCommand
|
||||||
chatCommandP =
|
chatCommandP =
|
||||||
|
30
src/Simplex/Chat/Migrations/M20230529_indexes.hs
Normal file
30
src/Simplex/Chat/Migrations/M20230529_indexes.hs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
|
||||||
|
module Simplex.Chat.Migrations.M20230529_indexes where
|
||||||
|
|
||||||
|
import Database.SQLite.Simple (Query)
|
||||||
|
import Database.SQLite.Simple.QQ (sql)
|
||||||
|
|
||||||
|
m20230529_indexes :: Query
|
||||||
|
m20230529_indexes =
|
||||||
|
[sql|
|
||||||
|
DROP INDEX idx_chat_items_timed_delete_at;
|
||||||
|
|
||||||
|
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(user_id, timed_delete_at);
|
||||||
|
|
||||||
|
CREATE INDEX idx_group_members_group_id ON group_members(user_id, group_id);
|
||||||
|
|
||||||
|
CREATE INDEX idx_msg_deliveries_agent_ack_cmd_id ON msg_deliveries(connection_id, agent_ack_cmd_id);
|
||||||
|
|]
|
||||||
|
|
||||||
|
down_m20230529_indexes :: Query
|
||||||
|
down_m20230529_indexes =
|
||||||
|
[sql|
|
||||||
|
DROP INDEX idx_msg_deliveries_agent_ack_cmd_id;
|
||||||
|
|
||||||
|
DROP INDEX idx_group_members_group_id;
|
||||||
|
|
||||||
|
DROP INDEX idx_chat_items_timed_delete_at;
|
||||||
|
|
||||||
|
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(timed_delete_at);
|
||||||
|
|]
|
@ -522,7 +522,6 @@ CREATE UNIQUE INDEX idx_snd_files_last_inline_msg_delivery_id ON snd_files(
|
|||||||
CREATE INDEX idx_messages_connection_id ON messages(connection_id);
|
CREATE INDEX idx_messages_connection_id ON messages(connection_id);
|
||||||
CREATE INDEX idx_chat_items_group_member_id ON chat_items(group_member_id);
|
CREATE INDEX idx_chat_items_group_member_id ON chat_items(group_member_id);
|
||||||
CREATE INDEX idx_chat_items_contact_id ON chat_items(contact_id);
|
CREATE INDEX idx_chat_items_contact_id ON chat_items(contact_id);
|
||||||
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(timed_delete_at);
|
|
||||||
CREATE INDEX idx_chat_items_item_status ON chat_items(item_status);
|
CREATE INDEX idx_chat_items_item_status ON chat_items(item_status);
|
||||||
CREATE INDEX idx_connections_group_member ON connections(
|
CREATE INDEX idx_connections_group_member ON connections(
|
||||||
user_id,
|
user_id,
|
||||||
@ -644,3 +643,12 @@ CREATE INDEX idx_messages_created_at ON messages(created_at);
|
|||||||
CREATE INDEX idx_chat_item_reactions_created_by_msg_id ON chat_item_reactions(
|
CREATE INDEX idx_chat_item_reactions_created_by_msg_id ON chat_item_reactions(
|
||||||
created_by_msg_id
|
created_by_msg_id
|
||||||
);
|
);
|
||||||
|
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(
|
||||||
|
user_id,
|
||||||
|
timed_delete_at
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_group_members_group_id ON group_members(user_id, group_id);
|
||||||
|
CREATE INDEX idx_msg_deliveries_agent_ack_cmd_id ON msg_deliveries(
|
||||||
|
connection_id,
|
||||||
|
agent_ack_cmd_id
|
||||||
|
);
|
||||||
|
@ -395,6 +395,7 @@ import Simplex.Chat.Migrations.M20230505_chat_item_versions
|
|||||||
import Simplex.Chat.Migrations.M20230511_reactions
|
import Simplex.Chat.Migrations.M20230511_reactions
|
||||||
import Simplex.Chat.Migrations.M20230519_item_deleted_ts
|
import Simplex.Chat.Migrations.M20230519_item_deleted_ts
|
||||||
import Simplex.Chat.Migrations.M20230526_indexes
|
import Simplex.Chat.Migrations.M20230526_indexes
|
||||||
|
import Simplex.Chat.Migrations.M20230529_indexes
|
||||||
import Simplex.Chat.Protocol
|
import Simplex.Chat.Protocol
|
||||||
import Simplex.Chat.Types
|
import Simplex.Chat.Types
|
||||||
import Simplex.Chat.Util (week)
|
import Simplex.Chat.Util (week)
|
||||||
@ -475,7 +476,8 @@ schemaMigrations =
|
|||||||
("20230505_chat_item_versions", m20230505_chat_item_versions, Just down_m20230505_chat_item_versions),
|
("20230505_chat_item_versions", m20230505_chat_item_versions, Just down_m20230505_chat_item_versions),
|
||||||
("20230511_reactions", m20230511_reactions, Just down_m20230511_reactions),
|
("20230511_reactions", m20230511_reactions, Just down_m20230511_reactions),
|
||||||
("20230519_item_deleted_ts", m20230519_item_deleted_ts, Just down_m20230519_item_deleted_ts),
|
("20230519_item_deleted_ts", m20230519_item_deleted_ts, Just down_m20230519_item_deleted_ts),
|
||||||
("20230526_indexes", m20230526_indexes, Just down_m20230526_indexes)
|
("20230526_indexes", m20230526_indexes, Just down_m20230526_indexes),
|
||||||
|
("20230529_indexes", m20230529_indexes, Just down_m20230529_indexes)
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | The list of migrations in ascending order by date
|
-- | The list of migrations in ascending order by date
|
||||||
|
@ -1309,7 +1309,7 @@ testUsersDifferentCIExpirationTTL tmp = do
|
|||||||
|
|
||||||
alice #$> ("/_get chat @4 count=100", chat, [])
|
alice #$> ("/_get chat @4 count=100", chat, [])
|
||||||
where
|
where
|
||||||
cfg = testCfg {ciExpirationInterval = 500000}
|
cfg = testCfg {initialCleanupManagerDelay = 0, ciExpirationInterval = 500000}
|
||||||
|
|
||||||
testUsersRestartCIExpiration :: HasCallStack => FilePath -> IO ()
|
testUsersRestartCIExpiration :: HasCallStack => FilePath -> IO ()
|
||||||
testUsersRestartCIExpiration tmp = do
|
testUsersRestartCIExpiration tmp = do
|
||||||
@ -1392,7 +1392,7 @@ testUsersRestartCIExpiration tmp = do
|
|||||||
|
|
||||||
alice #$> ("/_get chat @4 count=100", chat, [])
|
alice #$> ("/_get chat @4 count=100", chat, [])
|
||||||
where
|
where
|
||||||
cfg = testCfg {ciExpirationInterval = 500000}
|
cfg = testCfg {initialCleanupManagerDelay = 0, ciExpirationInterval = 500000}
|
||||||
|
|
||||||
testEnableCIExpirationOnlyForOneUser :: HasCallStack => FilePath -> IO ()
|
testEnableCIExpirationOnlyForOneUser :: HasCallStack => FilePath -> IO ()
|
||||||
testEnableCIExpirationOnlyForOneUser tmp = do
|
testEnableCIExpirationOnlyForOneUser tmp = do
|
||||||
@ -1463,7 +1463,7 @@ testEnableCIExpirationOnlyForOneUser tmp = do
|
|||||||
-- new messages are not deleted for second user
|
-- new messages are not deleted for second user
|
||||||
alice #$> ("/_get chat @4 count=100", chat, chatFeatures <> [(1, "alisa 1"), (0, "alisa 2"), (1, "alisa 3"), (0, "alisa 4"), (1, "alisa 5"), (0, "alisa 6")])
|
alice #$> ("/_get chat @4 count=100", chat, chatFeatures <> [(1, "alisa 1"), (0, "alisa 2"), (1, "alisa 3"), (0, "alisa 4"), (1, "alisa 5"), (0, "alisa 6")])
|
||||||
where
|
where
|
||||||
cfg = testCfg {ciExpirationInterval = 500000}
|
cfg = testCfg {initialCleanupManagerDelay = 0, ciExpirationInterval = 500000}
|
||||||
|
|
||||||
testDisableCIExpirationOnlyForOneUser :: HasCallStack => FilePath -> IO ()
|
testDisableCIExpirationOnlyForOneUser :: HasCallStack => FilePath -> IO ()
|
||||||
testDisableCIExpirationOnlyForOneUser tmp = do
|
testDisableCIExpirationOnlyForOneUser tmp = do
|
||||||
@ -1521,7 +1521,7 @@ testDisableCIExpirationOnlyForOneUser tmp = do
|
|||||||
-- second user messages are deleted
|
-- second user messages are deleted
|
||||||
alice #$> ("/_get chat @4 count=100", chat, [])
|
alice #$> ("/_get chat @4 count=100", chat, [])
|
||||||
where
|
where
|
||||||
cfg = testCfg {ciExpirationInterval = 500000}
|
cfg = testCfg {initialCleanupManagerDelay = 0, ciExpirationInterval = 500000}
|
||||||
|
|
||||||
testUsersTimedMessages :: HasCallStack => FilePath -> IO ()
|
testUsersTimedMessages :: HasCallStack => FilePath -> IO ()
|
||||||
testUsersTimedMessages tmp = do
|
testUsersTimedMessages tmp = do
|
||||||
|
@ -65,7 +65,12 @@ testSchemaMigrations = withTmpFiles $ do
|
|||||||
schema''' `shouldBe` schema'
|
schema''' `shouldBe` schema'
|
||||||
|
|
||||||
skipComparisonForDownMigrations :: [String]
|
skipComparisonForDownMigrations :: [String]
|
||||||
skipComparisonForDownMigrations = ["20230504_recreate_msg_delivery_events_cleanup_messages"]
|
skipComparisonForDownMigrations =
|
||||||
|
[ -- on down migration msg_delivery_events table moves down to the end of the file
|
||||||
|
"20230504_recreate_msg_delivery_events_cleanup_messages",
|
||||||
|
-- on down migration idx_chat_items_timed_delete_at index moves down to the end of the file
|
||||||
|
"20230529_indexes"
|
||||||
|
]
|
||||||
|
|
||||||
getSchema :: FilePath -> FilePath -> IO String
|
getSchema :: FilePath -> FilePath -> IO String
|
||||||
getSchema dpPath schemaPath = do
|
getSchema dpPath schemaPath = do
|
||||||
|
Loading…
Reference in New Issue
Block a user