add progress bar for hashing and zipping, cleanup files

This commit is contained in:
Lucy Cifferello
2022-09-14 17:26:46 -06:00
parent 73e0a84142
commit c27f68387e
2 changed files with 37 additions and 56 deletions

View File

@@ -378,7 +378,7 @@ makeAuthWare _ app req res = next
-- | Warp settings for the given foundation value. -- | Warp settings for the given foundation value.
warpSettings :: AppPort -> RegistryCtx -> Settings warpSettings :: AppPort -> RegistryCtx -> Settings
warpSettings port foundation = warpSettings port foundation =
setTimeout 120 $ setTimeout 90 $
setPort (fromIntegral port) $ setPort (fromIntegral port) $
setHost (appHost $ appSettings foundation) $ setHost (appHost $ appSettings foundation) $
setOnException setOnException

View File

@@ -12,14 +12,13 @@ module Cli.Cli (
cliMain, cliMain,
) where ) where
import Codec.Archive.Zip.Conduit.Types
import Codec.Archive.Zip.Conduit.Zip (ZipOptions (..), zipFileData, zipStream)
import Conduit ( import Conduit (
ConduitT, ConduitT,
MonadResource, MonadIO,
awaitForever,
foldC, foldC,
runConduit, runConduit,
runResourceT, runConduitRes,
sinkFileCautious, sinkFileCautious,
sourceFile, sourceFile,
yield, yield,
@@ -37,7 +36,7 @@ import Crypto.Hash (
SHA256 (SHA256), SHA256 (SHA256),
hashWith, hashWith,
) )
import Crypto.Hash.Conduit (hashFile) import Crypto.Hash.Conduit (hashFile, sinkHash)
import Data.Aeson ( import Data.Aeson (
ToJSON, ToJSON,
eitherDecodeStrict, eitherDecodeStrict,
@@ -64,8 +63,6 @@ import Data.String.Interpolate.IsString (
i, i,
) )
import Data.Text (toLower) import Data.Text (toLower)
import Data.Text qualified as T
import Data.Time (getTimeZone, utcToLocalTime)
import Dhall ( import Dhall (
Encoder (embed), Encoder (embed),
FromDhall (..), FromDhall (..),
@@ -92,6 +89,7 @@ import Network.HTTP.Client.Conduit (
observedStreamFile, observedStreamFile,
) )
import Network.HTTP.Client.TLS (newTlsManager) import Network.HTTP.Client.TLS (newTlsManager)
import Network.HTTP.Conduit (responseTimeoutMicro)
import Network.HTTP.Simple ( import Network.HTTP.Simple (
getResponseBody, getResponseBody,
getResponseStatus, getResponseStatus,
@@ -99,11 +97,10 @@ import Network.HTTP.Simple (
httpLBS, httpLBS,
parseRequest, parseRequest,
setRequestBody, setRequestBody,
setRequestBodyFile,
setRequestBodyJSON, setRequestBodyJSON,
setRequestBodySource,
setRequestHeaders, setRequestHeaders,
setRequestQueryString, setRequestQueryString,
setRequestResponseTimeout,
) )
import Network.HTTP.Types (status200) import Network.HTTP.Types (status200)
import Network.URI ( import Network.URI (
@@ -166,12 +163,11 @@ import Startlude (
ReaderT (runReaderT), ReaderT (runReaderT),
Semigroup ((<>)), Semigroup ((<>)),
Show, Show,
SomeException (SomeException),
String, String,
Word64,
appendFile, appendFile,
const, const,
decodeUtf8, decodeUtf8,
encodeUtf8,
exitWith, exitWith,
filter, filter,
flip, flip,
@@ -181,13 +177,13 @@ import Startlude (
fromIntegral, fromIntegral,
fromMaybe, fromMaybe,
fst, fst,
getCurrentTime,
headMay, headMay,
liftIO, liftIO,
not, not,
panic, panic,
show, show,
snd, snd,
throwIO,
unlessM, unlessM,
void, void,
when, when,
@@ -211,15 +207,17 @@ import System.Directory (
import System.FilePath ( import System.FilePath (
takeDirectory, takeDirectory,
takeExtension, takeExtension,
(<.>),
(</>), (</>),
) )
import System.ProgressBar ( import System.ProgressBar (
Progress (..), Progress (..),
ProgressBar,
defStyle, defStyle,
incProgress,
newProgressBar, newProgressBar,
updateProgress, updateProgress,
) )
import UnliftIO.Exception (handle)
import Yesod ( import Yesod (
logError, logError,
logWarn, logWarn,
@@ -563,6 +561,7 @@ upload (Upload name mpkg shouldIndex) = do
noBody <- noBody <-
parseRequest ("POST " <> show publishCfgRepoLocation <> "/admin/v0/upload") parseRequest ("POST " <> show publishCfgRepoLocation <> "/admin/v0/upload")
<&> setRequestHeaders [("accept", "text/plain")] <&> setRequestHeaders [("accept", "text/plain")]
<&> setRequestResponseTimeout (responseTimeoutMicro (90_000_000)) -- 90 seconds
<&> applyBasicAuth (B8.pack publishCfgRepoUser) (B8.pack publishCfgRepoPass) <&> applyBasicAuth (B8.pack publishCfgRepoUser) (B8.pack publishCfgRepoPass)
size <- getFileSize pkg size <- getFileSize pkg
bar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral size) ()) bar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral size) ())
@@ -593,40 +592,37 @@ upload (Upload name mpkg shouldIndex) = do
sfs2prog StreamFileStatus{..} = Progress (fromIntegral readSoFar) (fromIntegral fileSize) () sfs2prog StreamFileStatus{..} = Progress (fromIntegral readSoFar) (fromIntegral fileSize) ()
-- stream read file
-- stream zip file
-- stream zip into request body
-- store on server uncomressed?
-- nice to have: progress for hashing
eosUpload :: EosUpload -> IO () eosUpload :: EosUpload -> IO ()
eosUpload (EosUpload name img version) = do eosUpload (EosUpload name img version) = handle @_ @SomeException cleanup $ do
PublishCfgRepo{..} <- findNameInCfg name PublishCfgRepo{..} <- findNameInCfg name
noBody <- noBody <-
parseRequest ("POST " <> show publishCfgRepoLocation <> "/admin/v0/eos-upload") parseRequest ("POST " <> show publishCfgRepoLocation <> "/admin/v0/eos-upload")
<&> setRequestHeaders [("accept", "text/plain")] <&> setRequestHeaders [("accept", "text/plain")]
-- <&> setRequestHeaders [("Content-Type", "application/octet-stream")] <&> setRequestResponseTimeout (responseTimeoutMicro (90_000_000)) -- 90 seconds
<&> setRequestHeaders [("Content-Encoding", "gzip")] <&> setRequestHeaders [("Content-Encoding", "gzip")]
<&> applyBasicAuth (B8.pack publishCfgRepoUser) (B8.pack publishCfgRepoPass) <&> applyBasicAuth (B8.pack publishCfgRepoUser) (B8.pack publishCfgRepoPass)
size <- getFileSize img
hashBar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral size) ())
runConduitRes $ sourceFile img .| transByteCounter hashBar .| sinkHash @_ @SHA256
hash <- hashFile @_ @SHA256 img hash <- hashFile @_ @SHA256 img
-- let z = (createZipEntry img (Just $ fromIntegral size) .| (zipStream zipOptions)) let compressedFilePath = "/tmp/eos.img.gz"
let compressedFilePath = img <.> "gz" zipBar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral size) ())
runResourceT $ runConduitRes $
runConduit $ sourceFile img
sourceFile img .| gzip
.| gzip .| transByteCounter zipBar
.| sinkFileCautious compressedFilePath .| sinkFileCautious compressedFilePath
compressedSize <- getFileSize compressedFilePath compressedSize <- getFileSize compressedFilePath
bar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral compressedSize) ()) fileBar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral compressedSize) ())
body <- observedStreamFile (updateProgress bar . const . sfs2prog) $ compressedFilePath body <- observedStreamFile (updateProgress fileBar . const . sfs2prog) $ compressedFilePath
let withBody = setRequestBody body noBody let withBody = setRequestBody body noBody
let withQParams = let withQParams =
setRequestQueryString setRequestQueryString
[("version", Just $ show version), ("hash", Just $ convertToBase Base16 hash)] [("version", Just $ show version), ("hash", Just $ convertToBase Base16 hash)]
withBody withBody
-- let withSource = setRequestBodySource (fromIntegral size) _ withQParams
manager <- newTlsManager manager <- newTlsManager
res <- runReaderT (httpLbs withQParams) manager res <- runReaderT (httpLbs withQParams) manager
removeFile $ compressedFilePath removeFile compressedFilePath
if getResponseStatus res == status200 if getResponseStatus res == status200
then -- no output is successful then -- no output is successful
pure () pure ()
@@ -637,30 +633,15 @@ eosUpload (EosUpload name img version) = do
where where
sfs2prog :: StreamFileStatus -> Progress () sfs2prog :: StreamFileStatus -> Progress ()
sfs2prog StreamFileStatus{..} = Progress (fromIntegral readSoFar) (fromIntegral fileSize) () sfs2prog StreamFileStatus{..} = Progress (fromIntegral readSoFar) (fromIntegral fileSize) ()
zipOptions = transByteCounter :: MonadIO m => ProgressBar a -> ConduitT B8.ByteString B8.ByteString m ()
ZipOptions transByteCounter bar = awaitForever $ \bs -> do
{ zipOpt64 = True let len = B8.length bs
, zipOptCompressLevel = 6 liftIO $ incProgress bar len
, zipOptInfo = ZipInfo{zipComment = encodeUtf8 "zipped eos image"} yield bs
} cleanup e = do
createZipEntry :: $logError $ show e
MonadResource m => removeFile "/tmp/eos.img.gz"
FilePath -> throwIO e
Maybe Word64 ->
-- ZipData m ->
ConduitT () (ZipEntry, ZipData m) m ()
createZipEntry path size = do
let d = zipFileData img
utcTime <- liftIO getCurrentTime
localTimeZone <- liftIO $ getTimeZone utcTime
let zipEntry =
ZipEntry
{ zipEntryName = Left $ T.pack "eos.img.gz"
, zipEntryTime = utcToLocalTime localTimeZone utcTime
, zipEntrySize = size
, zipEntryExternalAttributes = Nothing
}
yield (zipEntry, d)
index :: String -> String -> Version -> IO () index :: String -> String -> Version -> IO ()