mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-25 15:34:32 +00:00
core: stop all workers on chat controller stop (#7502)
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
This commit is contained in:
co-authored by
Evgeny @ SimpleX Chat
parent
ae19a81201
commit
237409890e
@@ -95,7 +95,7 @@ import Simplex.Messaging.Protocol (AProtoServerWithAuth, AProtocolType (..), Msg
|
||||
import Simplex.Messaging.TMap (TMap)
|
||||
import Simplex.Messaging.Transport (TLS, TransportPeer (..), simplexMQVersion)
|
||||
import Simplex.Messaging.Transport.Client (SocksProxyWithAuth, TransportHost)
|
||||
import Simplex.Messaging.Util (AnyError (..), catchAllErrors, (<$$>))
|
||||
import Simplex.Messaging.Util (AnyError (..), catchAllErrors, catchOwn', (<$$>))
|
||||
import Simplex.RemoteControl.Client
|
||||
import Simplex.RemoteControl.Invitation (RCSignedInvitation, RCVerifiedInvitation)
|
||||
import Simplex.RemoteControl.Types
|
||||
@@ -1755,12 +1755,12 @@ withFastStore = withStorePriority True
|
||||
withStorePriority :: Bool -> (DB.Connection -> ExceptT StoreError IO a) -> CM a
|
||||
withStorePriority priority action = do
|
||||
ChatController {chatStore} <- ask
|
||||
liftIOEither $ withTransactionPriority chatStore priority (runExceptT . withExceptT ChatErrorStore . action) `E.catch` handleDBErrors
|
||||
liftIOEither $ withTransactionPriority chatStore priority (runExceptT . withExceptT ChatErrorStore . action) `catchOwn'` handleDBErrors
|
||||
|
||||
withStoreBatch :: Traversable t => (DB.Connection -> t (IO (Either ChatError a))) -> CM' (t (Either ChatError a))
|
||||
withStoreBatch actions = do
|
||||
ChatController {chatStore} <- ask
|
||||
liftIO $ withTransaction chatStore $ mapM (`E.catch` handleDBErrors) . actions
|
||||
liftIO $ withTransaction chatStore $ mapM (`catchOwn'` handleDBErrors) . actions
|
||||
|
||||
handleDBErrors :: E.SomeException -> IO (Either ChatError a)
|
||||
handleDBErrors e = pure $ Left $ ChatErrorStore $ case E.fromException e of
|
||||
|
||||
@@ -123,23 +123,24 @@ import Simplex.RemoteControl.Types (RCCtrlAddress (..))
|
||||
import System.Exit (ExitCode, exitSuccess)
|
||||
import System.FilePath (takeExtension, takeFileName, (</>))
|
||||
import System.IO (Handle, IOMode (..))
|
||||
import System.Mem.Weak (deRefWeak)
|
||||
import System.Random (randomRIO)
|
||||
import System.Timeout (timeout)
|
||||
import UnliftIO.Async
|
||||
import UnliftIO.Concurrent (forkIO, threadDelay)
|
||||
import UnliftIO.Concurrent (forkIO, killThread, threadDelay)
|
||||
import UnliftIO.Directory
|
||||
import qualified UnliftIO.Exception as E
|
||||
import UnliftIO.IO (hClose)
|
||||
import UnliftIO.STM
|
||||
#if defined(dbPostgres)
|
||||
import Data.Bifunctor (bimap, first, second)
|
||||
import Simplex.Messaging.Agent.Client (SubInfo (..), getAgentQueuesInfo, getAgentWorkersDetails, getAgentWorkersSummary, temporaryOrHostError)
|
||||
import Simplex.Messaging.Agent.Client (SubInfo (..), cancelWorker, getAgentQueuesInfo, getAgentWorkersDetails, getAgentWorkersSummary, temporaryOrHostError)
|
||||
#else
|
||||
import Data.Bifunctor (bimap, first, second)
|
||||
import qualified Data.ByteArray as BA
|
||||
import qualified Database.SQLite.Simple as SQL
|
||||
import Simplex.Chat.Archive
|
||||
import Simplex.Messaging.Agent.Client (SubInfo (..), agentClientStore, getAgentQueuesInfo, getAgentWorkersDetails, getAgentWorkersSummary, temporaryOrHostError)
|
||||
import Simplex.Messaging.Agent.Client (SubInfo (..), agentClientStore, cancelWorker, getAgentQueuesInfo, getAgentWorkersDetails, getAgentWorkersSummary, temporaryOrHostError)
|
||||
import Simplex.Messaging.Agent.Store.Common (withConnection)
|
||||
import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..))
|
||||
#endif
|
||||
@@ -346,11 +347,19 @@ restoreCalls = do
|
||||
atomically $ writeTVar calls callsMap
|
||||
|
||||
stopChatController :: ChatController -> IO ()
|
||||
stopChatController ChatController {smpAgent, agentAsync = s, sndFiles, rcvFiles, expireCIFlags, remoteHostSessions, remoteCtrlSession} = do
|
||||
stopChatController ChatController {smpAgent, agentAsync = s, sndFiles, rcvFiles, expireCIFlags, remoteHostSessions, remoteCtrlSession, cleanupManagerAsync, relayGroupLinkChecksAsync, webPreviewState, expireCIThreads, timedItemThreads, deliveryTaskWorkers, deliveryJobWorkers, relayRequestWorkers} = do
|
||||
readTVarIO remoteHostSessions >>= mapM_ (cancelRemoteHost False . snd)
|
||||
atomically (stateTVar remoteCtrlSession (,Nothing)) >>= mapM_ (cancelRemoteCtrl False . snd)
|
||||
disconnectAgentClient smpAgent
|
||||
readTVarIO s >>= mapM_ (\(a1, a2) -> forkIO $ uninterruptibleCancel a1 >> mapM_ uninterruptibleCancel a2)
|
||||
readTVarIO s >>= mapM_ (\(a1, a2) -> uninterruptibleCancel a1 >> mapM_ uninterruptibleCancel a2)
|
||||
cancelAsync cleanupManagerAsync
|
||||
cancelAsync relayGroupLinkChecksAsync
|
||||
forM_ webPreviewState $ \WebPreviewState {webPreviewWorkerAsync} -> cancelAsync webPreviewWorkerAsync
|
||||
clearMap expireCIThreads >>= mapM_ (mapM_ uninterruptibleCancel)
|
||||
clearMap timedItemThreads >>= mapM_ (readTVarIO >=> mapM_ (deRefWeak >=> mapM_ killThread))
|
||||
clearMap deliveryTaskWorkers >>= mapM_ cancelWorker
|
||||
clearMap deliveryJobWorkers >>= mapM_ cancelWorker
|
||||
clearMap relayRequestWorkers >>= mapM_ cancelWorker
|
||||
closeFiles sndFiles
|
||||
closeFiles rcvFiles
|
||||
atomically $ do
|
||||
@@ -358,6 +367,10 @@ stopChatController ChatController {smpAgent, agentAsync = s, sndFiles, rcvFiles,
|
||||
forM_ keys $ \k -> TM.insert k False expireCIFlags
|
||||
writeTVar s Nothing
|
||||
where
|
||||
cancelAsync :: TVar (Maybe (Async ())) -> IO ()
|
||||
cancelAsync a = atomically (swapTVar a Nothing) >>= mapM_ uninterruptibleCancel
|
||||
clearMap :: TM.TMap k a -> IO (Map k a)
|
||||
clearMap m = atomically $ swapTVar m M.empty
|
||||
closeFiles :: TVar (Map Int64 Handle) -> IO ()
|
||||
closeFiles files = do
|
||||
fs <- readTVarIO files
|
||||
|
||||
@@ -24,7 +24,7 @@ module Simplex.Chat.Web
|
||||
where
|
||||
|
||||
import Control.Concurrent.STM (check, flushTQueue)
|
||||
import Control.Exception (SomeException, catch)
|
||||
import Control.Exception (SomeException)
|
||||
import Control.Logger.Simple
|
||||
import Control.Monad
|
||||
import Control.Monad.Except (runExceptT)
|
||||
@@ -75,7 +75,7 @@ import Simplex.Chat.Types
|
||||
)
|
||||
import Simplex.Messaging.Agent.Store.Common (withTransaction)
|
||||
import Simplex.Messaging.Encoding.String (strEncode)
|
||||
import Simplex.Messaging.Util (catchOwn, eitherToMaybe, safeDecodeUtf8, tshow)
|
||||
import Simplex.Messaging.Util (catchOwn, catchOwn', eitherToMaybe, safeDecodeUtf8, tshow)
|
||||
import Simplex.Messaging.Parsers (defaultJSON)
|
||||
import System.Directory (createDirectoryIfMissing, listDirectory, removeFile, renameFile)
|
||||
import System.FilePath (dropExtension, takeExtension, (</>))
|
||||
@@ -150,7 +150,7 @@ webPreviewWorker cfg@WebPreviewConfig {webJsonDir, webCorsFile, webUpdateInterva
|
||||
drainRemovals = atomically (tryReadTQueue filesToRemove) >>= \case
|
||||
Nothing -> pure ()
|
||||
Just f -> do
|
||||
removeFile (webJsonDir </> f) `catch` \(_ :: SomeException) -> pure ()
|
||||
removeFile (webJsonDir </> f) `catchOwn'` \(_ :: SomeException) -> pure ()
|
||||
drainRemovals
|
||||
|
||||
-- flush the whole queue and render each group once: a burst of changes in one
|
||||
@@ -202,7 +202,7 @@ webPreviewWorker cfg@WebPreviewConfig {webJsonDir, webCorsFile, webUpdateInterva
|
||||
renderOneGroup WebPreviewState {publishableGroupIds} gId = do
|
||||
publishable <- atomically $ M.member gId <$> readTVar publishableGroupIds
|
||||
when publishable $
|
||||
renderOrRemoveStale `catch` \(e :: SomeException) ->
|
||||
renderOrRemoveStale `catchOwn'` \(e :: SomeException) ->
|
||||
logError $ "web preview: error rendering group " <> T.pack (show gId) <> ": " <> T.pack (show e)
|
||||
where
|
||||
renderOrRemoveStale = do
|
||||
@@ -217,7 +217,7 @@ webPreviewWorker cfg@WebPreviewConfig {webJsonDir, webCorsFile, webUpdateInterva
|
||||
modifyTVar' publishableGroupIds (M.delete gId)
|
||||
pure $ pgFileName <$> pg
|
||||
forM_ fName $ \f ->
|
||||
removeFile (webJsonDir </> f) `catch` \(_ :: SomeException) -> pure ()
|
||||
removeFile (webJsonDir </> f) `catchOwn'` \(_ :: SomeException) -> pure ()
|
||||
logInfo $ "web preview: group " <> T.pack (show gId) <> " no longer publishable"
|
||||
|
||||
findUser f = go users
|
||||
|
||||
Reference in New Issue
Block a user