Skip to content
Snippets Groups Projects
Commit f72855ea authored by stuebinm's avatar stuebinm
Browse files

server: keep (one) last good result per repo

(i.e. we want to still have a valid version of the map if new results
where introduced)
parent 0032307c
Branches
No related tags found
No related merge requests found
...@@ -52,9 +52,9 @@ instance ToJSON MapService where ...@@ -52,9 +52,9 @@ instance ToJSON MapService where
. mapMaybe worldObject . mapMaybe worldObject
$ M.elems statuses $ M.elems statuses
where where
worldObject (RemoteRef {..}, job) = case job of worldObject (remote, _current, result) = case result of
Linted res rev _ -> Just (Linted res rev _) ->
Just (A.fromText reponame .= Just (A.fromText (reponame remote) .=
M.mapWithKey (mapInfo rev) (dirresultMaps res)) M.mapWithKey (mapInfo rev) (dirresultMaps res))
_ -> Nothing _ -> Nothing
mapInfo rev mappath MapResult { .. } = A.object mapInfo rev mappath MapResult { .. } = A.object
...@@ -68,7 +68,7 @@ statusImpl :: MVar ServerState -> Text -> Sha1 -> Handler JobStatus ...@@ -68,7 +68,7 @@ statusImpl :: MVar ServerState -> Text -> Sha1 -> Handler JobStatus
statusImpl state orgslug sha1 = do statusImpl state orgslug sha1 = do
status <- liftIO $ getJobStatus state orgslug sha1 status <- liftIO $ getJobStatus state orgslug sha1
case status of case status of
Just (_,_,jobstatus) -> pure jobstatus Just (_,_,jobstatus,_) -> pure jobstatus
Nothing -> throwError err404 Nothing -> throwError err404
-- | since there are multiple apis that just get state information … -- | since there are multiple apis that just get state information …
...@@ -83,7 +83,7 @@ relintImpl :: TQueue Job -> MVar ServerState -> Text -> Sha1 -> Handler Text ...@@ -83,7 +83,7 @@ relintImpl :: TQueue Job -> MVar ServerState -> Text -> Sha1 -> Handler Text
relintImpl queue state orgslug sha1 = relintImpl queue state orgslug sha1 =
liftIO $ getJobStatus state orgslug sha1 >>= \case liftIO $ getJobStatus state orgslug sha1 >>= \case
Nothing -> pure "there isn't a job here to restart" Nothing -> pure "there isn't a job here to restart"
Just (org, ref, _oldjob) -> do Just (org, ref, _oldjob, _veryoldjob) -> do
atomically $ writeTQueue queue (Job ref org) atomically $ writeTQueue queue (Job ref org)
pure "hello" pure "hello"
...@@ -91,7 +91,7 @@ relintImpl queue state orgslug sha1 = ...@@ -91,7 +91,7 @@ relintImpl queue state orgslug sha1 =
realtimeImpl :: MVar ServerState -> Text -> Sha1 -> PendingConnection -> Handler () realtimeImpl :: MVar ServerState -> Text -> Sha1 -> PendingConnection -> Handler ()
realtimeImpl state orgslug sha1 pending = realtimeImpl state orgslug sha1 pending =
liftIO (getJobStatus state orgslug sha1) >>= \case liftIO (getJobStatus state orgslug sha1) >>= \case
Just (_org, _ref, Linted _ _ (_, realtime)) -> do Just (_org, _ref, Linted _ _ (_, realtime), _) -> do
conn <- liftIO $ acceptRequest pending conn <- liftIO $ acceptRequest pending
incoming <- atomically $ dupTChan realtime incoming <- atomically $ dupTChan realtime
liftIO $ withPingThread conn 30 pass $ forever $ do liftIO $ withPingThread conn 30 pass $ forever $ do
......
...@@ -97,7 +97,7 @@ instance ToHtml AdminOverview where ...@@ -97,7 +97,7 @@ instance ToHtml AdminOverview where
forM_ (view unState state) $ \(org, jobs) -> do forM_ (view unState state) $ \(org, jobs) -> do
h2_ (toHtml $ orgSlug org) h2_ (toHtml $ orgSlug org)
if null jobs then em_ "(nothing yet)" if null jobs then em_ "(nothing yet)"
else flip M.foldMapWithKey jobs $ \sha1 (ref, status) -> li_ $ do else flip M.foldMapWithKey jobs $ \sha1 (ref, status, _lastvalid) -> li_ $ do
case status of case status of
Pending _ -> badge Info "pending" Pending _ -> badge Info "pending"
(Linted res rev _) -> toHtml $ maximumLintLevel res (Linted res rev _) -> toHtml $ maximumLintLevel res
......
...@@ -27,15 +27,15 @@ module Server ( loadConfig ...@@ -27,15 +27,15 @@ module Server ( loadConfig
, RemoteRef(..) , RemoteRef(..)
, ServerState, emptyState, unState , ServerState, emptyState, unState
, JobStatus(..) , JobStatus(..)
, setJobStatus , prettySha,getJobStatus,overJobStatus
, prettySha,getJobStatus,adjustedPath,RealtimeMsg(..),newRealtimeChannel) where , adjustedPath,RealtimeMsg(..),newRealtimeChannel) where
import Universum import Universum
import CheckDir (DirResult) import CheckDir (DirResult)
import CheckMap (ResultKind (Shrunk)) import CheckMap (ResultKind (Shrunk))
import Control.Arrow ((>>>)) import Control.Arrow ((>>>))
import Control.Concurrent (modifyMVar_, withMVar) import Control.Concurrent (modifyMVar, withMVar)
import Control.Concurrent.STM.TChan (TChan, newBroadcastTChan) import Control.Concurrent.STM.TChan (TChan, newBroadcastTChan)
import Crypto.Hash.SHA1 (hash) import Crypto.Hash.SHA1 (hash)
import Data.Aeson (FromJSON, ToJSON, ToJSONKey (..), import Data.Aeson (FromJSON, ToJSON, ToJSONKey (..),
...@@ -209,7 +209,7 @@ instance TS.Show JobStatus where ...@@ -209,7 +209,7 @@ instance TS.Show JobStatus where
-- | the server's global state; might eventually end up with more -- | the server's global state; might eventually end up with more
-- stuff in here, hence the newtype -- stuff in here, hence the newtype
newtype ServerState = ServerState newtype ServerState = ServerState
{ _unState :: Map Text (Org True, Map Sha1 (RemoteRef, JobStatus)) } { _unState :: Map Text (Org True, Map Sha1 (RemoteRef, JobStatus, Maybe JobStatus)) }
deriving Generic deriving Generic
-- instance NFData LintConfig' => NFData ServerState -- instance NFData LintConfig' => NFData ServerState
...@@ -223,23 +223,32 @@ emptyState config = ServerState ...@@ -223,23 +223,32 @@ emptyState config = ServerState
$ M.fromList $ map (\org -> (orgSlug org, (org, mempty))) (view orgs config) $ M.fromList $ map (\org -> (orgSlug org, (org, mempty))) (view orgs config)
-- | NOTE: this does not create the org if it does not yet exist! -- | NOTE: this does not create the org if it does not yet exist!
setJobStatus :: MVar ServerState -> Org True -> RemoteRef -> JobStatus -> IO () overJobStatus
setJobStatus mvar !org !ref !status = do :: MVar ServerState
modifyMVar_ mvar $ \state -> do -> Org True
-> RemoteRef
-> (Maybe (RemoteRef, JobStatus, Maybe JobStatus) ->
Maybe (RemoteRef, JobStatus, Maybe JobStatus))
-> IO (Maybe (RemoteRef, JobStatus, Maybe JobStatus))
overJobStatus mvar !org !ref overState = do
modifyMVar mvar $ \state -> do
-- will otherwise cause a thunk leak, since Data.Map is annoyingly un-strict -- will otherwise cause a thunk leak, since Data.Map is annoyingly un-strict
-- even in its strict variety. for some reason it also doesn't work when -- even in its strict variety. for some reason it also doesn't work when
-- moved inside the `over` though … -- moved inside the `over` though …
_ <- evaluateWHNF (view (unState . ix (orgSlug org) . _2) state) bla <- evaluateWHNF (view (unState . ix (orgSlug org) . _2) state)
pure $ over (unState . ix (orgSlug org) . _2 . at (toSha ref)) let thing = state & (unState . ix (orgSlug org) . _2 . at (toSha ref)) %~ overState
(const $ Just (ref, status)) state pure (thing, view (at (toSha ref)) bla)
getJobStatus :: MVar ServerState -> Text -> Sha1 -> IO (Maybe (Org True, RemoteRef, JobStatus))
getJobStatus
:: MVar ServerState
-> Text
-> Sha1
-> IO (Maybe (Org True, RemoteRef, JobStatus, Maybe JobStatus))
getJobStatus mvar orgslug sha = withMVar mvar $ \state -> pure $ do getJobStatus mvar orgslug sha = withMVar mvar $ \state -> pure $ do
(org, jobs) <- view (unState . at orgslug) state (org, jobs) <- view (unState . at orgslug) state
(ref, status) <- M.lookup sha jobs (ref, status, rev) <- M.lookup sha jobs
Just (org, ref, status) Just (org, ref, status, rev)
-- pure $ second (M.lookup sha) orgIndex
-- pure (M.lookup sha (view (unState . ix orgslug) state))
-- | the path (relative to a baseurl / webdir) where an adjusted -- | the path (relative to a baseurl / webdir) where an adjusted
......
...@@ -11,7 +11,7 @@ module Worker (linterThread, Job(..)) where ...@@ -11,7 +11,7 @@ module Worker (linterThread, Job(..)) where
import Universum import Universum
import CheckDir (recursiveCheckDir, import CheckDir (recursiveCheckDir,
shrinkDirResult) shrinkDirResult, resultIsFatal)
import Control.Concurrent.Async (async, link) import Control.Concurrent.Async (async, link)
import Control.Concurrent.STM (writeTChan) import Control.Concurrent.STM (writeTChan)
import Control.Concurrent.STM.TQueue import Control.Concurrent.STM.TQueue
...@@ -27,9 +27,9 @@ import Server (Config, JobStatus (..), ...@@ -27,9 +27,9 @@ import Server (Config, JobStatus (..),
Org (..), Org (..),
RealtimeMsg (RelintPending, Reload), RealtimeMsg (RelintPending, Reload),
RemoteRef (..), ServerState, RemoteRef (..), ServerState,
adjustedPath, getJobStatus, adjustedPath,
newRealtimeChannel, newRealtimeChannel,
setJobStatus, tmpdir, toSha) tmpdir, overJobStatus)
import System.Directory (doesDirectoryExist) import System.Directory (doesDirectoryExist)
import System.Exit (ExitCode (ExitFailure, ExitSuccess)) import System.Exit (ExitCode (ExitFailure, ExitSuccess))
import System.FilePath ((</>)) import System.FilePath ((</>))
...@@ -65,17 +65,20 @@ runJob config Job {..} done = do ...@@ -65,17 +65,20 @@ runJob config Job {..} done = do
where where
lintConfig = stuffConfig (orgLintconfig jobOrg) (reponame jobRef) lintConfig = stuffConfig (orgLintconfig jobOrg) (reponame jobRef)
lint workdir = do lint workdir = do
maybeRealtime <- getJobStatus done (orgSlug jobOrg) (toSha jobRef) >>= \case
Nothing -> pure Nothing
Just (org, ref, jobstatus) -> case jobstatus of
Linted res rev (_, realtime) -> do
setJobStatus done org ref (Linted res rev (True, realtime))
pure $ Just realtime
Pending realtime -> pure $ Just realtime
_ -> pure Nothing
whenJust maybeRealtime $ \realtime -> -- set the "is being linted" flag in the assembly's state
-- (to show on the site even after reloads etc.)
oldstate <- overJobStatus done jobOrg jobRef $ \case
Just (ref, Linted res rev (_, realtime), oldstatus) ->
Just (ref, Linted res rev (True, realtime), oldstatus)
a -> a
-- send an update message to all connected websocket clients
maybeRealtime <- case oldstate of
Just (_, Linted _ _ (_, realtime), _) -> do
atomically $ writeTChan realtime RelintPending atomically $ writeTChan realtime RelintPending
pure (Just realtime)
_ -> pure Nothing
ifM (doesDirectoryExist gitdir) ifM (doesDirectoryExist gitdir)
-- TODO: these calls fail for dumb http, add some fallback! -- TODO: these calls fail for dumb http, add some fallback!
...@@ -114,16 +117,27 @@ runJob config Job {..} done = do ...@@ -114,16 +117,27 @@ runJob config Job {..} done = do
Nothing -> Nothing ->
newRealtimeChannel newRealtimeChannel
setJobStatus done jobOrg jobRef $ -- the fact that `realtime` can't be defined in here is horrifying
Linted (shrinkDirResult res) rev (False, realtime) void $ overJobStatus done jobOrg jobRef $ \maybeOld ->
let status = Linted (shrinkDirResult res) rev (False, realtime)
lastvalid = case maybeOld of
Just (_,_,lastvalid) -> lastvalid
Nothing -> Nothing
in Just ( jobRef
, status
, if resultIsFatal lintConfig res
then lastvalid
else Just status
)
cleanup workdir = do cleanup workdir = do
callgit gitdir [ "worktree", "remove", "-f", "-f", workdir ] callgit gitdir [ "worktree", "remove", "-f", "-f", workdir ]
whoops (error :: IOException) = runStdoutLoggingT $ do whoops (error :: IOException) = runStdoutLoggingT $ do
logErrorN (show error) logErrorN (show error)
liftIO $ setJobStatus done jobOrg jobRef $ Failed (show error) void $ liftIO $ overJobStatus done jobOrg jobRef $ \case
Nothing -> Just (jobRef, Failed (show error), Nothing)
Just (_,_,lastvalid) -> Just (jobRef, Failed (show error), lastvalid)
url = repourl jobRef url = repourl jobRef
ref = reporef jobRef ref = reporef jobRef
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment