packages feed

cachix-1.7.5: src/Cachix/Client/WatchStore.hs

module Cachix.Client.WatchStore
  ( startWorkers,
  )
where

import Cachix.Client.CNix (filterInvalidStorePath)
import Cachix.Client.Push
import Cachix.Client.PushQueue qualified as PushQueue
import Control.Concurrent.STM.TBQueue qualified as TBQueue
import Hercules.CNix.Store (Store)
import Hercules.CNix.Store qualified as Store
import Protolude
import System.FSNotify
import System.Systemd.Daemon qualified as Systemd

startWorkers :: Store -> Int -> PushParams IO () -> IO ()
startWorkers store numWorkers pushParams = do
  void Systemd.notifyReady
  withManager $ \mgr -> PushQueue.startWorkers numWorkers (producer store mgr) pushParams

producer :: Store -> WatchManager -> PushQueue.Queue -> IO (IO ())
producer store mgr queue = do
  putErrText "Watching /nix/store for new store paths ..."
  watchDir mgr "/nix/store" filterOnlyStorePaths (queueStorePathAction store queue)

queueStorePathAction :: Store -> PushQueue.Queue -> Event -> IO ()
queueStorePathAction store queue (Removed lockFile _ _) = do
  sp <- Store.parseStorePath store (encodeUtf8 $ toS $ dropLast 5 lockFile)
  filterInvalidStorePath store sp >>= \case
    Nothing -> return ()
    Just p -> atomically $ TBQueue.writeTBQueue queue p
queueStorePathAction _ _ _ = return ()

dropLast :: Int -> [a] -> [a]
dropLast index xs = take (length xs - index) xs

-- we queue store paths after their lock has been removed
filterOnlyStorePaths :: ActionPredicate
filterOnlyStorePaths (Removed fp _ _)
  | ".drv.lock" `isSuffixOf` fp = False
  | ".lock" `isSuffixOf` fp = True
filterOnlyStorePaths _ = False