{-| Module : Gargantext.Utils.UTCTime Description : Gargantext utilities Copyright : (c) CNRS, 2017 License : AGPL + CECILL v3 Maintainer : team@gargantext.org Stability : experimental Portability : POSIX -} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE TypeApplications #-} module Gargantext.Utils.UTCTime where import Data.Fixed (Fixed(..)) import Data.Morpheus.Kind (SCALAR) import Data.Morpheus.Types (GQLType(..), DecodeScalar(..), EncodeScalar(..)) import Data.Morpheus.Types qualified as DMT import Data.String (fromString) import Data.Swagger (ToSchema (..)) import Data.Text qualified as T import Data.Time.Clock.POSIX (getPOSIXTime, POSIXTime) import Data.Time (UTCTime, nominalDiffTimeToSeconds) import Data.TreeDiff.Class import Gargantext.Prelude import Gargantext.System.Logging import Prelude (String) import Test.QuickCheck hiding (label) newtype NUTCTime = NUTCTime UTCTime deriving (Eq, Show, Generic) deriving newtype NFData instance DecodeScalar NUTCTime where decodeScalar (DMT.String x) = case (readEither $ T.unpack x) of Right r -> pure $ NUTCTime r Left err -> Left $ T.pack err decodeScalar _ = Left "Invalid value for NUTCTime" instance EncodeScalar NUTCTime where encodeScalar (NUTCTime x) = DMT.String $ T.pack $ show x instance GQLType NUTCTime where type KIND NUTCTime = SCALAR instance FromJSON NUTCTime instance ToJSON NUTCTime instance ToSchema NUTCTime newtype ElapsedSeconds = ElapsedSeconds { _Seconds :: POSIXTime } deriving stock (Show, Eq, Generic) deriving newtype (FromJSON, ToJSON, Num) instance NFData ElapsedSeconds instance ToExpr ElapsedSeconds where toExpr (ElapsedSeconds x) = let (MkFixed secs) = nominalDiffTimeToSeconds x in toExpr secs instance ToSchema ElapsedSeconds where declareNamedSchema _ = declareNamedSchema (Proxy @Int) instance Arbitrary ElapsedSeconds where arbitrary = ElapsedSeconds . fromInteger . getPositive <$> arbitrary timeMeasured :: (MonadLogger m, MonadBase IO m, HasCallStack) => String -- ^ A label -> m a -- ^ The action to run -> m a timeMeasured = withFrozenCallStack $ timeMeasured' DEBUG -- | A version of timeMeasured that also returns the elapsed time, in seconds. timeMeasured'' :: (MonadLogger m, MonadBase IO m, HasCallStack) => LogLevel -- ^ The severity of the log -> String -- ^ A label to identify the action. -> m a -- ^ The action to run -> m (ElapsedSeconds, a) timeMeasured'' severity label action = withFrozenCallStack $ do startTime <- liftBase getPOSIXTime res <- action endTime <- liftBase getPOSIXTime let finalTime = endTime - startTime let msg = label <> " took " <> (show finalTime) <> " seconds to execute." $(logLocM) severity (fromString msg) pure (ElapsedSeconds finalTime, res) timeMeasured' :: (MonadLogger m, MonadBase IO m, HasCallStack) => LogLevel -- ^ The severity of the log -> String -- ^ A label to identify the action. -> m a -- ^ The action to run -> m a timeMeasured' severity label action = withFrozenCallStack $ snd <$> timeMeasured'' severity label action