hunk.code_window: <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   	 viewBox="0 0 85 95" style="enable-background:new 0 0 85 95;" xml:space="preserve">
   <style type="text/css">
   	.st0{fill:#102954;}
   </style>
   <g>
   	<g>
   		<path class="st0" d="M79.9,31.8c2.6-6.3,2.6-19.1-0.8-28.9l0,0c-0.9-1.8-3.6-1.2-3.7,0.7v0.7c-0.6,9.4-4,14.5-9.1,17
   			c-0.8,0.4-2.1,0.4-3-0.2c-6-3.8-13.2-6-20.9-6s-14.8,2.3-20.9,6c-0.8,0.5-1.8,0.6-2.6,0.2c-5.2-1.9-8.8-7.6-9.4-17.1V3.5
  
hunk.labels: keep keep keep replace keep keep keep keep keep
hunk.after_edit: 	.st0{fill:#001934;}
  
hunk.file_path: assets/brand/hasura_icon_blue.svg
hunk.type: replace
file: module Hasura.GraphQL.Execute.Plan
    ( ReusablePlan(..)
    , PlanCache
    , PlanCacheOptions
    , mkPlanCacheOptions
    , getPlan
    , addPlan
    , initPlanCache
    , clearPlanCache
    , dumpPlanCache
    ) where
  
  import           Hasura.Prelude
  
  import qualified Data.Aeson                             as J
  import qualified Data.Aeson.Casing                      as J
  import qualified Data.Aeson.TH                          as J
  
  import qualified Hasura.Cache                           as Cache
  import qualified Hasura.GraphQL.Execute.LiveQuery       as LQ
  import qualified Hasura.GraphQL.Execute.Query           as EQ
  import qualified Hasura.GraphQL.Transport.HTTP.Protocol as GH
  import           Hasura.RQL.Types
  
  data PlanId
    = PlanId
    { _piSchemaCacheVersion :: !SchemaCacheVer
    , _piRole               :: !RoleName
    , _piOperationName      :: !(Maybe GH.OperationName)
    , _piQuery              :: !GH.GQLQueryText
    } deriving (Show, Eq, Ord, Generic)
  
  instance Hashable PlanId
  
  instance J.ToJSON PlanId where
    toJSON (PlanId scVer rn opNameM query) =
      J.object
      [ "schema_cache_version" J..= scVer
      , "role" J..= rn
      , "operation" J..= opNameM
      , "query" J..= query
      ]
  
  newtype PlanCache
    = PlanCache {_unPlanCache :: Cache.Cache PlanId ReusablePlan}
  
  data ReusablePlan
    = RPQuery !EQ.ReusableQueryPlan
    | RPSubs !LQ.ReusableLiveQueryPlan
  
  instance J.ToJSON ReusablePlan where
    toJSON = \case
      RPQuery queryPlan -> J.toJSON queryPlan
      RPSubs subsPlan -> J.toJSON subsPlan
  
  newtype PlanCacheOptions
    = PlanCacheOptions { unPlanCacheSize :: Maybe Cache.CacheSize }
    deriving (Show, Eq)
  $(J.deriveJSON (J.aesonDrop 2 J.snakeCase) ''PlanCacheOptions)
  
  mkPlanCacheOptions :: Maybe Cache.CacheSize -> PlanCacheOptions
  mkPlanCacheOptions = PlanCacheOptions
  
  initPlanCache :: PlanCacheOptions -> IO PlanCache
  initPlanCache options =
    PlanCache <$>
    Cache.initialise (Cache.mkCacheOptions $ unPlanCacheSize options)
  
  getPlan
    :: SchemaCacheVer -> RoleName -> Maybe GH.OperationName -> GH.GQLQueryText
    -> PlanCache -> IO (Maybe ReusablePlan)
  getPlan schemaVer rn opNameM q (PlanCache planCache) =
    Cache.lookup planId planCache
    where
      planId = PlanId schemaVer rn opNameM q
  
  addPlan
    :: SchemaCacheVer -> RoleName -> Maybe GH.OperationName -> GH.GQLQueryText
    -> ReusablePlan -> PlanCache -> IO ()
  addPlan schemaVer rn opNameM q queryPlan (PlanCache planCache) =
    Cache.insert planId queryPlan planCache
    where
      planId = PlanId schemaVer rn opNameM q
  
  clearPlanCache :: PlanCache -> IO ()
  clearPlanCache (PlanCache planCache) =
    Cache.clear planCache
  
  dumpPlanCache :: PlanCache -> IO J.Value
  dumpPlanCache (PlanCache cache) =
    J.toJSON . map (map dumpEntry) <$> Cache.getEntries cache
    where
      dumpEntry (planId, plan) =
        J.object
        [ "id" J..= planId
        , "plan" J..= plan
        ]
  