@@ -37,14 +37,16 @@ import Control.Applicative (optional, (<|>))
3737import Control.Concurrent.STM
3838import qualified Control.Exception as E
3939import Control.Logger.Simple
40- import Control.Monad ( when )
40+ import Control.Monad
4141import qualified Data.Attoparsec.ByteString.Char8 as A
4242import qualified Data.ByteString.Char8 as B
4343import Data.Functor (($>) )
44+ import Data.List (sort , stripPrefix )
4445import qualified Data.Map.Strict as M
46+ import Data.Maybe (mapMaybe )
4547import qualified Data.Text as T
46- import Data.Time.Clock (getCurrentTime )
47- import Data.Time.Format.ISO8601 (iso8601Show )
48+ import Data.Time.Clock (UTCTime , addUTCTime , getCurrentTime , nominalDay )
49+ import Data.Time.Format.ISO8601 (iso8601Show , iso8601ParseM )
4850import GHC.IO (catchAny )
4951import Simplex.Messaging.Encoding.String
5052import Simplex.Messaging.Protocol
@@ -53,8 +55,9 @@ import Simplex.Messaging.Server.QueueStore
5355import Simplex.Messaging.Server.StoreLog.Types
5456import qualified Simplex.Messaging.TMap as TM
5557import Simplex.Messaging.Util (ifM , tshow , unlessM , whenM )
56- import System.Directory (doesFileExist , renameFile )
58+ import System.Directory (doesFileExist , listDirectory , removeFile , renameFile )
5759import System.IO
60+ import System.FilePath (takeDirectory , takeFileName )
5861
5962data StoreLogRecord
6063 = CreateQueue RecipientId QueueRec
@@ -237,6 +240,7 @@ readWriteStoreLog readStore writeStore f st =
237240 renameFile f tempBackup -- 1) make temp backup
238241 s <- writeLog " compacting store log (do not terminate)..." -- 2) save state
239242 renameBackup -- 3) timed backup
243+ removeStoreLogBackups f
240244 pure s
241245 writeLog msg = do
242246 s <- openWriteStoreLog f
@@ -258,6 +262,27 @@ writeQueueStore s st = readTVarIO qs >>= mapM_ writeQueue . M.assocs
258262 Just q' -> logCreateQueue s rId q'
259263 Nothing -> atomically $ TM. delete rId qs
260264
265+ removeStoreLogBackups :: FilePath -> IO ()
266+ removeStoreLogBackups f = do
267+ ts <- getCurrentTime
268+ times <- sort . mapMaybe backupPathTime <$> listDirectory (takeDirectory f)
269+ let new = addUTCTime (- nominalDay) ts
270+ old = addUTCTime (- oldBackupTTL) ts
271+ times1 = filter (< new) times -- exclude backups newer than 24 hours
272+ times2 = take (length times1 - minOldBackups) times1 -- keep 3 backups older than 24 hours
273+ toDelete = filter (< old) times2 -- remove all backups older than 21 day
274+ mapM_ (removeFile . backupPath) toDelete
275+ putStrLn $ " Removed " <> show (length toDelete) <> " backups:"
276+ mapM_ (putStrLn . backupPath) toDelete
277+ where
278+ backupPathTime :: FilePath -> Maybe UTCTime
279+ backupPathTime = iso8601ParseM <=< stripPrefix backupPathPfx
280+ backupPath :: UTCTime -> FilePath
281+ backupPath ts = f <> " ." <> iso8601Show ts
282+ backupPathPfx = takeFileName f <> " ."
283+ minOldBackups = 3
284+ oldBackupTTL = 21 * nominalDay
285+
261286readLogLines :: Bool -> FilePath -> (Bool -> B. ByteString -> IO () ) -> IO ()
262287readLogLines tty f action = foldLogLines tty f (const action) ()
263288
0 commit comments