33
44module Test.AnomalyDetectionSpec (spec ) where
55
6+ import Control.Concurrent (threadDelay )
67import Control.Monad (void )
78import Control.Monad.Catch (bracket_ )
89import Control.Monad.IO.Class (liftIO )
910import Data.Aeson (Value (.. ), decode , encode , object , (.=) )
10- import qualified Data.ByteString.Lazy.Char8 as LBS
11+ import Data.ByteString.Lazy.Char8 qualified as LBS
1112import Data.Fixed (Pico )
12- import qualified Data.List as L
13+ import Data.List qualified as L
1314import Data.Maybe (isJust )
14- import qualified Data.Text as T
15+ import Data.Text qualified as T
1516import Data.Time.Calendar (toGregorian )
1617import Data.Time.Clock (UTCTime (.. ))
1718import Data.Time.Clock.POSIX (getPOSIXTime , posixSecondsToUTCTime )
1819import Data.Time.LocalTime (TimeOfDay (.. ), timeToTimeOfDay )
19- import qualified Database.Bloodhound.OpenSearch1.Client as OS1Client
20- import qualified Database.Bloodhound.OpenSearch1.Requests as OS1Requests
21- import qualified Database.Bloodhound.OpenSearch1.Types as OS1Types
22- import qualified Database.Bloodhound.OpenSearch2.Client as OS2Client
23- import qualified Database.Bloodhound.OpenSearch2.Requests as OS2Requests
24- import qualified Database.Bloodhound.OpenSearch2.Types as OS2Types
25- import qualified Database.Bloodhound.OpenSearch3.Client as OS3Client
26- import qualified Database.Bloodhound.OpenSearch3.Requests as OS3Requests
27- import qualified Database.Bloodhound.OpenSearch3.Types as OS3Types
20+ import Database.Bloodhound.OpenSearch1.Client qualified as OS1Client
21+ import Database.Bloodhound.OpenSearch1.Requests qualified as OS1Requests
22+ import Database.Bloodhound.OpenSearch1.Types qualified as OS1Types
23+ import Database.Bloodhound.OpenSearch2.Client qualified as OS2Client
24+ import Database.Bloodhound.OpenSearch2.Requests qualified as OS2Requests
25+ import Database.Bloodhound.OpenSearch2.Types qualified as OS2Types
26+ import Database.Bloodhound.OpenSearch3.Client qualified as OS3Client
27+ import Database.Bloodhound.OpenSearch3.Requests qualified as OS3Requests
28+ import Database.Bloodhound.OpenSearch3.Types qualified as OS3Types
2829import TestsUtils.Common
2930 ( os1OnlyIT ,
3031 os2OnlyIT ,
@@ -1074,7 +1075,7 @@ spec = do
10741075 expectationFailure
10751076 (" startDetector failed: " <> T. unpack (errorMessage e))
10761077 Right _ -> pure ()
1077- stopResp <- OS1Client. stopDetector detectorId False
1078+ stopResp <- stopDetectorWithRetry ( OS1Client. stopDetector detectorId False )
10781079 liftIO $
10791080 case stopResp of
10801081 Left e ->
@@ -1086,7 +1087,7 @@ spec = do
10861087 liftIO $ expectationFailureOnLeft updateResp " updateDetector failed:"
10871088 startResp <- OS1Client. startDetector detectorId Nothing
10881089 liftIO $ expectationFailureOnLeft startResp " startDetector failed:"
1089- stopResp <- OS1Client. stopDetector detectorId False
1090+ stopResp <- stopDetectorWithRetry ( OS1Client. stopDetector detectorId False )
10901091 liftIO $ expectationFailureOnLeft stopResp " stopDetector failed:"
10911092 delResp <- OS1Client. deleteDetector detectorId
10921093 liftIO $ expectationFailureOnLeft delResp " deleteDetector failed:"
@@ -1161,7 +1162,7 @@ spec = do
11611162 expectationFailure
11621163 (" startDetector failed: " <> T. unpack (errorMessage e))
11631164 Right _ -> pure ()
1164- stopResp <- OS2Client. stopDetector detectorId False
1165+ stopResp <- stopDetectorWithRetry ( OS2Client. stopDetector detectorId False )
11651166 liftIO $
11661167 case stopResp of
11671168 Left e ->
@@ -1173,7 +1174,7 @@ spec = do
11731174 liftIO $ expectationFailureOnLeft updateResp " updateDetector failed:"
11741175 startResp <- OS2Client. startDetector detectorId Nothing
11751176 liftIO $ expectationFailureOnLeft startResp " startDetector failed:"
1176- stopResp <- OS2Client. stopDetector detectorId False
1177+ stopResp <- stopDetectorWithRetry ( OS2Client. stopDetector detectorId False )
11771178 liftIO $ expectationFailureOnLeft stopResp " stopDetector failed:"
11781179 delResp <- OS2Client. deleteDetector detectorId
11791180 liftIO $ expectationFailureOnLeft delResp " deleteDetector failed:"
@@ -1248,7 +1249,7 @@ spec = do
12481249 expectationFailure
12491250 (" startDetector failed: " <> T. unpack (errorMessage e))
12501251 Right _ -> pure ()
1251- stopResp <- OS3Client. stopDetector detectorId False
1252+ stopResp <- stopDetectorWithRetry ( OS3Client. stopDetector detectorId False )
12521253 liftIO $
12531254 case stopResp of
12541255 Left e ->
@@ -1260,7 +1261,7 @@ spec = do
12601261 liftIO $ expectationFailureOnLeft updateResp " updateDetector failed:"
12611262 startResp <- OS3Client. startDetector detectorId Nothing
12621263 liftIO $ expectationFailureOnLeft startResp " startDetector failed:"
1263- stopResp <- OS3Client. stopDetector detectorId False
1264+ stopResp <- stopDetectorWithRetry ( OS3Client. stopDetector detectorId False )
12641265 liftIO $ expectationFailureOnLeft stopResp " stopDetector failed:"
12651266 delResp <- OS3Client. deleteDetector detectorId
12661267 liftIO $ expectationFailureOnLeft delResp " deleteDetector failed:"
@@ -1326,3 +1327,24 @@ expectationFailureOnLeft r prefix =
13261327 case r of
13271328 Left e -> expectationFailure (prefix <> " " <> T. unpack (errorMessage e))
13281329 Right _ -> pure ()
1330+
1331+ -- | Tolerate the Anomaly Detection plugin's start\/stop race:
1332+ -- 'startDetector' returns as soon as it acknowledges the start, but the
1333+ -- real-time job is registered asynchronously in the
1334+ -- @.opendistro-anomaly-detector-jobs@ index, so an immediate
1335+ -- 'stopDetector' can transiently receive "Fail to stop detector" from the
1336+ -- server. Retry only that specific error, bounded so a genuine failure
1337+ -- still surfaces. Mirrors the 'waitFor' idiom in "Test.CCRSpec".
1338+ stopDetectorWithRetry ::
1339+ (MonadIO m ) =>
1340+ m (Either EsError a ) ->
1341+ m (Either EsError a )
1342+ stopDetectorWithRetry stop = go (0 :: Int )
1343+ where
1344+ go n = do
1345+ r <- stop
1346+ case r of
1347+ Left e
1348+ | " Fail to stop detector" `T.isInfixOf` errorMessage e && n < 10 ->
1349+ liftIO (threadDelay 1000000 ) >> go (n + 1 )
1350+ _ -> pure r
0 commit comments