make the assistant retry failed transfers
When a transfer fails, the progress info can be used to intelligently retry it. If the transfer managed to make some progress, but did not fully complete, then there's a good chance that a retry will finish it (or at least make more progress).
This commit is contained in:
parent
d4055b3dd2
commit
df07ccf404
6 changed files with 37 additions and 17 deletions
|
@ -66,7 +66,7 @@ getKeyFile key file dest = dispatch =<< Remote.keyPossibilities key
|
||||||
either (const False) id <$> Remote.hasKey r key
|
either (const False) id <$> Remote.hasKey r key
|
||||||
| otherwise = return True
|
| otherwise = return True
|
||||||
docopy r continue = do
|
docopy r continue = do
|
||||||
ok <- download (Remote.uuid r) key (Just file) $ do
|
ok <- download (Remote.uuid r) key (Just file) noRetry $ do
|
||||||
showAction $ "from " ++ Remote.name r
|
showAction $ "from " ++ Remote.name r
|
||||||
Remote.retrieveKeyFile r key (Just file) dest
|
Remote.retrieveKeyFile r key (Just file) dest
|
||||||
if ok then return ok else continue
|
if ok then return ok else continue
|
||||||
|
|
|
@ -89,7 +89,7 @@ toPerform dest move key file = moveLock move key $ do
|
||||||
stop
|
stop
|
||||||
Right False -> do
|
Right False -> do
|
||||||
showAction $ "to " ++ Remote.name dest
|
showAction $ "to " ++ Remote.name dest
|
||||||
ok <- upload (Remote.uuid dest) key (Just file) $
|
ok <- upload (Remote.uuid dest) key (Just file) noRetry $
|
||||||
Remote.storeKey dest key (Just file)
|
Remote.storeKey dest key (Just file)
|
||||||
if ok
|
if ok
|
||||||
then finish
|
then finish
|
||||||
|
@ -138,7 +138,7 @@ fromPerform src move key file = moveLock move key $
|
||||||
, handle move =<< go
|
, handle move =<< go
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
go = download (Remote.uuid src) key (Just file) $ do
|
go = download (Remote.uuid src) key (Just file) noRetry $ do
|
||||||
showAction $ "from " ++ Remote.name src
|
showAction $ "from " ++ Remote.name src
|
||||||
getViaTmp key $ Remote.retrieveKeyFile src key (Just file)
|
getViaTmp key $ Remote.retrieveKeyFile src key (Just file)
|
||||||
handle _ False = stop -- failed
|
handle _ False = stop -- failed
|
||||||
|
|
|
@ -24,7 +24,7 @@ seek = [withKeys start]
|
||||||
|
|
||||||
start :: Key -> CommandStart
|
start :: Key -> CommandStart
|
||||||
start key = ifM (inAnnex key)
|
start key = ifM (inAnnex key)
|
||||||
( fieldTransfer Upload key $ \p -> do
|
( fieldTransfer Upload key $ \_p -> do
|
||||||
file <- inRepo $ gitAnnexLocation key
|
file <- inRepo $ gitAnnexLocation key
|
||||||
liftIO $ rsyncServerSend file
|
liftIO $ rsyncServerSend file
|
||||||
, do
|
, do
|
||||||
|
@ -36,7 +36,7 @@ fieldTransfer :: Direction -> Key -> (MeterUpdate -> Annex Bool) -> CommandStart
|
||||||
fieldTransfer direction key a = do
|
fieldTransfer direction key a = do
|
||||||
afile <- Fields.getField Fields.associatedFile
|
afile <- Fields.getField Fields.associatedFile
|
||||||
ok <- maybe (a $ const noop)
|
ok <- maybe (a $ const noop)
|
||||||
(\u -> runTransfer (Transfer direction (toUUID u) key) afile a)
|
(\u -> runTransfer (Transfer direction (toUUID u) key) afile noRetry a)
|
||||||
=<< Fields.getField Fields.remoteUUID
|
=<< Fields.getField Fields.remoteUUID
|
||||||
if ok
|
if ok
|
||||||
then liftIO exitSuccess
|
then liftIO exitSuccess
|
||||||
|
|
|
@ -43,7 +43,7 @@ start to from file key =
|
||||||
|
|
||||||
toPerform :: Remote -> Key -> AssociatedFile -> CommandPerform
|
toPerform :: Remote -> Key -> AssociatedFile -> CommandPerform
|
||||||
toPerform remote key file = next $
|
toPerform remote key file = next $
|
||||||
upload (uuid remote) key file $ \p -> do
|
upload (uuid remote) key file forwardRetry $ \p -> do
|
||||||
ok <- Remote.storeKey remote key file p
|
ok <- Remote.storeKey remote key file p
|
||||||
when ok $
|
when ok $
|
||||||
Remote.logStatus remote key InfoPresent
|
Remote.logStatus remote key InfoPresent
|
||||||
|
@ -51,5 +51,5 @@ toPerform remote key file = next $
|
||||||
|
|
||||||
fromPerform :: Remote -> Key -> AssociatedFile -> CommandPerform
|
fromPerform :: Remote -> Key -> AssociatedFile -> CommandPerform
|
||||||
fromPerform remote key file = next $
|
fromPerform remote key file = next $
|
||||||
download (uuid remote) key file $
|
download (uuid remote) key file forwardRetry $
|
||||||
getViaTmp key $ Remote.retrieveKeyFile remote key file
|
getViaTmp key $ Remote.retrieveKeyFile remote key file
|
||||||
|
|
|
@ -74,11 +74,21 @@ percentComplete :: Transfer -> TransferInfo -> Maybe Percentage
|
||||||
percentComplete (Transfer { transferKey = key }) info =
|
percentComplete (Transfer { transferKey = key }) info =
|
||||||
percentage <$> keySize key <*> Just (fromMaybe 0 $ bytesComplete info)
|
percentage <$> keySize key <*> Just (fromMaybe 0 $ bytesComplete info)
|
||||||
|
|
||||||
upload :: UUID -> Key -> AssociatedFile -> (MeterUpdate -> Annex Bool) -> Annex Bool
|
type RetryDecider = TransferInfo -> TransferInfo -> Bool
|
||||||
upload u key file a = runTransfer (Transfer Upload u key) file a
|
|
||||||
|
|
||||||
download :: UUID -> Key -> AssociatedFile -> Annex Bool -> Annex Bool
|
noRetry :: RetryDecider
|
||||||
download u key file a = runTransfer (Transfer Download u key) file (const a)
|
noRetry _ _ = False
|
||||||
|
|
||||||
|
{- Retries a transfer when it fails, as long as the failed transfer managed
|
||||||
|
- to send some data. -}
|
||||||
|
forwardRetry :: RetryDecider
|
||||||
|
forwardRetry old new = bytesComplete old < bytesComplete new
|
||||||
|
|
||||||
|
upload :: UUID -> Key -> AssociatedFile -> RetryDecider -> (MeterUpdate -> Annex Bool) -> Annex Bool
|
||||||
|
upload u key = runTransfer (Transfer Upload u key)
|
||||||
|
|
||||||
|
download :: UUID -> Key -> AssociatedFile -> RetryDecider -> Annex Bool -> Annex Bool
|
||||||
|
download u key file shouldretry a = runTransfer (Transfer Download u key) file shouldretry (const a)
|
||||||
|
|
||||||
{- Runs a transfer action. Creates and locks the lock file while the
|
{- Runs a transfer action. Creates and locks the lock file while the
|
||||||
- action is running, and stores info in the transfer information
|
- action is running, and stores info in the transfer information
|
||||||
|
@ -87,12 +97,12 @@ download u key file a = runTransfer (Transfer Download u key) file (const a)
|
||||||
- If the transfer action returns False, the transfer info is
|
- If the transfer action returns False, the transfer info is
|
||||||
- left in the failedTransferDir.
|
- left in the failedTransferDir.
|
||||||
-}
|
-}
|
||||||
runTransfer :: Transfer -> Maybe FilePath -> (MeterUpdate -> Annex Bool) -> Annex Bool
|
runTransfer :: Transfer -> Maybe FilePath -> RetryDecider -> (MeterUpdate -> Annex Bool) -> Annex Bool
|
||||||
runTransfer t file a = do
|
runTransfer t file shouldretry a = do
|
||||||
info <- liftIO $ startTransferInfo file
|
info <- liftIO $ startTransferInfo file
|
||||||
(meter, tfile) <- mkProgressUpdater t info
|
(meter, tfile) <- mkProgressUpdater t info
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
ok <- bracketIO (prep tfile mode info) (cleanup tfile) (a meter)
|
ok <- retry tfile info $ bracketIO (prep tfile mode info) (cleanup tfile) (a meter)
|
||||||
unless ok $ failed info
|
unless ok $ failed info
|
||||||
return ok
|
return ok
|
||||||
where
|
where
|
||||||
|
@ -113,7 +123,17 @@ runTransfer t file a = do
|
||||||
failedtfile <- fromRepo $ failedTransferFile t
|
failedtfile <- fromRepo $ failedTransferFile t
|
||||||
createAnnexDirectory $ takeDirectory failedtfile
|
createAnnexDirectory $ takeDirectory failedtfile
|
||||||
liftIO $ writeTransferInfoFile info failedtfile
|
liftIO $ writeTransferInfoFile info failedtfile
|
||||||
|
retry tfile oldinfo run = do
|
||||||
|
ok <- run
|
||||||
|
if ok
|
||||||
|
then return ok
|
||||||
|
else do
|
||||||
|
v <- liftIO $ readTransferInfoFile Nothing tfile
|
||||||
|
case v of
|
||||||
|
Nothing -> return ok
|
||||||
|
Just newinfo -> if shouldretry oldinfo newinfo
|
||||||
|
then retry tfile newinfo run
|
||||||
|
else return ok
|
||||||
|
|
||||||
{- Generates a callback that can be called as transfer progresses to update
|
{- Generates a callback that can be called as transfer progresses to update
|
||||||
- the transfer info file. Also returns the file it'll be updating. -}
|
- the transfer info file. Also returns the file it'll be updating. -}
|
||||||
|
|
|
@ -247,7 +247,7 @@ copyFromRemote r key file dest
|
||||||
liftIO $ onLocal r $ do
|
liftIO $ onLocal r $ do
|
||||||
ensureInitialized
|
ensureInitialized
|
||||||
loc <- inRepo $ gitAnnexLocation key
|
loc <- inRepo $ gitAnnexLocation key
|
||||||
upload u key file $
|
upload u key file noRetry $
|
||||||
rsyncOrCopyFile params loc dest
|
rsyncOrCopyFile params loc dest
|
||||||
| Git.repoIsSsh r = feedprogressback $ \feeder ->
|
| Git.repoIsSsh r = feedprogressback $ \feeder ->
|
||||||
rsyncHelper (Just feeder)
|
rsyncHelper (Just feeder)
|
||||||
|
@ -317,7 +317,7 @@ copyToRemote r key file p
|
||||||
( return False
|
( return False
|
||||||
, do
|
, do
|
||||||
ensureInitialized
|
ensureInitialized
|
||||||
download u key file $
|
download u key file noRetry $
|
||||||
Annex.Content.saveState True `after`
|
Annex.Content.saveState True `after`
|
||||||
Annex.Content.getViaTmp key
|
Annex.Content.getViaTmp key
|
||||||
(\d -> rsyncOrCopyFile params keysrc d p)
|
(\d -> rsyncOrCopyFile params keysrc d p)
|
||||||
|
|
Loading…
Reference in a new issue