perf: skip favouriteQuickActions under db conn pressure

This commit is contained in:
Gregor Kleen 2021-03-08 12:55:48 +01:00
parent 63f0d3c37a
commit 55a9c8a5ae
5 changed files with 42 additions and 13 deletions

View File

@ -1,6 +1,7 @@
module Foundation.DB
( runDBRead, runDBRead'
, runSqlPoolRetry, runSqlPoolRetry'
, dbPoolPressured
) where
import Import.NoFoundation hiding (runDB, getDBRunner)
@ -61,3 +62,13 @@ runDBRead' :: CallStack -> ReaderT SqlReadBackend (HandlerFor UniWorX) a -> (Han
runDBRead' lbl action = do
$logDebugS "YesodPersist" "runDBRead"
flip (runSqlPoolRetry' . withReaderT SqlReadBackend $ [executeQQ|SET TRANSACTION READ ONLY|] *> action) lbl . appConnPool =<< getYesod
dbPoolPressured :: ( MonadHandler m
, HandlerSite m ~ UniWorX
)
=> m Bool
dbPoolPressured = do
connPool <- getsYesod @_ @(Custom.Pool' IO _ _ _) appConnPool
case Custom.getPoolMaxAvailable connPool of
Nothing -> return False
Just lim -> atomically $ (>= lim) <$> Custom.getPoolInUseCount connPool

View File

@ -191,18 +191,21 @@ siteLayout' overrideHeading widget = do
langs <- selectLanguages appLanguages <$> languages
let cK = MemcachedKeyFavouriteQuickActions (tid, ssh, csh) ctx langs
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Checking..."
items <- memcachedLimitedKeyTimeoutBy
MemcachedLimitKeyFavourites appFavouritesQuickActionsBurstsize appFavouritesQuickActionsAvgInverseRate 1
(Right <$> appFavouritesQuickActionsCacheTTL)
appFavouritesQuickActionsTimeout
cK
cK
. observeFavouritesQuickActionsDuration $ do
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Starting..."
items' <- pageQuickActions NavQuickViewFavourite courseRoute
items <- forM items' $ \n@NavLink{navLabel} -> fmap (mr navLabel,) $ toTextUrl =<< navLinkRoute n
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Done."
return items
poolIsPressured <- dbPoolPressured
items <- if
| poolIsPressured -> Nothing <$ observeFavouritesSkippedDueToDBLoad
| otherwise -> memcachedLimitedKeyTimeoutBy
MemcachedLimitKeyFavourites appFavouritesQuickActionsBurstsize appFavouritesQuickActionsAvgInverseRate 1
(Right <$> appFavouritesQuickActionsCacheTTL)
appFavouritesQuickActionsTimeout
cK
cK
. observeFavouritesQuickActionsDuration $ do
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Starting..."
items' <- pageQuickActions NavQuickViewFavourite courseRoute
items <- forM items' $ \n@NavLink{navLabel} -> fmap (mr navLabel,) $ toTextUrl =<< navLinkRoute n
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Done."
return items
$logDebugS "FavouriteQuickActions" $ tshow cK <> " returning " <> tshow (is _Just items)
return (c, courseRoute, items, favouriteReason, courseVisible, mayView, mayEdit)

View File

@ -11,7 +11,6 @@ import Data.Map as Map
-- import Data.CaseInsensitive (CI)
-- import qualified Data.CaseInsensitive as CI
import qualified Database.Esqueleto as E
makeSchoolDictionaryDB :: DB (Map.Map SchoolId SchoolName)

View File

@ -25,6 +25,7 @@ module Utils.Metrics
, observeDatabaseConnectionOpened, observeDatabaseConnectionClosed
, onUseDBConn, onReleaseDBConn, DBConnUseState, DBConnLabel
, AuthTagEvalOutcome(..), observeAuthTagEvaluation
, observeFavouritesSkippedDueToDBLoad
) where
import Import.NoModel hiding (Vector, Info)
@ -259,6 +260,12 @@ missingFiles = unsafeRegister . vector "ref" $ gauge info
where info = Info "uni2work_missing_files_count"
"Number of files referenced from within database that are missing"
{-# NOINLINE favouritesSkippedDueToDBLoad #-}
favouritesSkippedDueToDBLoad :: Counter
favouritesSkippedDueToDBLoad = unsafeRegister $ counter info
where info = Info "uni2work_favourites_skipped_due_to_db_load_count"
"Number of times this Uni2work-instance skipped generating FavouriteQuickActions due to database pressure"
relabel :: Text -> Text
-> SampleGroup -> SampleGroup
relabel l s (SampleGroup i t ss) = SampleGroup i t . flip map ss $ \(Sample k lbls v) -> Sample k ((l, s) : filter (views _1 $ (/=) l) lbls) v
@ -592,3 +599,6 @@ observeAuthTagEvaluation aTag act = do
liftIO . withLabel authTagEvaluationDuration (toPathPiece aTag, toPathPiece outcome) . flip observe . realToFrac $ end - start
either throwIO (views _1 return) res
observeFavouritesSkippedDueToDBLoad :: MonadIO m => m ()
observeFavouritesSkippedDueToDBLoad = liftIO $ incCounter favouritesSkippedDueToDBLoad

View File

@ -5,6 +5,7 @@ module Utils.Pool
, PoolResourceIdent'
, Pool, PoolResourceIdent
, getPoolAvailableCount, getPoolInUseCount, getPoolUsesCount
, getPoolIdleTime, getPoolMaxAvailable
, createPool, createPool'
, purgePool
, withResource, withResource'
@ -24,6 +25,7 @@ import UnliftIO.Concurrent (forkIO)
import Data.Fixed
import System.Clock
import Data.Time.Clock (DiffTime)
import Control.Concurrent.STM.Delay
import Control.Concurrent.STM.TVar (stateTVar)
@ -78,6 +80,10 @@ getPoolAvailableCount Pool{..} = availableCount <$> readTVar resources
getPoolInUseCount Pool{..} = inUseCount <$> readTVar resources
getPoolUsesCount Pool{..} = inUseTick <$> readTVar resources
getPoolIdleTime :: Pool' m c' c a -> Maybe DiffTime
getPoolIdleTime = fmap realToFrac . maxAvailable
getPoolMaxAvailable :: Pool' m c' c a -> Maybe Int
getPoolMaxAvailable = maxAvailable
toSecond :: TimeSpec -> Int
toSecond = fromIntegral . sec