perf: skip favouriteQuickActions under db conn pressure
This commit is contained in:
parent
63f0d3c37a
commit
55a9c8a5ae
@ -1,6 +1,7 @@
|
|||||||
module Foundation.DB
|
module Foundation.DB
|
||||||
( runDBRead, runDBRead'
|
( runDBRead, runDBRead'
|
||||||
, runSqlPoolRetry, runSqlPoolRetry'
|
, runSqlPoolRetry, runSqlPoolRetry'
|
||||||
|
, dbPoolPressured
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import.NoFoundation hiding (runDB, getDBRunner)
|
import Import.NoFoundation hiding (runDB, getDBRunner)
|
||||||
@ -61,3 +62,13 @@ runDBRead' :: CallStack -> ReaderT SqlReadBackend (HandlerFor UniWorX) a -> (Han
|
|||||||
runDBRead' lbl action = do
|
runDBRead' lbl action = do
|
||||||
$logDebugS "YesodPersist" "runDBRead"
|
$logDebugS "YesodPersist" "runDBRead"
|
||||||
flip (runSqlPoolRetry' . withReaderT SqlReadBackend $ [executeQQ|SET TRANSACTION READ ONLY|] *> action) lbl . appConnPool =<< getYesod
|
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
|
||||||
|
|||||||
@ -191,18 +191,21 @@ siteLayout' overrideHeading widget = do
|
|||||||
langs <- selectLanguages appLanguages <$> languages
|
langs <- selectLanguages appLanguages <$> languages
|
||||||
let cK = MemcachedKeyFavouriteQuickActions (tid, ssh, csh) ctx langs
|
let cK = MemcachedKeyFavouriteQuickActions (tid, ssh, csh) ctx langs
|
||||||
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Checking..."
|
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Checking..."
|
||||||
items <- memcachedLimitedKeyTimeoutBy
|
poolIsPressured <- dbPoolPressured
|
||||||
MemcachedLimitKeyFavourites appFavouritesQuickActionsBurstsize appFavouritesQuickActionsAvgInverseRate 1
|
items <- if
|
||||||
(Right <$> appFavouritesQuickActionsCacheTTL)
|
| poolIsPressured -> Nothing <$ observeFavouritesSkippedDueToDBLoad
|
||||||
appFavouritesQuickActionsTimeout
|
| otherwise -> memcachedLimitedKeyTimeoutBy
|
||||||
cK
|
MemcachedLimitKeyFavourites appFavouritesQuickActionsBurstsize appFavouritesQuickActionsAvgInverseRate 1
|
||||||
cK
|
(Right <$> appFavouritesQuickActionsCacheTTL)
|
||||||
. observeFavouritesQuickActionsDuration $ do
|
appFavouritesQuickActionsTimeout
|
||||||
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Starting..."
|
cK
|
||||||
items' <- pageQuickActions NavQuickViewFavourite courseRoute
|
cK
|
||||||
items <- forM items' $ \n@NavLink{navLabel} -> fmap (mr navLabel,) $ toTextUrl =<< navLinkRoute n
|
. observeFavouritesQuickActionsDuration $ do
|
||||||
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Done."
|
$logDebugS "FavouriteQuickActions" $ tshow cK <> " Starting..."
|
||||||
return items
|
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)
|
$logDebugS "FavouriteQuickActions" $ tshow cK <> " returning " <> tshow (is _Just items)
|
||||||
return (c, courseRoute, items, favouriteReason, courseVisible, mayView, mayEdit)
|
return (c, courseRoute, items, favouriteReason, courseVisible, mayView, mayEdit)
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import Data.Map as Map
|
|||||||
-- import Data.CaseInsensitive (CI)
|
-- import Data.CaseInsensitive (CI)
|
||||||
-- import qualified Data.CaseInsensitive as CI
|
-- import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
|
||||||
makeSchoolDictionaryDB :: DB (Map.Map SchoolId SchoolName)
|
makeSchoolDictionaryDB :: DB (Map.Map SchoolId SchoolName)
|
||||||
|
|||||||
@ -25,6 +25,7 @@ module Utils.Metrics
|
|||||||
, observeDatabaseConnectionOpened, observeDatabaseConnectionClosed
|
, observeDatabaseConnectionOpened, observeDatabaseConnectionClosed
|
||||||
, onUseDBConn, onReleaseDBConn, DBConnUseState, DBConnLabel
|
, onUseDBConn, onReleaseDBConn, DBConnUseState, DBConnLabel
|
||||||
, AuthTagEvalOutcome(..), observeAuthTagEvaluation
|
, AuthTagEvalOutcome(..), observeAuthTagEvaluation
|
||||||
|
, observeFavouritesSkippedDueToDBLoad
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import.NoModel hiding (Vector, Info)
|
import Import.NoModel hiding (Vector, Info)
|
||||||
@ -259,6 +260,12 @@ missingFiles = unsafeRegister . vector "ref" $ gauge info
|
|||||||
where info = Info "uni2work_missing_files_count"
|
where info = Info "uni2work_missing_files_count"
|
||||||
"Number of files referenced from within database that are missing"
|
"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
|
relabel :: Text -> Text
|
||||||
-> SampleGroup -> SampleGroup
|
-> 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
|
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
|
liftIO . withLabel authTagEvaluationDuration (toPathPiece aTag, toPathPiece outcome) . flip observe . realToFrac $ end - start
|
||||||
|
|
||||||
either throwIO (views _1 return) res
|
either throwIO (views _1 return) res
|
||||||
|
|
||||||
|
observeFavouritesSkippedDueToDBLoad :: MonadIO m => m ()
|
||||||
|
observeFavouritesSkippedDueToDBLoad = liftIO $ incCounter favouritesSkippedDueToDBLoad
|
||||||
|
|||||||
@ -5,6 +5,7 @@ module Utils.Pool
|
|||||||
, PoolResourceIdent'
|
, PoolResourceIdent'
|
||||||
, Pool, PoolResourceIdent
|
, Pool, PoolResourceIdent
|
||||||
, getPoolAvailableCount, getPoolInUseCount, getPoolUsesCount
|
, getPoolAvailableCount, getPoolInUseCount, getPoolUsesCount
|
||||||
|
, getPoolIdleTime, getPoolMaxAvailable
|
||||||
, createPool, createPool'
|
, createPool, createPool'
|
||||||
, purgePool
|
, purgePool
|
||||||
, withResource, withResource'
|
, withResource, withResource'
|
||||||
@ -24,6 +25,7 @@ import UnliftIO.Concurrent (forkIO)
|
|||||||
import Data.Fixed
|
import Data.Fixed
|
||||||
|
|
||||||
import System.Clock
|
import System.Clock
|
||||||
|
import Data.Time.Clock (DiffTime)
|
||||||
|
|
||||||
import Control.Concurrent.STM.Delay
|
import Control.Concurrent.STM.Delay
|
||||||
import Control.Concurrent.STM.TVar (stateTVar)
|
import Control.Concurrent.STM.TVar (stateTVar)
|
||||||
@ -78,6 +80,10 @@ getPoolAvailableCount Pool{..} = availableCount <$> readTVar resources
|
|||||||
getPoolInUseCount Pool{..} = inUseCount <$> readTVar resources
|
getPoolInUseCount Pool{..} = inUseCount <$> readTVar resources
|
||||||
getPoolUsesCount Pool{..} = inUseTick <$> 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 :: TimeSpec -> Int
|
||||||
toSecond = fromIntegral . sec
|
toSecond = fromIntegral . sec
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user