@@ -4,10 +4,16 @@ module Test.Meetings where
44
55import API.Galley
66import qualified API.GalleyInternal as I
7+ import Control.Monad.Reader (ask )
8+ import qualified Data.Text as Text
9+ import qualified Data.Text.Encoding as Text
710import Data.Time.Clock
811import qualified Data.Time.Format as Time
912import SetupHelpers
13+ import System.Timeout (timeout )
1014import Testlib.Prelude
15+ import Text.Regex.TDFA ((=~) )
16+ import UnliftIO.Concurrent (threadDelay )
1117
1218-- Helper to extract meetingId and domain from a meeting JSON object
1319getMeetingIdAndDomain :: (HasCallStack ) => Value -> App (String , String )
@@ -359,3 +365,93 @@ testMeetingDeleteUnauthorized = do
359365 meeting <- getJSON 201 r1
360366 (meetingId, domain) <- getMeetingIdAndDomain meeting
361367 deleteMeeting otherUser domain meetingId >>= assertStatus 404
368+
369+ testMeetingCleanup :: (HasCallStack ) => App ()
370+ testMeetingCleanup = do
371+ env <- ask
372+ timedOutResult <- liftIO $ timeout (2 * 60 * 1_000_000 ) $ runAppWithEnv env $ do
373+ -- 2 minutes timeout
374+ (owner, _tid, _members) <- createTeam OwnDomain 1
375+ now <- liftIO getCurrentTime
376+ -- Create a meeting that ends now.
377+ -- Configured retention is 0.0014 hours (~5 seconds).
378+ -- cutoffTime will be now' - 5s.
379+ -- We need end_date < cutoffTime.
380+ -- If we wait 6 seconds, now' = now + 6s.
381+ -- cutoffTime = now + 6s - 5s = now + 1s.
382+ -- end_date (now) < cutoffTime (now + 1s).
383+ let startTime = addUTCTime (negate 3600 ) now
384+ endTime = now
385+ newMeeting = defaultMeetingJson " Cleanup Test" startTime endTime []
386+
387+ r1 <- postMeetings owner newMeeting
388+ assertSuccess r1
389+ meeting <- getJSON 201 r1
390+ (meetingId, domain) <- getMeetingIdAndDomain meeting
391+
392+ -- Wait 6 seconds to ensure meeting is old enough
393+ liftIO $ threadDelay 6_000_000
394+
395+ -- Wait for cleanup job to run
396+ waitForCleanupJob OwnDomain
397+
398+ -- Check it's gone
399+ getMeeting owner domain meetingId >>= assertStatus 404
400+
401+ case timedOutResult of
402+ Just () -> pure ()
403+ Nothing -> assertFailure " testMeetingCleanup timed out after 2 minutes"
404+
405+ waitForCleanupJob :: (HasCallStack , MakesValue domain ) => domain -> App ()
406+ waitForCleanupJob domain = do
407+ initialMetrics <- getMetricsBody domain
408+ let initialCount = getRunCount initialMetrics
409+
410+ waitForIncrease domain initialCount
411+ where
412+ getMetricsBody d = do
413+ getMetrics d BackgroundWorker `bindResponse` \ resp -> do
414+ resp. status `shouldMatchInt` 200
415+ pure $ Text. unpack $ Text. decodeUtf8 resp. body
416+
417+ getRunCount metrics =
418+ let (_, _, _, matches) :: (String , String , String , [String ]) = (metrics =~ " wire_meetings_cleanup_runs_total ([0-9]+)" )
419+ in case matches of
420+ [val] -> read val :: Int
421+ _ -> 0
422+
423+ waitForIncrease d oldVal = do
424+ metrics <- getMetricsBody d
425+ let newVal = getRunCount metrics
426+ -- We wait until it increases.
427+ -- Note: if oldVal was 0 (metric didn't exist), getting 0 again means it hasn't run.
428+ -- If it runs, it should become >= 1.
429+ -- But wait, if matches is empty, we return 0.
430+ -- If the metric appears, it will be >= 1 (initialized at 0? Counter starts at 0).
431+ -- If it runs, it increments.
432+ when (newVal <= oldVal) $ do
433+ liftIO $ threadDelay 1_000_000 -- Wait 1s
434+ waitForIncrease d oldVal
435+
436+ testMeetingExpiration :: (HasCallStack ) => App ()
437+ testMeetingExpiration = do
438+ (owner, _tid, _members) <- createTeam OwnDomain 1
439+ now <- liftIO getCurrentTime
440+ let startTime = addUTCTime (negate 3600 ) now
441+ -- meetingValidityPeriodSeconds is configured to 5 seconds in galley.integration.yaml
442+ endTime = now
443+ newMeeting = defaultMeetingJson " Expiring Meeting" startTime endTime []
444+
445+ r1 <- postMeetings owner newMeeting
446+ assertSuccess r1
447+ meeting <- getJSON 201 r1
448+ (meetingId, domain) <- getMeetingIdAndDomain meeting
449+
450+ -- Check it is accessible immediately (endDate = now, so valid until now + 5s)
451+ getMeeting owner domain meetingId >>= assertStatus 200
452+
453+ -- Wait 6 seconds
454+ liftIO $ threadDelay 6_000_000
455+
456+ -- Check it is expired
457+ getMeeting owner domain meetingId >>= assertStatus 404
0 commit comments