<commit_before>{-# LANGUAGE PatternSynonyms   #-}
{-# LANGUAGE DoAndIfThenElse   #-}
{-# LANGUAGE OverloadedStrings #-}

module Unison.Codebase.Watch where

import Unison.Prelude

import           UnliftIO.Concurrent            ( forkIO
                                                , threadDelay
                                                , killThread
                                                )
import           UnliftIO                       ( MonadUnliftIO
                                                , withRunInIO )
import           UnliftIO.MVar                  ( newEmptyMVar, takeMVar
                                                , tryTakeMVar, putMVar )
import           UnliftIO.STM                   ( atomically )
import           UnliftIO.Exception             ( catch, IOException)
import           UnliftIO.IORef                 ( newIORef
                                                , readIORef
                                                , writeIORef
                                                )
import qualified Data.Map                      as Map
import qualified Data.Text.IO
import           Data.Time.Clock                ( UTCTime
                                                , diffUTCTime
                                                )
import           System.FSNotify                ( Event(Added, Modified)
                                                , watchTree
                                                , withManagerConf
                                                , defaultConfig
                                                , confDebounce
                                                , Debounce (NoDebounce)
                                                )
import           Unison.Util.TQueue             ( TQueue )
import qualified Unison.Util.TQueue            as TQueue

watchDirectory'
  :: forall m. MonadUnliftIO m => FilePath -> m (m (), m (FilePath, UTCTime))
watchDirectory' d = do
    mvar <- newEmptyMVar
    let handler :: Event -> m ()
        handler e = case e of
          Added    fp t False -> doIt fp t
          Modified fp t False -> doIt fp t
          _                   -> pure ()
          where doIt fp t = do
                  _ <- tryTakeMVar mvar
                  putMVar mvar (fp, t)
        watchConfig = defaultConfig { confDebounce = NoDebounce }
    -- janky: used to store the cancellation action returned
    -- by `watchTree`, which is created asynchronously
    cleanupRef <- newEmptyMVar
    cancel <- forkIO $ withRunInIO $ \inIO ->
      withManagerConf watchConfig $ \mgr -> do
        cancelInner <- watchTree mgr d (const True) (inIO . handler) <|> (pure (pure ()))
        putMVar cleanupRef $ liftIO cancelInner
        forever $ threadDelay 1000000
    let cleanup :: m ()
        cleanup = join (takeMVar cleanupRef) >> killThread cancel<commit_msg>Revert "Disable debouncing in the file watcher, experimenting on #625"<commit_after>{-# LANGUAGE PatternSynonyms   #-}
{-# LANGUAGE DoAndIfThenElse   #-}
{-# LANGUAGE OverloadedStrings #-}

module Unison.Codebase.Watch where

import Unison.Prelude

import           UnliftIO.Concurrent            ( forkIO
                                                , threadDelay
                                                , killThread
                                                )
import           UnliftIO                       ( MonadUnliftIO
                                                , withRunInIO )
import           UnliftIO.MVar                  ( newEmptyMVar, takeMVar
                                                , tryTakeMVar, putMVar )
import           UnliftIO.STM                   ( atomically )
import           UnliftIO.Exception             ( catch, IOException)
import           UnliftIO.IORef                 ( newIORef
                                                , readIORef
                                                , writeIORef
                                                )
import qualified Data.Map                      as Map
import qualified Data.Text.IO
import           Data.Time.Clock                ( UTCTime
                                                , diffUTCTime
                                                )
import           System.FSNotify                ( Event(Added, Modified)
                                                , watchTree
                                                , withManager
                                                )
import           Unison.Util.TQueue             ( TQueue )
import qualified Unison.Util.TQueue            as TQueue

watchDirectory'
  :: forall m. MonadUnliftIO m => FilePath -> m (m (), m (FilePath, UTCTime))
watchDirectory' d = do
    mvar <- newEmptyMVar
    let handler :: Event -> m ()
        handler e = case e of
          Added    fp t False -> doIt fp t
          Modified fp t False -> doIt fp t
          _                   -> pure ()
          where doIt fp t = do
                  _ <- tryTakeMVar mvar
                  putMVar mvar (fp, t)
    -- janky: used to store the cancellation action returned
    -- by `watchTree`, which is created asynchronously
    cleanupRef <- newEmptyMVar
    cancel <- forkIO $ withRunInIO $ \inIO ->
      withManager $ \mgr -> do
        cancelInner <- watchTree mgr d (const True) (inIO . handler) <|> (pure (pure ()))
        putMVar cleanupRef $ liftIO cancelInner
        forever $ threadDelay 1000000
    let cleanup :: m ()
        cleanup = join (takeMVar cleanupRef) >> killThread cancel
{'fraction_non_alphanumeric': 0.060316888728844074, 'fraction_numerical': 0.003060857039971192, 'mean_word_length': 0.9423076923076923, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 60, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '970708', 'n_tokens_mistral': 1252, 'n_tokens_neox': 1157, 'n_words': 347}