diff options
author | Joey Hess <joey@kitenet.net> | 2012-06-25 16:10:10 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-06-25 16:10:24 -0400 |
commit | 0b146f9ecc36545478c4a2218981b376828c61db (patch) | |
tree | c7c758fb5421d61e6b286b76ec474dd9b04450df /Assistant/Threads/Pusher.hs | |
parent | 19eee6a1df2a6c724e6d6dbe842b40dc1c17f65b (diff) |
reorg threads
Diffstat (limited to 'Assistant/Threads/Pusher.hs')
-rw-r--r-- | Assistant/Threads/Pusher.hs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/Assistant/Threads/Pusher.hs b/Assistant/Threads/Pusher.hs new file mode 100644 index 000000000..de90d4e64 --- /dev/null +++ b/Assistant/Threads/Pusher.hs @@ -0,0 +1,69 @@ +{- git-annex assistant git pushing thread + - + - Copyright 2012 Joey Hess <joey@kitenet.net> + - + - Licensed under the GNU GPL version 3 or higher. + -} + +module Assistant.Threads.Pusher where + +import Common.Annex +import Assistant.Commits +import Assistant.ThreadedMonad +import qualified Command.Sync +import Utility.ThreadScheduler +import Utility.Parallel + +import Data.Time.Clock + +data FailedPush = FailedPush + { failedRemote :: Remote + , failedTimeStamp :: UTCTime + } + +{- This thread pushes git commits out to remotes. -} +pushThread :: ThreadState -> CommitChan -> IO () +pushThread st commitchan = do + remotes <- runThreadState st $ Command.Sync.syncRemotes [] + runEveryWith (Seconds 2) [] $ \failedpushes -> do + -- We already waited two seconds as a simple rate limiter. + -- Next, wait until at least one commit has been made + commits <- getCommits commitchan + -- Now see if now's a good time to push. + time <- getCurrentTime + if shouldPush time commits failedpushes + then pushToRemotes time st remotes + else do + refillCommits commitchan commits + return failedpushes + +{- Decide if now is a good time to push to remotes. + - + - Current strategy: Immediately push all commits. The commit machinery + - already determines batches of changes, so we can't easily determine + - batches better. + - + - TODO: FailedPushs are only retried the next time there's a commit. + - Should retry them periodically, or when a remote that was not available + - becomes available. + -} +shouldPush :: UTCTime -> [Commit] -> [FailedPush] -> Bool +shouldPush _now commits _failedremotes + | not (null commits) = True + | otherwise = False + +{- Updates the local sync branch, then pushes it to all remotes, in + - parallel. + - + - Avoids running possibly long-duration commands in the Annex monad, so + - as not to block other threads. -} +pushToRemotes :: UTCTime -> ThreadState -> [Remote] -> IO [FailedPush] +pushToRemotes now st remotes = do + (g, branch) <- runThreadState st $ + (,) <$> fromRepo id <*> Command.Sync.currentBranch + Command.Sync.updateBranch (Command.Sync.syncBranch branch) g + map (`FailedPush` now) <$> inParallel (push g branch) remotes + where + push g branch remote = + ifM (Command.Sync.pushBranch remote branch g) + ( exitSuccess, exitFailure) |