Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavlo Strokov <pstrokov@gitlab.com>2023-06-01 16:02:02 +0300
committerPavlo Strokov <pstrokov@gitlab.com>2023-06-01 18:09:52 +0300
commit16ba7a28f4bf4b2beb06dceedeb615200a4ad3cf (patch)
treed18f3b0608f585da820c98788b258b08cbd2044e
parent008c4b50d12557b1a490a23707bf171b04b21758 (diff)
praefect: Sub-command interruption with SIGINT
Execution of any sub-commands should be possible to interrupt by sending SIGINT signal to the process. It is so for all except the 'serve' command as it has its own handling mechanism.
-rw-r--r--internal/cli/praefect/main.go27
-rw-r--r--internal/cli/praefect/subcmd_check_test.go33
2 files changed, 47 insertions, 13 deletions
diff --git a/internal/cli/praefect/main.go b/internal/cli/praefect/main.go
index 1b2ec299e..b1fcf2007 100644
--- a/internal/cli/praefect/main.go
+++ b/internal/cli/praefect/main.go
@@ -15,10 +15,12 @@ import (
"fmt"
"log"
"os"
+ "os/signal"
"github.com/urfave/cli/v2"
"gitlab.com/gitlab-org/gitaly/v16/internal/praefect/service"
"gitlab.com/gitlab-org/gitaly/v16/internal/version"
+ "golang.org/x/exp/slices"
)
func init() {
@@ -37,6 +39,8 @@ const (
// NewApp returns a new praefect app.
func NewApp() *cli.App {
+ interrupt := make(chan os.Signal, 1)
+
return &cli.App{
Name: progname,
Usage: "a gitaly proxy",
@@ -78,6 +82,29 @@ func NewApp() *cli.App {
Usage: "load configuration from `FILE`",
},
},
+ Before: func(appCtx *cli.Context) error {
+ // Praefect service manages os.Interrupt on its own, by making a "table-flip".
+ // That is why the signal listening is omitted if there are no arguments passed
+ // (old-fashioned method of starting Praefect service) or 'serve' sub-command
+ // is invoked. Other sub-commands require signal to be properly handled.
+ args := appCtx.Args().Slice()
+ if len(args) == 0 || slices.Contains(args, "serve") {
+ return nil
+ }
+
+ signal.Notify(interrupt, os.Interrupt)
+ go func() {
+ if _, ok := <-interrupt; ok {
+ os.Exit(130) // indicates program was interrupted
+ }
+ }()
+
+ return nil
+ },
+ After: func(*cli.Context) error {
+ close(interrupt)
+ return nil
+ },
}
}
diff --git a/internal/cli/praefect/subcmd_check_test.go b/internal/cli/praefect/subcmd_check_test.go
index ba8804625..c970b8520 100644
--- a/internal/cli/praefect/subcmd_check_test.go
+++ b/internal/cli/praefect/subcmd_check_test.go
@@ -181,19 +181,17 @@ Checking check 3...Failed (warning) error: i failed but not too badly
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- var stdout, stderr bytes.Buffer
- app := NewApp()
- app.Writer = &stdout
- app.ErrWriter = &stderr
- for i, cmd := range app.Commands {
- if cmd.Name == "check" {
- app.Commands[i] = newCheckCommand(tc.checks)
- break
- }
- }
-
t.Run("quiet", func(t *testing.T) {
- stdout.Reset()
+ var stdout, stderr bytes.Buffer
+ app := NewApp()
+ app.Writer = &stdout
+ app.ErrWriter = &stderr
+ for i, cmd := range app.Commands {
+ if cmd.Name == "check" {
+ app.Commands[i] = newCheckCommand(tc.checks)
+ break
+ }
+ }
err := app.Run(append([]string{progname, "-config", confPath, "check", "-q"}, tc.args...))
assert.Equal(t, tc.expectedError, err)
if len(tc.args) == 0 {
@@ -203,7 +201,16 @@ Checking check 3...Failed (warning) error: i failed but not too badly
})
t.Run("normal", func(t *testing.T) {
- stdout.Reset()
+ var stdout, stderr bytes.Buffer
+ app := NewApp()
+ app.Writer = &stdout
+ app.ErrWriter = &stderr
+ for i, cmd := range app.Commands {
+ if cmd.Name == "check" {
+ app.Commands[i] = newCheckCommand(tc.checks)
+ break
+ }
+ }
err := app.Run(append([]string{progname, "-config", confPath, "check"}, tc.args...))
assert.Equal(t, tc.expectedError, err)
if len(tc.args) == 0 {