content: {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE LambdaCase #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedStrings #-}
  
  import Control.Monad.Logger (runNoLoggingT, runStdoutLoggingT)
  import Data.Pool (destroyAllResources)
  import Database.Persist.Postgresql (PostgresConf(..), createPostgresqlPool)
  import Database.Persist.Sql (ConnectionPool, SqlBackend, runSqlPool)
  import Gauge
  import Pantry.Internal.Stackage (PackageNameP(..))
  import RIO
  import Settings (getAppSettings, AppSettings(..), DatabaseSettings(..), configSettingsYmlValue)
  import Stackage.Database.Query
  import Stackage.Database.Schema (withStackageDatabase, runDatabase)
  import Stackage.Database.Types (LatestInfo, SnapName(..), SnapshotPackageInfo(..))
  import Yesod.Default.Config2
  
  main :: IO ()
  main = do
      appSettings <- getAppSettings
      let snapName = SNLts 16 4
      mSnapInfo <-
          runSimpleApp $
          withStackageDatabase
              True
              (appDatabase appSettings)
              (\db -> runDatabase db $ getSnapshotPackageInfoQuery snapName (PackageNameP "yesod"))
      let snapInfo = fromMaybe (error "snapInfo not retrieved") mSnapInfo
      defaultMain [benchs snapInfo]
  
  runBenchApp :: ConnectionPool -> ReaderT SqlBackend (RIO SimpleApp) a -> IO a
  runBenchApp pool m = runSimpleApp $ runSqlPool m pool
  
  createBenchPool :: IO ConnectionPool
  createBenchPool = do
      loadYamlSettingsArgs [configSettingsYmlValue] useEnv >>= \case
          AppSettings{appDatabase = DSPostgres pgString _} ->
              runNoLoggingT $ createPostgresqlPool (encodeUtf8 pgString) 1
          _ -> throwString "Benchmarks are crafted for PostgreSQL"
  
  releasePool :: ConnectionPool -> IO ()
  releasePool = destroyAllResources
  
  -- TODO: Upstream fix ? Or add new function to gauge (although it
  -- seems it might be a breaking change there) ?
  instance NFData ConnectionPool where
      rnf _ = ()
  
  getLatestsBench :: Benchmark
  getLatestsBench =
      bench "getLatests" $
      perBatchEnvWithCleanup
          (\runs -> createBenchPool)
          (\_ pool -> releasePool pool)
          (\pool -> runBenchApp pool (void $ getLatests $ PackageNameP "yesod"))
  
  getDeprecatedBench :: Benchmark
  getDeprecatedBench =
      bench "getDeprecated" $
      perBatchEnvWithCleanup
          (\runs -> createBenchPool)
          (\_ pool -> releasePool pool)
          (\pool -> runBenchApp pool (void $ getDeprecatedQuery $ PackageNameP "yesod"))
  
  getSnapshotPackageLatestVersionBench :: Benchmark
  getSnapshotPackageLatestVersionBench =
      bench "getSnapshotPackageLatestVersion" $
      perBatchEnvWithCleanup
          (\runs -> createBenchPool)
          (\_ pool -> releasePool pool)
          (\pool ->
               runBenchApp pool (void $ getSnapshotPackageLatestVersionQuery $ PackageNameP "yesod"))
  
  getSnapshotPackagePageInfoBench :: SnapshotPackageInfo -> Benchmark
  getSnapshotPackagePageInfoBench snapshotInfo =
      bench "getSnapshotPackagePageInfo" $
      perBatchEnvWithCleanup
          (\runs -> createBenchPool)
          (\_ pool -> releasePool pool)
          (\pool -> runBenchApp pool (void $ getSnapshotPackagePageInfoQuery snapshotInfo 40))
  
  getPackageInfoBench :: SnapshotPackageInfo -> Benchmark
  getPackageInfoBench snapInfo =
      bench "getPackageInfo" $
      perBatchEnvWithCleanup
          (\runs -> createBenchPool)
          (\_ pool -> releasePool pool)
          (\pool -> runBenchApp pool (void $ getPackageInfoQuery (Right snapInfo)))
  
  getHackageLatestVersionBench :: Benchmark
  getHackageLatestVersionBench =
      bench "getHackageLatestVersion" $
      perBatchEnvWithCleanup
          (\runs -> createBenchPool)
          (\_ pool -> releasePool pool)
          (\pool -> runBenchApp pool (void $ getHackageLatestVersion $ PackageNameP "yesod"))
  
  benchs :: SnapshotPackageInfo -> Benchmark
  benchs snap =
      bgroup
          "SQL Query Benchmark"
          [ getLatestsBench
          , getDeprecatedBench
          , getHackageLatestVersionBench
          , getPackageInfoBench snap
          , getSnapshotPackagePageInfoBench snap
          , getSnapshotPackageLatestVersionBench
          ]
  