module Cachix.Client.WatchStore
  ( startWorkers,
  )
where

import Cachix.Client.Push
import qualified Cachix.Client.PushQueue as PushQueue
import qualified Control.Concurrent.STM.TBQueue as TBQueue
import Data.List (isSuffixOf)
import Protolude
import System.FSNotify

startWorkers :: Int -> PushParams IO () -> IO ()
startWorkers :: Int -> PushParams IO () -> IO ()
startWorkers numWorkers :: Int
numWorkers pushParams :: PushParams IO ()
pushParams = do
  (WatchManager -> IO ()) -> IO ()
forall a. (WatchManager -> IO a) -> IO a
withManager ((WatchManager -> IO ()) -> IO ())
-> (WatchManager -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \mgr :: WatchManager
mgr -> Int -> (Queue -> IO (IO ())) -> PushParams IO () -> IO ()
PushQueue.startWorkers Int
numWorkers (WatchManager -> Queue -> IO (IO ())
producer WatchManager
mgr) PushParams IO ()
pushParams

producer :: WatchManager -> PushQueue.Queue -> IO (IO ())
producer :: WatchManager -> Queue -> IO (IO ())
producer mgr :: WatchManager
mgr queue :: Queue
queue = do
  Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putText "Watching /nix/store for new store paths ..."
  WatchManager -> FilePath -> ActionPredicate -> Action -> IO (IO ())
watchDir WatchManager
mgr "/nix/store" ActionPredicate
filterOnlyStorePaths (Queue -> Action
queueStorePathAction Queue
queue)

queueStorePathAction :: PushQueue.Queue -> Event -> IO ()
queueStorePathAction :: Queue -> Action
queueStorePathAction queue :: Queue
queue (Removed lockFile :: FilePath
lockFile _ _) = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ Queue -> Text -> STM ()
forall a. TBQueue a -> a -> STM ()
TBQueue.writeTBQueue Queue
queue (FilePath -> Text
forall a b. ConvertText a b => a -> b
toS (FilePath -> Text) -> FilePath -> Text
forall a b. (a -> b) -> a -> b
$ Int -> FilePath -> FilePath
forall a. Int -> [a] -> [a]
dropLast 5 FilePath
lockFile)
queueStorePathAction _ _ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

dropLast :: Int -> [a] -> [a]
dropLast :: Int -> [a] -> [a]
dropLast index :: Int
index xs :: [a]
xs = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
index) [a]
xs

-- we queue store paths after their lock has been removed
filterOnlyStorePaths :: ActionPredicate
filterOnlyStorePaths :: ActionPredicate
filterOnlyStorePaths (Removed fp :: FilePath
fp _ _)
  | ".drv.lock" FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` FilePath
fp = Bool
False
  | ".lock" FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` FilePath
fp = Bool
True
filterOnlyStorePaths _ = Bool
False