chore(daily): add function to retrieve all exam occurrences for given days

the function uses the memcachedByClass mechanism, which was slightly refined as well to include the class within the memcached keys for added correctness
This commit is contained in:
Steffen Jost 2024-12-13 17:27:02 +01:00 committed by Sarah Vaupel
parent 4f524bd8d2
commit f467f6086e
5 changed files with 30 additions and 4 deletions

View File

@ -47,7 +47,7 @@ ExamOccurrence
end UTCTime Maybe end UTCTime Maybe
description StoredMarkup Maybe description StoredMarkup Maybe
UniqueExamOccurrence exam name UniqueExamOccurrence exam name
deriving Generic deriving Show Generic Binary
ExamRegistration ExamRegistration
exam ExamId exam ExamId
user UserId user UserId

View File

@ -152,6 +152,7 @@ postEEditR tid ssh csh examn = do
deleteWhere [ ExamCorrectorExam ==. eId ] deleteWhere [ ExamCorrectorExam ==. eId ]
insertMany_ $ map (ExamCorrector eId) adds insertMany_ $ map (ExamCorrector eId) adds
memcachedByInvalidate AuthCacheExamCorrectorList $ Proxy @(Set UserId) memcachedByInvalidate AuthCacheExamCorrectorList $ Proxy @(Set UserId)
memcachedInvalidateClass MemcachedKeyClassExamOccurrences
deleteWhere [ InvitationFor ==. invRef @ExamCorrector eId, InvitationEmail /<-. invites ] deleteWhere [ InvitationFor ==. invRef @ExamCorrector eId, InvitationEmail /<-. invites ]
sinkInvitationsF examCorrectorInvitationConfig $ map (, eId, (InvDBDataExamCorrector, InvTokenDataExamCorrector)) invites sinkInvitationsF examCorrectorInvitationConfig $ map (, eId, (InvDBDataExamCorrector, InvTokenDataExamCorrector)) invites

View File

@ -93,6 +93,7 @@ postCExamNewR tid ssh csh = do
] ]
sinkInvitationsF examCorrectorInvitationConfig $ map (, examid, (InvDBDataExamCorrector, InvTokenDataExamCorrector)) invites sinkInvitationsF examCorrectorInvitationConfig $ map (, examid, (InvDBDataExamCorrector, InvTokenDataExamCorrector)) invites
memcachedByInvalidate AuthCacheExamCorrectorList $ Proxy @(Set UserId) memcachedByInvalidate AuthCacheExamCorrectorList $ Proxy @(Set UserId)
memcachedInvalidateClass MemcachedKeyClassExamOccurrences
let recordNoShow (Entity _ CourseParticipant{..}) = do let recordNoShow (Entity _ CourseParticipant{..}) = do
didRecord <- is _Just <$> insertUnique ExamResult didRecord <- is _Just <$> insertUnique ExamResult

View File

@ -74,7 +74,8 @@ getDayTutorials ssh d = E.unValue <<$>> E.select (do
-- Datatype to be used as key for memcaching DayTask related stuff; note that newtype-CacheKeys are optimized away, so multiple constructors are advisable -- Datatype to be used as key for memcaching DayTask related stuff; note that newtype-CacheKeys are optimized away, so multiple constructors are advisable
data DailyCacheKeys data DailyCacheKeys
= CacheKeyTutorialOccurrences SchoolId (Day,Day) = CacheKeyTutorialOccurrences SchoolId (Day,Day) -- ^ Map TutorialId (TutorialName, [LessonTime])
| CacheKeyExamOccurrences SchoolId (Day,Day) -- ^ Map ExamOccurrenceId (CourseId, ExamName, ExamOccurrence)
| CacheKeySuggsParticipantNote SchoolId TutorialId | CacheKeySuggsParticipantNote SchoolId TutorialId
| CacheKeySuggsAttendanceNote SchoolId TutorialId | CacheKeySuggsAttendanceNote SchoolId TutorialId
| CacheKeyTutorialCheckResults SchoolId Day | CacheKeyTutorialCheckResults SchoolId Day
@ -139,6 +140,28 @@ getDayTutorials' ssh dlimit@(dstart, dend )
lessonFltr LessonTime{..} = dstart <= localDay lessonStart lessonFltr LessonTime{..} = dstart <= localDay lessonStart
&& dend >= localDay lessonEnd && dend >= localDay lessonEnd
-- | retrieve all exam occurrences for a school in a given time period; uses caching
getDayExamOccurrences :: SchoolId -> (Day,Day) -> DB (Map ExamOccurrenceId (CourseId, ExamName, ExamOccurrence))
getDayExamOccurrences ssh dlimit@(dstart, dend )
| dstart > dend = return mempty
| otherwise = memcachedByClass MemcachedKeyClassExamOccurrences (Just . Right $ 12 * diffDay) (CacheKeyExamOccurrences ssh dlimit) $ do
candidates <- E.select $ do
(trm :& crs :& exm :& occ) <- E.from $ E.table @Term
`E.innerJoin` E.table @Course `E.on` (\(trm :& crs) -> crs E.^. CourseTerm E.==. trm E.^. TermId)
`E.innerJoin` E.table @Exam `E.on` (\(_ :& crs :& exm) -> crs E.^. CourseId E.==. exm E.^. ExamCourse)
`E.innerJoin` E.table @ExamOccurrence `E.on` (\(_ :& _ :& exm :& occ) -> exm E.^. ExamId E.==. occ E.^. ExamOccurrenceExam)
E.where_ $ E.val ssh E.==. crs E.^. CourseSchool
E.&&. E.val dstart E.<=. trm E.^. TermEnd
E.&&. E.val dend E.>=. trm E.^. TermStart
E.&&. ( E.between (E.day $ occ E.^. ExamOccurrenceStart) (E.val dstart, E.val dend)
E.||. E.between (E.dayMaybe $ occ E.^. ExamOccurrenceEnd) (E.justVal dstart, E.justVal dend)
)
return (exm, occ)
return $ foldMap mkOccMap candidates
where
mkOccMap :: (Entity Exam, Entity ExamOccurrence) -> Map ExamOccurrenceId (CourseId, ExamName, ExamOccurrence)
mkOccMap (entityVal -> exm, Entity{..}) = Map.singleton entityKey (exm ^. _examCourse, exm ^. _examName, entityVal)
type DailyTableExpr = type DailyTableExpr =
( E.SqlExpr (Entity Course) ( E.SqlExpr (Entity Course)

View File

@ -364,10 +364,11 @@ memcachedByClass :: forall a m k.
, Binary k , Binary k
) )
=> MemcachedKeyClass -> Maybe Expiry -> k -> m a -> m a => MemcachedKeyClass -> Maybe Expiry -> k -> m a -> m a
memcachedByClass mkc mExp k = memcachedWith (memcachedByGet k, setAndAddClass) memcachedByClass mkc mExp k = memcachedWith (memcachedByGet ck, setAndAddClass)
where where
ck = (mkc, k)
setAndAddClass v = do setAndAddClass v = do
mbKey <- memcachedBySet' mExp k v mbKey <- memcachedBySet' mExp ck v
whenIsJust mbKey $ \vKey -> do whenIsJust mbKey $ \vKey -> do
cl <- maybeMonoid <$> memcachedByGet mkc cl <- maybeMonoid <$> memcachedByGet mkc
memcachedBySet Nothing mkc $ MemcachedKeyClassStore $ Set.insert vKey $ unMemcachedKeyClassStore cl memcachedBySet Nothing mkc $ MemcachedKeyClassStore $ Set.insert vKey $ unMemcachedKeyClassStore cl