There is a thread waiting for new input in a queue to safe it to the file system. It also creates backup copies. The sscce looks like this:
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import Data.Time.Clock.POSIX
main :: IO ()
main = do
contentQueue <- atomically $ newTQueue
_ <- forkIO $ saveThreadFunc contentQueue
forever $ do
line <- getLine
atomically $ writeTQueue contentQueue line
saveThreadFunc :: TQueue String -> IO ()
saveThreadFunc queue = forever $ do
newLine <- atomically $ readTQueue queue
now <- round `fmap` getPOSIXTime :: IO Int
writeFile "content.txt" newLine
-- todo: Backup no more than once every 86400 seconds (24 hours).
backupContent now newLine
backupContent :: Int -> String -> IO ()
backupContent t = writeFile $ "content.backup." ++ show t
Now it would be great if the backup would not be written more than once every 24 hours. In imperative programming I would probably use a mutable int lastBackupTime
inside the "forever loop" in saveThreadFunc
. How can the same effect be achieved in Haskell?
How about Control.Monad.Loops.iterateM_
? This is slightly neater as it avoids explict recursion.
iterateM_ :: Monad m => (a -> m a) -> a -> m b
saveThreadFunc :: TQueue String -> Int -> IO ()
saveThreadFunc queue = iterateM_ $ \lastBackupTime -> do
newLine <- atomically $ readTQueue queue
now <- round `fmap` getPOSIXTime :: IO Int
writeFile "content.txt" newLine
let makeNewBackup = now >= lastBackupTime + 86400
when makeNewBackup (backupContent now newLine)
return (if makeNewBackup then now else lastBackupTime)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With