feat(minio): use separate bucket for temporary files
This commit is contained in:
parent
fc9a78a7b3
commit
1cd79d35e2
@ -168,6 +168,7 @@ upload-cache:
|
|||||||
auto-discover-region: "_env:UPLOAD_S3_AUTO_DISCOVER_REGION:true"
|
auto-discover-region: "_env:UPLOAD_S3_AUTO_DISCOVER_REGION:true"
|
||||||
disable-cert-validation: "_env:UPLOAD_S3_DISABLE_CERT_VALIDATION:false"
|
disable-cert-validation: "_env:UPLOAD_S3_DISABLE_CERT_VALIDATION:false"
|
||||||
upload-cache-bucket: "uni2work-uploads"
|
upload-cache-bucket: "uni2work-uploads"
|
||||||
|
upload-tmp-bucket: "uni2work-tmp"
|
||||||
|
|
||||||
inject-files: 601
|
inject-files: 601
|
||||||
rechunk-files: 1201
|
rechunk-files: 1201
|
||||||
|
|||||||
@ -159,6 +159,7 @@ dependencies:
|
|||||||
- topograph
|
- topograph
|
||||||
- network-uri
|
- network-uri
|
||||||
- psqueues
|
- psqueues
|
||||||
|
- nonce
|
||||||
other-extensions:
|
other-extensions:
|
||||||
- GeneralizedNewtypeDeriving
|
- GeneralizedNewtypeDeriving
|
||||||
- IncoherentInstances
|
- IncoherentInstances
|
||||||
|
|||||||
@ -277,8 +277,9 @@ makeFoundation appSettings''@AppSettings{..} = do
|
|||||||
conn <- Minio.connect minioConf
|
conn <- Minio.connect minioConf
|
||||||
let isBucketExists Minio.BucketAlreadyOwnedByYou = True
|
let isBucketExists Minio.BucketAlreadyOwnedByYou = True
|
||||||
isBucketExists _ = False
|
isBucketExists _ = False
|
||||||
either throwM return <=< Minio.runMinioWith conn $
|
either throwM return <=< Minio.runMinioWith conn $ do
|
||||||
handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadCacheBucket Nothing
|
handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadCacheBucket Nothing
|
||||||
|
handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadTmpBucket Nothing
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
$logDebugS "Runtime configuration" $ tshow appSettings'
|
$logDebugS "Runtime configuration" $ tshow appSettings'
|
||||||
|
|||||||
@ -184,7 +184,7 @@ data AppSettings = AppSettings
|
|||||||
, appMemcachedConf :: Maybe MemcachedConf
|
, appMemcachedConf :: Maybe MemcachedConf
|
||||||
|
|
||||||
, appUploadCacheConf :: Maybe Minio.ConnectInfo
|
, appUploadCacheConf :: Maybe Minio.ConnectInfo
|
||||||
, appUploadCacheBucket :: Minio.Bucket
|
, appUploadCacheBucket, appUploadTmpBucket :: Minio.Bucket
|
||||||
, appInjectFiles :: Maybe NominalDiffTime
|
, appInjectFiles :: Maybe NominalDiffTime
|
||||||
, appRechunkFiles :: Maybe NominalDiffTime
|
, appRechunkFiles :: Maybe NominalDiffTime
|
||||||
, appCheckMissingFiles :: Maybe NominalDiffTime
|
, appCheckMissingFiles :: Maybe NominalDiffTime
|
||||||
@ -619,6 +619,7 @@ instance FromJSON AppSettings where
|
|||||||
|
|
||||||
appUploadCacheConf <- assertM (not . null . Minio.connectHost) <$> o .:? "upload-cache"
|
appUploadCacheConf <- assertM (not . null . Minio.connectHost) <$> o .:? "upload-cache"
|
||||||
appUploadCacheBucket <- o .: "upload-cache-bucket"
|
appUploadCacheBucket <- o .: "upload-cache-bucket"
|
||||||
|
appUploadTmpBucket <- o .: "upload-tmp-bucket"
|
||||||
|
|
||||||
appFallbackPersonalisedSheetFilesKeysExpire <- o .: "fallback-personalised-sheet-files-keys-expire"
|
appFallbackPersonalisedSheetFilesKeysExpire <- o .: "fallback-personalised-sheet-files-keys-expire"
|
||||||
|
|
||||||
|
|||||||
@ -29,9 +29,7 @@ import qualified Data.Sequence as Seq
|
|||||||
|
|
||||||
import Database.Persist.Sql (deleteWhereCount)
|
import Database.Persist.Sql (deleteWhereCount)
|
||||||
|
|
||||||
import Control.Monad.Trans.Resource (allocate)
|
import Control.Monad.Trans.Resource (allocate, register, release)
|
||||||
|
|
||||||
import qualified Data.UUID.V4 as UUID
|
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
import qualified Database.Esqueleto.Utils as E
|
import qualified Database.Esqueleto.Utils as E
|
||||||
@ -40,6 +38,9 @@ import Data.Conduit.Algorithms.FastCDC (fastCDC)
|
|||||||
|
|
||||||
import Control.Monad.Trans.Cont
|
import Control.Monad.Trans.Cont
|
||||||
|
|
||||||
|
import qualified Crypto.Nonce as Nonce
|
||||||
|
import System.IO.Unsafe
|
||||||
|
|
||||||
|
|
||||||
sinkFileDB :: (MonadCatch m, MonadHandler m, HandlerSite m ~ UniWorX, MonadUnliftIO m, BackendCompatible SqlBackend (YesodPersistBackend UniWorX), YesodPersist UniWorX)
|
sinkFileDB :: (MonadCatch m, MonadHandler m, HandlerSite m ~ UniWorX, MonadUnliftIO m, BackendCompatible SqlBackend (YesodPersistBackend UniWorX), YesodPersist UniWorX)
|
||||||
=> Bool -- ^ Replace? Use only in serializable transaction
|
=> Bool -- ^ Replace? Use only in serializable transaction
|
||||||
@ -96,12 +97,17 @@ sinkFileDB doReplace fileContentContent = do
|
|||||||
where fileContentChunkContentBased = True
|
where fileContentChunkContentBased = True
|
||||||
|
|
||||||
|
|
||||||
|
minioTmpGenerator :: Nonce.Generator
|
||||||
|
minioTmpGenerator = unsafePerformIO Nonce.new
|
||||||
|
{-# NOINLINE minioTmpGenerator #-}
|
||||||
|
|
||||||
sinkFileMinio :: (MonadCatch m, MonadHandler m, HandlerSite m ~ UniWorX, MonadUnliftIO m)
|
sinkFileMinio :: (MonadCatch m, MonadHandler m, HandlerSite m ~ UniWorX, MonadUnliftIO m)
|
||||||
=> ConduitT () ByteString m ()
|
=> ConduitT () ByteString m ()
|
||||||
-> MaybeT m FileContentReference
|
-> MaybeT m FileContentReference
|
||||||
-- ^ Cannot deal with zero length uploads
|
-- ^ Cannot deal with zero length uploads
|
||||||
sinkFileMinio fileContentContent = do
|
sinkFileMinio fileContentContent = do
|
||||||
uploadBucket <- getsYesod $ views appSettings appUploadCacheBucket
|
uploadBucket <- getsYesod $ views appSettings appUploadCacheBucket
|
||||||
|
tmpBucket <- getsYesod $ views appSettings appUploadTmpBucket
|
||||||
chunk <- liftIO newEmptyMVar
|
chunk <- liftIO newEmptyMVar
|
||||||
let putChunks = do
|
let putChunks = do
|
||||||
nextChunk <- await
|
nextChunk <- await
|
||||||
@ -119,16 +125,17 @@ sinkFileMinio fileContentContent = do
|
|||||||
.| Crypto.sinkHash
|
.| Crypto.sinkHash
|
||||||
|
|
||||||
runAppMinio $ do
|
runAppMinio $ do
|
||||||
tmpUUID <- liftIO UUID.nextRandom
|
uploadName <- Nonce.nonce128urlT minioTmpGenerator
|
||||||
let uploadName = ".tmp." <> toPathPiece tmpUUID
|
let pooOptions = Minio.defaultPutObjectOptions
|
||||||
pooOptions = Minio.defaultPutObjectOptions
|
|
||||||
{ Minio.pooCacheControl = Just "immutable"
|
{ Minio.pooCacheControl = Just "immutable"
|
||||||
}
|
}
|
||||||
Minio.putObject uploadBucket uploadName (C.unfoldM (\x -> fmap (, x) <$> takeMVar chunk) ()) Nothing pooOptions
|
removeObject <- withRunInIO $ \runInIO -> runInIO . register . runInIO $ Minio.removeObject tmpBucket uploadName
|
||||||
|
Minio.putObject tmpBucket uploadName (C.unfoldM (\x -> fmap (, x) <$> takeMVar chunk) ()) Nothing pooOptions
|
||||||
fileContentHash <- review _Wrapped <$> waitAsync sinkAsync
|
fileContentHash <- review _Wrapped <$> waitAsync sinkAsync
|
||||||
let dstName = minioFileReference # fileContentHash
|
let dstName = minioFileReference # fileContentHash
|
||||||
copySrc = Minio.defaultSourceInfo
|
copySrc = Minio.defaultSourceInfo
|
||||||
{ Minio.srcBucket = uploadBucket, Minio.srcObject = uploadName
|
{ Minio.srcBucket = tmpBucket
|
||||||
|
, Minio.srcObject = uploadName
|
||||||
}
|
}
|
||||||
copyDst = Minio.defaultDestinationInfo
|
copyDst = Minio.defaultDestinationInfo
|
||||||
{ Minio.dstBucket = uploadBucket
|
{ Minio.dstBucket = uploadBucket
|
||||||
@ -137,7 +144,7 @@ sinkFileMinio fileContentContent = do
|
|||||||
uploadExists <- handleIf minioIsDoesNotExist (const $ return False) $ True <$ Minio.statObject uploadBucket dstName Minio.defaultGetObjectOptions
|
uploadExists <- handleIf minioIsDoesNotExist (const $ return False) $ True <$ Minio.statObject uploadBucket dstName Minio.defaultGetObjectOptions
|
||||||
unless uploadExists $
|
unless uploadExists $
|
||||||
Minio.copyObject copyDst copySrc
|
Minio.copyObject copyDst copySrc
|
||||||
Minio.removeObject uploadBucket uploadName
|
release removeObject
|
||||||
return fileContentHash
|
return fileContentHash
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user