Use request timeout for git service rpc (#20689)
This enables git.Command's Run to optionally use the given context directly so its deadline will be respected. Otherwise, it falls back to the previous behavior of using the supplied timeout or a default timeout value of 360 seconds. repo's serviceRPC() calls now use the context's deadline (which is unset/unlimited) instead of the default 6-minute timeout. This means that large repo clones will no longer arbitrarily time out on the upload-pack step, and pushes can take longer than 6 minutes on the receive-pack step. Fixes #20680 Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
279e4e235c
commit
27789908d8
2 changed files with 23 additions and 13 deletions
|
@ -95,14 +95,15 @@ func (c *Command) AddArguments(args ...string) *Command {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunOpts represents parameters to run the command
|
// RunOpts represents parameters to run the command. If UseContextTimeout is specified, then Timeout is ignored.
|
||||||
type RunOpts struct {
|
type RunOpts struct {
|
||||||
Env []string
|
Env []string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
Dir string
|
UseContextTimeout bool
|
||||||
Stdout, Stderr io.Writer
|
Dir string
|
||||||
Stdin io.Reader
|
Stdout, Stderr io.Writer
|
||||||
PipelineFunc func(context.Context, context.CancelFunc) error
|
Stdin io.Reader
|
||||||
|
PipelineFunc func(context.Context, context.CancelFunc) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonBaseEnvs() []string {
|
func commonBaseEnvs() []string {
|
||||||
|
@ -171,7 +172,15 @@ func (c *Command) Run(opts *RunOpts) error {
|
||||||
desc = fmt.Sprintf("%s %s [repo_path: %s]", c.name, strings.Join(args, " "), opts.Dir)
|
desc = fmt.Sprintf("%s %s [repo_path: %s]", c.name, strings.Join(args, " "), opts.Dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel, finished := process.GetManager().AddContextTimeout(c.parentContext, opts.Timeout, desc)
|
var ctx context.Context
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
var finished context.CancelFunc
|
||||||
|
|
||||||
|
if opts.UseContextTimeout {
|
||||||
|
ctx, cancel, finished = process.GetManager().AddContext(c.parentContext, desc)
|
||||||
|
} else {
|
||||||
|
ctx, cancel, finished = process.GetManager().AddContextTimeout(c.parentContext, opts.Timeout, desc)
|
||||||
|
}
|
||||||
defer finished()
|
defer finished()
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, c.name, c.args...)
|
cmd := exec.CommandContext(ctx, c.name, c.args...)
|
||||||
|
|
|
@ -474,11 +474,12 @@ func serviceRPC(ctx gocontext.Context, h serviceHandler, service string) {
|
||||||
cmd := git.NewCommand(h.r.Context(), service, "--stateless-rpc", h.dir)
|
cmd := git.NewCommand(h.r.Context(), service, "--stateless-rpc", h.dir)
|
||||||
cmd.SetDescription(fmt.Sprintf("%s %s %s [repo_path: %s]", git.GitExecutable, service, "--stateless-rpc", h.dir))
|
cmd.SetDescription(fmt.Sprintf("%s %s %s [repo_path: %s]", git.GitExecutable, service, "--stateless-rpc", h.dir))
|
||||||
if err := cmd.Run(&git.RunOpts{
|
if err := cmd.Run(&git.RunOpts{
|
||||||
Dir: h.dir,
|
Dir: h.dir,
|
||||||
Env: append(os.Environ(), h.environ...),
|
Env: append(os.Environ(), h.environ...),
|
||||||
Stdout: h.w,
|
Stdout: h.w,
|
||||||
Stdin: reqBody,
|
Stdin: reqBody,
|
||||||
Stderr: &stderr,
|
Stderr: &stderr,
|
||||||
|
UseContextTimeout: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if err.Error() != "signal: killed" {
|
if err.Error() != "signal: killed" {
|
||||||
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.dir, err, stderr.String())
|
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.dir, err, stderr.String())
|
||||||
|
|
Loading…
Add table
Reference in a new issue