Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement retry logic to fix LFS storage race conditions on Windows
Testing showed that while race condition analysis in #3880 was correct, the way it tries to fix that does not work for the *first* git-lfs process that will actually perform file move. Instead, this commit performs multiple attempts when working with files in LFS storage. Similar logic is already implemented in "cmd/go/internal/robustio" and "cmd/go/internal/renameio" packages. However, they are not public, so we cannot use them.
- Loading branch information
1 parent
470398c
commit 67c173b
Showing
7 changed files
with
62 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// +build !windows | ||
|
||
package tools | ||
|
||
import "os" | ||
|
||
func RobustRename(oldpath, newpath string) error { | ||
return os.Rename(oldpath, newpath) | ||
} | ||
|
||
func RobustOpen(name string) (*os.File, error) { | ||
return os.Open(name) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// +build windows | ||
|
||
package tools | ||
|
||
import ( | ||
"github.com/avast/retry-go" | ||
"os" | ||
"syscall" | ||
) | ||
|
||
const ( | ||
// This is private in [go]/src/internal/syscall/windows/syscall_windows.go :( | ||
ERROR_SHARING_VIOLATION syscall.Errno = 32 | ||
) | ||
|
||
// isEphemeralError returns true if err may be resolved by waiting. | ||
func isEphemeralError(err error) bool { | ||
return err == ERROR_SHARING_VIOLATION | ||
} | ||
|
||
func RobustRename(oldpath, newpath string) error { | ||
return retry.Do( | ||
func() error { | ||
return os.Rename(oldpath, newpath) | ||
}, | ||
retry.RetryIf(isEphemeralError), | ||
retry.LastErrorOnly(true), | ||
) | ||
} | ||
|
||
func RobustOpen(name string) (*os.File, error) { | ||
var result *os.File | ||
return result, retry.Do( | ||
func() error { | ||
f, err := os.Open(name) | ||
result = f | ||
return err | ||
}, | ||
retry.RetryIf(isEphemeralError), | ||
retry.LastErrorOnly(true), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters