-- | A simple implementation of /incremental build rules/, which can be used to avoid unnecessary
-- recomputation on incrementally-changing input. See 'Rule' for more details.
module Hasura.Incremental
  ( -- * The @Rule@ datatype
    Rule,
    Result,
    build,
    rebuild,
    rebuildRule,
    result,

    -- * Abstract interface
    ArrowDistribute (..),
    ArrowCache (..),
    MonadDepend (..),
    DependT,

    -- * Fine-grained dependencies
    Dependency,
    Select (Selector),
    selectD,
    selectKeyD,
    Cacheable (..),
    Accesses,

    -- * Cache invalidation
    InvalidationKey,
    initialInvalidationKey,
    invalidate,
  )
where

import Hasura.Incremental.Internal.Cache
import Hasura.Incremental.Internal.Dependency
import Hasura.Incremental.Internal.Rule
import Hasura.Incremental.Select
import Hasura.Prelude

-- | A simple helper type that can be used to implement explicit cache invalidation. Internally,
-- each 'InvalidationKey' is a counter; 'initialInvalidationKey' starts the counter at 0 and
-- 'invalidate' increments it by 1. Two 'InvalidationKey's are equal iff they have the same internal
-- count, so depending on an 'InvalidationKey' provides a mechanism to force portions of the build
-- process to be reexecuted by calling 'invalidate' before running the build.
newtype InvalidationKey = InvalidationKey Int
  deriving (Int -> InvalidationKey -> ShowS
[InvalidationKey] -> ShowS
InvalidationKey -> String
(Int -> InvalidationKey -> ShowS)
-> (InvalidationKey -> String)
-> ([InvalidationKey] -> ShowS)
-> Show InvalidationKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InvalidationKey] -> ShowS
$cshowList :: [InvalidationKey] -> ShowS
show :: InvalidationKey -> String
$cshow :: InvalidationKey -> String
showsPrec :: Int -> InvalidationKey -> ShowS
$cshowsPrec :: Int -> InvalidationKey -> ShowS
Show, InvalidationKey -> InvalidationKey -> Bool
(InvalidationKey -> InvalidationKey -> Bool)
-> (InvalidationKey -> InvalidationKey -> Bool)
-> Eq InvalidationKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InvalidationKey -> InvalidationKey -> Bool
$c/= :: InvalidationKey -> InvalidationKey -> Bool
== :: InvalidationKey -> InvalidationKey -> Bool
$c== :: InvalidationKey -> InvalidationKey -> Bool
Eq, Eq InvalidationKey
Eq InvalidationKey
-> (Accesses -> InvalidationKey -> InvalidationKey -> Bool)
-> Cacheable InvalidationKey
Accesses -> InvalidationKey -> InvalidationKey -> Bool
forall a. Eq a -> (Accesses -> a -> a -> Bool) -> Cacheable a
unchanged :: Accesses -> InvalidationKey -> InvalidationKey -> Bool
$cunchanged :: Accesses -> InvalidationKey -> InvalidationKey -> Bool
$cp1Cacheable :: Eq InvalidationKey
Cacheable)

initialInvalidationKey :: InvalidationKey
initialInvalidationKey :: InvalidationKey
initialInvalidationKey = Int -> InvalidationKey
InvalidationKey Int
0

invalidate :: InvalidationKey -> InvalidationKey
invalidate :: InvalidationKey -> InvalidationKey
invalidate (InvalidationKey Int
n) = Int -> InvalidationKey
InvalidationKey (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)