diff options
author | Sami Hiltunen <shiltunen@gitlab.com> | 2020-08-06 13:31:16 +0300 |
---|---|---|
committer | Sami Hiltunen <shiltunen@gitlab.com> | 2020-08-07 13:41:17 +0300 |
commit | 9d0937cc128d601681a8d5a1effb20a4c3813a76 (patch) | |
tree | 71bfa9c54c74c772ffa9e517d8009bf04a8073b5 | |
parent | 9e5dfd987388c905b584f58b48afede245721ec7 (diff) |
report only read-only repositories by default in dataloss
`dataloss` command currenly display every outdated repository on a
virtual storage by default. While outdated secondaries should also
be fixed, they do not require immediate administrator action as they
do not affect the writability of the repository. Secondaries might also
be outdated only temporarily until a replication job brings them up to
date.
Outdated primary requires administrator action to enable the repository
for writes again. This is currently a permanent state until administrator
takes action. To reduce the noise from the tool, this commit only displays
read-only repositories by default. Listing outdated writable repositories is
still supported via the `-partially-replicated` flag.
-rw-r--r-- | changelogs/unreleased/smh-dataloss-filter-read-only.yml | 5 | ||||
-rw-r--r-- | cmd/praefect/subcmd_dataloss.go | 32 | ||||
-rw-r--r-- | cmd/praefect/subcmd_dataloss_test.go | 35 | ||||
-rw-r--r-- | internal/praefect/service/info/dataloss.go | 10 | ||||
-rw-r--r-- | proto/go/gitalypb/praefect.pb.go | 138 | ||||
-rw-r--r-- | proto/praefect.proto | 10 | ||||
-rw-r--r-- | ruby/proto/gitaly/praefect_pb.rb | 2 | ||||
-rw-r--r-- | ruby/proto/gitaly/praefect_services_pb.rb | 3 |
8 files changed, 160 insertions, 75 deletions
diff --git a/changelogs/unreleased/smh-dataloss-filter-read-only.yml b/changelogs/unreleased/smh-dataloss-filter-read-only.yml new file mode 100644 index 000000000..bc4b0b8f9 --- /dev/null +++ b/changelogs/unreleased/smh-dataloss-filter-read-only.yml @@ -0,0 +1,5 @@ +--- +title: Report only read-only repositories by default in dataloss +merge_request: 2449 +author: +type: changed diff --git a/cmd/praefect/subcmd_dataloss.go b/cmd/praefect/subcmd_dataloss.go index db23ccd5e..460e374ba 100644 --- a/cmd/praefect/subcmd_dataloss.go +++ b/cmd/praefect/subcmd_dataloss.go @@ -21,8 +21,9 @@ func (err unexpectedPositionalArgsError) Error() string { } type datalossSubcommand struct { - output io.Writer - virtualStorage string + output io.Writer + virtualStorage string + includePartiallyReplicated bool } func newDatalossSubcommand() *datalossSubcommand { @@ -32,6 +33,12 @@ func newDatalossSubcommand() *datalossSubcommand { func (cmd *datalossSubcommand) FlagSet() *flag.FlagSet { fs := flag.NewFlagSet("dataloss", flag.ContinueOnError) fs.StringVar(&cmd.virtualStorage, "virtual-storage", "", "virtual storage to check for data loss") + fs.BoolVar(&cmd.includePartiallyReplicated, "partially-replicated", false, strings.TrimSpace(` +Additionally include repositories which are fully up to date on the +primary but outdated on some secondaries. Such repositories are writable +and do not suffer from data loss. The data on the primary is not fully +replicated to all secondaries which leads to increased risk of data loss +following a failover.`)) return fs } @@ -74,7 +81,8 @@ func (cmd *datalossSubcommand) Exec(flags *flag.FlagSet, cfg config.Config) erro for _, vs := range virtualStorages { resp, err := client.DatalossCheck(context.Background(), &gitalypb.DatalossCheckRequest{ - VirtualStorage: vs, + VirtualStorage: vs, + IncludePartiallyReplicated: cmd.includePartiallyReplicated, }) if err != nil { return fmt.Errorf("error checking: %v", err) @@ -83,14 +91,24 @@ func (cmd *datalossSubcommand) Exec(flags *flag.FlagSet, cfg config.Config) erro cmd.println(0, "Virtual storage: %s", vs) cmd.println(1, "Primary: %s", resp.Primary) if len(resp.Repositories) == 0 { - cmd.println(1, "All repositories are up to date!") + msg := "All repositories are writable!" + if cmd.includePartiallyReplicated { + msg = "All repositories are up to date!" + } + + cmd.println(1, msg) continue } cmd.println(1, "Outdated repositories:") - for _, r := range resp.Repositories { - cmd.println(2, "%s:", r.RelativePath) - for _, s := range r.Storages { + for _, repo := range resp.Repositories { + mode := "writable" + if repo.ReadOnly { + mode = "read-only" + } + + cmd.println(2, "%s (%s):", repo.RelativePath, mode) + for _, s := range repo.Storages { plural := "" if s.BehindBy > 1 { plural = "s" diff --git a/cmd/praefect/subcmd_dataloss_test.go b/cmd/praefect/subcmd_dataloss_test.go index 15daeba45..ee6113f07 100644 --- a/cmd/praefect/subcmd_dataloss_test.go +++ b/cmd/praefect/subcmd_dataloss_test.go @@ -59,27 +59,50 @@ func TestDatalossSubcommand(t *testing.T) { error: unexpectedPositionalArgsError{Command: "dataloss"}, }, { - desc: "data loss", + desc: "data loss with read-only repositories", args: []string{"-virtual-storage=virtual-storage-1"}, output: `Virtual storage: virtual-storage-1 Primary: gitaly-1 Outdated repositories: - repository-1: + repository-2 (read-only): + gitaly-1 is behind by 1 change or less +`, + }, + { + desc: "data loss with partially replicated repositories", + args: []string{"-virtual-storage=virtual-storage-1", "-partially-replicated"}, output: `Virtual storage: virtual-storage-1 + Primary: gitaly-1 + Outdated repositories: + repository-1 (writable): gitaly-2 is behind by 1 change or less gitaly-3 is behind by 2 changes or less - repository-2: + repository-2 (read-only): + gitaly-1 is behind by 1 change or less +`, + }, + { + desc: "multiple virtual storages with read-only repositories", + virtualStorages: []*config.VirtualStorage{{Name: "virtual-storage-2"}, {Name: "virtual-storage-1"}}, + output: `Virtual storage: virtual-storage-1 + Primary: gitaly-1 + Outdated repositories: + repository-2 (read-only): gitaly-1 is behind by 1 change or less +Virtual storage: virtual-storage-2 + Primary: gitaly-4 + All repositories are writable! `, }, { - desc: "multiple virtual storages", + desc: "multiple virtual storages with partially replicated repositories", + args: []string{"-partially-replicated"}, virtualStorages: []*config.VirtualStorage{{Name: "virtual-storage-2"}, {Name: "virtual-storage-1"}}, output: `Virtual storage: virtual-storage-1 Primary: gitaly-1 Outdated repositories: - repository-1: + repository-1 (writable): gitaly-2 is behind by 1 change or less gitaly-3 is behind by 2 changes or less - repository-2: + repository-2 (read-only): gitaly-1 is behind by 1 change or less Virtual storage: virtual-storage-2 Primary: gitaly-4 diff --git a/internal/praefect/service/info/dataloss.go b/internal/praefect/service/info/dataloss.go index 5ce72ce7f..cf657685f 100644 --- a/internal/praefect/service/info/dataloss.go +++ b/internal/praefect/service/info/dataloss.go @@ -20,18 +20,28 @@ func (s *Server) DatalossCheck(ctx context.Context, req *gitalypb.DatalossCheckR pbRepos := make([]*gitalypb.DatalossCheckResponse_Repository, 0, len(outdatedRepos)) for relativePath, storages := range outdatedRepos { + readOnly := false pbStorages := make([]*gitalypb.DatalossCheckResponse_Repository_Storage, 0, len(storages)) for name, behindBy := range storages { + if name == shard.Primary.GetStorage() { + readOnly = true + } + pbStorages = append(pbStorages, &gitalypb.DatalossCheckResponse_Repository_Storage{ Name: name, BehindBy: int64(behindBy), }) } + if !req.IncludePartiallyReplicated && !readOnly { + continue + } + sort.Slice(pbStorages, func(i, j int) bool { return pbStorages[i].Name < pbStorages[j].Name }) pbRepos = append(pbRepos, &gitalypb.DatalossCheckResponse_Repository{ RelativePath: relativePath, + ReadOnly: readOnly, Storages: pbStorages, }) } diff --git a/proto/go/gitalypb/praefect.pb.go b/proto/go/gitalypb/praefect.pb.go index 3e156657d..e674376e7 100644 --- a/proto/go/gitalypb/praefect.pb.go +++ b/proto/go/gitalypb/praefect.pb.go @@ -111,10 +111,15 @@ func (m *SetAuthoritativeStorageResponse) XXX_DiscardUnknown() { var xxx_messageInfo_SetAuthoritativeStorageResponse proto.InternalMessageInfo type DatalossCheckRequest struct { - VirtualStorage string `protobuf:"bytes,1,opt,name=virtual_storage,json=virtualStorage,proto3" json:"virtual_storage,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + VirtualStorage string `protobuf:"bytes,1,opt,name=virtual_storage,json=virtualStorage,proto3" json:"virtual_storage,omitempty"` + // include_partially_replicated decides whether to include repositories which are fully up to date + // on the primary but are outdated on some secondaries. Such repositories are still writable and do + // not suffer from data loss. The data on the primary is not fully replicated which increases the + // chances of data loss following a failover. + IncludePartiallyReplicated bool `protobuf:"varint,2,opt,name=include_partially_replicated,json=includePartiallyReplicated,proto3" json:"include_partially_replicated,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *DatalossCheckRequest) Reset() { *m = DatalossCheckRequest{} } @@ -149,6 +154,13 @@ func (m *DatalossCheckRequest) GetVirtualStorage() string { return "" } +func (m *DatalossCheckRequest) GetIncludePartiallyReplicated() bool { + if m != nil { + return m.IncludePartiallyReplicated + } + return false +} + type DatalossCheckResponse struct { // current primary storage Primary string `protobuf:"bytes,1,opt,name=primary,proto3" json:"primary,omitempty"` @@ -202,10 +214,12 @@ type DatalossCheckResponse_Repository struct { // relative path of the repository with outdated replicas RelativePath string `protobuf:"bytes,1,opt,name=relative_path,json=relativePath,proto3" json:"relative_path,omitempty"` // storages on which the repository is outdated - Storages []*DatalossCheckResponse_Repository_Storage `protobuf:"bytes,2,rep,name=storages,proto3" json:"storages,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Storages []*DatalossCheckResponse_Repository_Storage `protobuf:"bytes,2,rep,name=storages,proto3" json:"storages,omitempty"` + // read_only indicates whether the repository is in read-only mode. + ReadOnly bool `protobuf:"varint,3,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *DatalossCheckResponse_Repository) Reset() { *m = DatalossCheckResponse_Repository{} } @@ -247,6 +261,13 @@ func (m *DatalossCheckResponse_Repository) GetStorages() []*DatalossCheckRespons return nil } +func (m *DatalossCheckResponse_Repository) GetReadOnly() bool { + if m != nil { + return m.ReadOnly + } + return false +} + type DatalossCheckResponse_Repository_Storage struct { // name of the storage Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -596,52 +617,55 @@ func init() { func init() { proto.RegisterFile("praefect.proto", fileDescriptor_d32bf44842ead735) } var fileDescriptor_d32bf44842ead735 = []byte{ - // 715 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4d, 0x6e, 0xd3, 0x40, - 0x18, 0x95, 0x9d, 0xd0, 0xba, 0x5f, 0xfa, 0x93, 0x0e, 0x2d, 0x0d, 0x06, 0xda, 0xd4, 0x08, 0x1a, - 0x89, 0x36, 0xa9, 0x52, 0x24, 0x24, 0x76, 0xb4, 0x65, 0x51, 0x54, 0x41, 0xe5, 0x4a, 0x2c, 0xd8, - 0x58, 0x63, 0x67, 0x9a, 0x0c, 0x38, 0x1e, 0x33, 0x33, 0xa9, 0x94, 0x1b, 0x70, 0x03, 0x0e, 0xc0, - 0x8a, 0x05, 0x27, 0x40, 0x6c, 0xb9, 0x01, 0xc7, 0xe0, 0x02, 0xac, 0x90, 0xed, 0xb1, 0xeb, 0x24, - 0x4e, 0x8b, 0xc2, 0xce, 0xf3, 0xfd, 0xbc, 0x6f, 0xde, 0x7b, 0x33, 0x63, 0x58, 0x0e, 0x39, 0x26, - 0x17, 0xc4, 0x93, 0xcd, 0x90, 0x33, 0xc9, 0xd0, 0x5c, 0x97, 0x4a, 0xec, 0x0f, 0x4d, 0xf0, 0x69, - 0xa0, 0x62, 0xe6, 0xa2, 0xe8, 0x61, 0x4e, 0x3a, 0xc9, 0xca, 0xfa, 0xaa, 0xc1, 0xe6, 0x39, 0x91, - 0x2f, 0x06, 0xb2, 0xc7, 0x38, 0x95, 0x58, 0xd2, 0x4b, 0x72, 0x2e, 0x19, 0xc7, 0x5d, 0x62, 0x93, - 0x8f, 0x03, 0x22, 0x24, 0xda, 0x83, 0x95, 0x4b, 0xca, 0xe5, 0x00, 0xfb, 0x8e, 0x48, 0x32, 0x35, - 0xad, 0xae, 0x35, 0x16, 0x0e, 0xcb, 0x9f, 0x7e, 0xee, 0x6a, 0xf6, 0xb2, 0x4a, 0xaa, 0x2e, 0xf4, - 0x10, 0x96, 0x38, 0xf1, 0x63, 0x20, 0x27, 0xc4, 0xb2, 0x57, 0xd3, 0xa3, 0x62, 0x7b, 0x31, 0x0d, - 0x9e, 0x61, 0xd9, 0x43, 0x07, 0xb0, 0x8e, 0xf3, 0x23, 0x33, 0xe4, 0x52, 0x5c, 0xbc, 0x86, 0x0b, - 0xf6, 0x63, 0x6d, 0xc3, 0xd6, 0xd4, 0xad, 0x8a, 0x90, 0x05, 0x82, 0x58, 0x2f, 0x61, 0xed, 0x18, - 0x4b, 0xec, 0x33, 0x21, 0x8e, 0x7a, 0xc4, 0xfb, 0x30, 0x1b, 0x07, 0xeb, 0x87, 0x0e, 0xeb, 0x63, - 0x38, 0xc9, 0x00, 0x54, 0x83, 0xf9, 0x90, 0xd3, 0x3e, 0xe6, 0xc3, 0x04, 0xc0, 0x4e, 0x97, 0xe8, - 0x14, 0x16, 0x39, 0x09, 0x99, 0xa0, 0x92, 0x71, 0x4a, 0x44, 0x4d, 0xaf, 0x97, 0x1a, 0x95, 0x76, - 0xa3, 0x99, 0x58, 0xd0, 0x2c, 0x84, 0x6b, 0xda, 0x69, 0xc7, 0xd0, 0x1e, 0xe9, 0x36, 0xbf, 0x6b, - 0x00, 0x57, 0xc9, 0x49, 0x51, 0xb5, 0x02, 0x51, 0x4f, 0xc1, 0x50, 0xe4, 0xd2, 0xe9, 0xfb, 0xff, - 0x3a, 0xbd, 0x99, 0x0a, 0x99, 0x21, 0x98, 0xcf, 0x61, 0x3e, 0xb5, 0x14, 0x41, 0x39, 0xc0, 0x7d, - 0x25, 0x99, 0x1d, 0x7f, 0xa3, 0x7b, 0xb0, 0xe0, 0x92, 0x1e, 0x0d, 0x3a, 0x8e, 0x3b, 0x8c, 0x2d, - 0x2e, 0xd9, 0x46, 0x12, 0x38, 0x1c, 0x5a, 0x6f, 0xe0, 0x6e, 0x8e, 0x19, 0x09, 0x7d, 0xea, 0x61, - 0x91, 0x7a, 0xd1, 0x06, 0xc8, 0xa8, 0x26, 0x2a, 0x56, 0xda, 0x28, 0xdd, 0x68, 0xae, 0x2d, 0x57, - 0x65, 0x7d, 0xd1, 0xc1, 0x2c, 0x42, 0x54, 0xae, 0xbc, 0x1e, 0x75, 0xa5, 0xd2, 0x7e, 0x5a, 0x80, - 0x37, 0xd6, 0x94, 0x4b, 0x1d, 0x13, 0x89, 0xa9, 0x2f, 0xae, 0xbc, 0x3c, 0x03, 0x83, 0xab, 0x72, - 0xa5, 0xe4, 0x6c, 0x80, 0x19, 0x8a, 0xe9, 0xc1, 0xea, 0x44, 0x7a, 0x16, 0x25, 0x90, 0x09, 0x86, - 0x17, 0x99, 0x28, 0x06, 0x7d, 0x75, 0xb3, 0xb2, 0xb5, 0xf5, 0x4b, 0x83, 0x8d, 0x23, 0x16, 0x08, - 0x2a, 0x24, 0x09, 0xbc, 0xe1, 0x7f, 0xdc, 0x00, 0xf4, 0x08, 0x96, 0x25, 0xe6, 0x5d, 0x22, 0xb3, - 0xea, 0x64, 0xd8, 0x52, 0x12, 0x4d, 0xcb, 0x9e, 0xc0, 0x2a, 0x27, 0x17, 0x84, 0x93, 0xc0, 0x1b, - 0xbf, 0xc3, 0xd5, 0x2c, 0x91, 0x16, 0x3f, 0x83, 0x8d, 0x0e, 0x15, 0xd8, 0xf5, 0x89, 0xc3, 0x89, - 0xc7, 0x02, 0x8f, 0xfa, 0x3e, 0xc5, 0x92, 0xb2, 0xa0, 0x56, 0xae, 0x6b, 0x0d, 0xc3, 0xbe, 0xa3, - 0xd2, 0xf6, 0x68, 0xd6, 0xfa, 0xad, 0x41, 0x6d, 0x92, 0x97, 0xf2, 0x7e, 0x17, 0x50, 0x24, 0x8f, - 0x53, 0x74, 0x3f, 0xaa, 0x51, 0xc6, 0xce, 0xdf, 0x91, 0x1d, 0x58, 0x51, 0xbc, 0xc6, 0x54, 0x54, - 0x74, 0x8f, 0x54, 0x14, 0xed, 0x45, 0xb0, 0x29, 0xb3, 0xac, 0x36, 0xa1, 0x76, 0xc5, 0x39, 0x2b, - 0xdf, 0x84, 0x4a, 0xe4, 0xb5, 0xf3, 0x9e, 0xb9, 0x0e, 0xed, 0xc4, 0x7c, 0xca, 0xf6, 0x42, 0x14, - 0x7a, 0xc5, 0xdc, 0x93, 0x4e, 0xb1, 0x50, 0xb7, 0x8a, 0x85, 0x6a, 0x7f, 0x2b, 0xc1, 0xed, 0x33, - 0xf5, 0x92, 0x9f, 0x04, 0x17, 0xec, 0x9c, 0xf0, 0x4b, 0xea, 0x11, 0x44, 0x00, 0x4d, 0x1e, 0x3f, - 0xb4, 0x7d, 0xdd, 0xd1, 0x8c, 0xcd, 0x37, 0xad, 0x9b, 0x4f, 0xaf, 0x65, 0xfc, 0xf9, 0xdc, 0x28, - 0x1b, 0x7a, 0x55, 0x43, 0x18, 0xaa, 0xe3, 0x6a, 0xa3, 0xad, 0x14, 0x61, 0xca, 0xf9, 0x32, 0xeb, - 0xd3, 0x0b, 0xc6, 0x06, 0xe8, 0xfb, 0x1a, 0x7a, 0x0b, 0x4b, 0x23, 0x4f, 0x12, 0xba, 0x3f, 0xe5, - 0xa5, 0x4a, 0xc0, 0x1f, 0x5c, 0xfb, 0x8e, 0xe5, 0xb6, 0x2e, 0x61, 0x63, 0xca, 0x2f, 0x02, 0x3d, - 0x4e, 0x31, 0xae, 0xff, 0xdd, 0x99, 0x3b, 0x37, 0xd6, 0x8d, 0x4c, 0xd5, 0xaa, 0xfa, 0xe1, 0xfe, - 0xbb, 0xa8, 0xc7, 0xc7, 0x6e, 0xd3, 0x63, 0xfd, 0x56, 0xf2, 0xb9, 0xc7, 0x78, 0xb7, 0x95, 0x20, - 0xb5, 0xe2, 0x5f, 0x6d, 0xab, 0xcb, 0xd4, 0x3a, 0x74, 0xdd, 0xb9, 0x38, 0x74, 0xf0, 0x37, 0x00, - 0x00, 0xff, 0xff, 0xb0, 0xb3, 0x43, 0x09, 0xb1, 0x07, 0x00, 0x00, + // 765 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0xcd, 0x6e, 0xd3, 0x4c, + 0x14, 0x95, 0x93, 0x7c, 0xad, 0x7b, 0xd3, 0x9f, 0x74, 0xbe, 0x96, 0x06, 0x53, 0xfa, 0x63, 0x04, + 0x8d, 0x44, 0x9b, 0x54, 0x29, 0x12, 0x12, 0x2b, 0x68, 0xbb, 0x29, 0xaa, 0x68, 0xe4, 0x4a, 0x2c, + 0xd8, 0x58, 0x63, 0x7b, 0x9a, 0x0c, 0x4c, 0x3c, 0x66, 0x3c, 0xa9, 0xe4, 0x27, 0x80, 0x37, 0xe0, + 0x01, 0x58, 0xb1, 0xe0, 0x35, 0x78, 0x03, 0x24, 0xc4, 0x3b, 0xf0, 0x02, 0xac, 0x90, 0xed, 0xb1, + 0x9b, 0x1f, 0xa7, 0x45, 0x65, 0x67, 0xdf, 0x7b, 0xee, 0x99, 0xb9, 0xe7, 0xdc, 0x99, 0x81, 0xc5, + 0x40, 0x60, 0x72, 0x41, 0x5c, 0xd9, 0x0c, 0x04, 0x97, 0x1c, 0xcd, 0x74, 0xa9, 0xc4, 0x2c, 0x32, + 0x80, 0x51, 0x5f, 0xc5, 0x8c, 0xf9, 0xb0, 0x87, 0x05, 0xf1, 0xd2, 0x3f, 0xf3, 0x8b, 0x06, 0x1b, + 0xe7, 0x44, 0xbe, 0x18, 0xc8, 0x1e, 0x17, 0x54, 0x62, 0x49, 0x2f, 0xc9, 0xb9, 0xe4, 0x02, 0x77, + 0x89, 0x45, 0xde, 0x0f, 0x48, 0x28, 0xd1, 0x1e, 0x2c, 0x5d, 0x52, 0x21, 0x07, 0x98, 0xd9, 0x61, + 0x9a, 0xa9, 0x6b, 0x5b, 0x5a, 0x63, 0xee, 0xb0, 0xf2, 0xf1, 0xdb, 0xae, 0x66, 0x2d, 0xaa, 0xa4, + 0xaa, 0x42, 0x0f, 0x60, 0x41, 0x10, 0x96, 0x10, 0xd9, 0x01, 0x96, 0xbd, 0x7a, 0x29, 0x06, 0x5b, + 0xf3, 0x59, 0xb0, 0x83, 0x65, 0x0f, 0x1d, 0xc0, 0x2a, 0x1e, 0x5e, 0x32, 0x67, 0x2e, 0x27, 0xe0, + 0x15, 0x5c, 0xb0, 0x1f, 0x73, 0x1b, 0x36, 0xa7, 0x6e, 0x35, 0x0c, 0xb8, 0x1f, 0x12, 0xf3, 0x83, + 0x06, 0x2b, 0xc7, 0x58, 0x62, 0xc6, 0xc3, 0xf0, 0xa8, 0x47, 0xdc, 0x77, 0xb7, 0x6c, 0xe2, 0x39, + 0xac, 0x53, 0xdf, 0x65, 0x03, 0x2f, 0xee, 0x41, 0x48, 0x8a, 0x19, 0x8b, 0x6c, 0x41, 0x02, 0x46, + 0x5d, 0x2c, 0x89, 0x97, 0xf4, 0xa4, 0x5b, 0x86, 0xc2, 0x74, 0x32, 0x88, 0x95, 0x23, 0xcc, 0x9f, + 0x25, 0x58, 0x1d, 0xdb, 0x49, 0xba, 0x47, 0x54, 0x87, 0xd9, 0x40, 0xd0, 0x3e, 0x16, 0x51, 0xba, + 0x05, 0x2b, 0xfb, 0x45, 0xa7, 0x30, 0x2f, 0x48, 0xc0, 0x43, 0x2a, 0xb9, 0xa0, 0x24, 0xac, 0x97, + 0xb6, 0xca, 0x8d, 0x6a, 0xbb, 0xd1, 0x4c, 0x5d, 0x6c, 0x16, 0xd2, 0x35, 0xad, 0xac, 0x22, 0xb2, + 0x46, 0xaa, 0x8d, 0x1f, 0x1a, 0xc0, 0x55, 0x72, 0xd2, 0x17, 0xad, 0xc0, 0x97, 0x53, 0xd0, 0x95, + 0x3c, 0xd9, 0xea, 0xfb, 0x7f, 0xbb, 0x7a, 0x33, 0xf3, 0x22, 0x67, 0x40, 0xf7, 0x60, 0x4e, 0x10, + 0xec, 0xd9, 0xdc, 0x67, 0x51, 0xe2, 0xac, 0x6e, 0xe9, 0x71, 0xe0, 0xcc, 0x67, 0x91, 0xf1, 0x0c, + 0x66, 0x33, 0xb5, 0x11, 0x54, 0x7c, 0xdc, 0x57, 0x8e, 0x58, 0xc9, 0x77, 0x5c, 0xeb, 0x90, 0x1e, + 0xf5, 0x3d, 0xdb, 0x89, 0x12, 0xb9, 0xcb, 0x96, 0x9e, 0x06, 0x0e, 0x23, 0xf3, 0x0c, 0xee, 0x0e, + 0xb5, 0x9d, 0x8a, 0x1e, 0x66, 0x56, 0xb7, 0x01, 0x72, 0x1d, 0x52, 0x89, 0xab, 0x6d, 0x94, 0x75, + 0x31, 0x54, 0x36, 0x84, 0x32, 0x3f, 0x97, 0xc0, 0x28, 0x62, 0x54, 0x96, 0xbd, 0x1a, 0xb5, 0xac, + 0xda, 0x7e, 0x52, 0xc0, 0x37, 0x56, 0x34, 0x94, 0x3a, 0x26, 0x12, 0x53, 0x16, 0x5e, 0x19, 0xdd, + 0x01, 0x5d, 0x0d, 0x53, 0x26, 0xf3, 0xed, 0x08, 0x73, 0x16, 0xc3, 0x85, 0xe5, 0x89, 0xf4, 0x6d, + 0x94, 0x40, 0x06, 0xe8, 0x6e, 0xec, 0x70, 0x38, 0xe8, 0xab, 0x93, 0x9b, 0xff, 0x9b, 0xdf, 0x35, + 0x58, 0x3b, 0xe2, 0x7e, 0x48, 0x43, 0x49, 0x7c, 0x37, 0xfa, 0x97, 0x03, 0xf6, 0x10, 0x16, 0x25, + 0x16, 0x5d, 0x22, 0x73, 0x74, 0xba, 0xd8, 0x42, 0x1a, 0xcd, 0x60, 0x8f, 0x61, 0x59, 0x90, 0x0b, + 0x22, 0x88, 0xef, 0x8e, 0xdf, 0x11, 0xb5, 0x3c, 0x91, 0x81, 0x9f, 0xc2, 0x9a, 0x47, 0x43, 0xec, + 0x30, 0x62, 0x0b, 0xe2, 0x72, 0xdf, 0xa5, 0x8c, 0x51, 0x2c, 0x29, 0xf7, 0xeb, 0x95, 0x64, 0xf8, + 0xee, 0xa8, 0xb4, 0x35, 0x9a, 0x35, 0x7f, 0x69, 0x50, 0x9f, 0xec, 0x4b, 0x79, 0xbf, 0x0b, 0x28, + 0x96, 0xc7, 0x2e, 0x3a, 0x3c, 0xb5, 0x38, 0x63, 0x0d, 0x1f, 0xa0, 0x1d, 0x58, 0x52, 0x7d, 0x8d, + 0xa9, 0xa8, 0xda, 0x3d, 0x52, 0x51, 0xb4, 0x17, 0xd3, 0x66, 0x9d, 0xe5, 0xd8, 0xb4, 0xb5, 0xab, + 0x9e, 0x73, 0xf8, 0x06, 0x54, 0x63, 0xaf, 0xed, 0xb7, 0xdc, 0xb1, 0xa9, 0x97, 0xf4, 0x53, 0xb1, + 0xe6, 0xe2, 0xd0, 0x4b, 0xee, 0x9c, 0x78, 0xc5, 0x42, 0xfd, 0x57, 0x2c, 0x54, 0xfb, 0x6b, 0x19, + 0xfe, 0xef, 0xa8, 0x97, 0xe2, 0xc4, 0xbf, 0xe0, 0xe7, 0x44, 0x5c, 0x52, 0x97, 0x20, 0x02, 0x68, + 0x72, 0xfc, 0xd0, 0xf6, 0x75, 0xa3, 0x99, 0x98, 0x6f, 0x98, 0x37, 0x4f, 0xaf, 0xa9, 0xff, 0xfe, + 0xd4, 0xa8, 0xe8, 0xa5, 0x9a, 0x86, 0x30, 0xd4, 0xc6, 0xd5, 0x46, 0x9b, 0x19, 0xc3, 0x94, 0xf9, + 0x32, 0xb6, 0xa6, 0x03, 0xc6, 0x16, 0x28, 0xed, 0x6b, 0xe8, 0x35, 0x2c, 0x8c, 0xdc, 0x57, 0x68, + 0x7d, 0xca, 0x35, 0x96, 0x92, 0xdf, 0xbf, 0xf6, 0x92, 0x1b, 0xda, 0xba, 0x84, 0xb5, 0x29, 0x4f, + 0x10, 0x7a, 0x94, 0x71, 0x5c, 0xff, 0x9c, 0x1a, 0x3b, 0x37, 0xe2, 0x46, 0x56, 0xd5, 0x6a, 0xa5, + 0xc3, 0xfd, 0x37, 0x71, 0x0d, 0xc3, 0x4e, 0xd3, 0xe5, 0xfd, 0x56, 0xfa, 0xb9, 0xc7, 0x45, 0xb7, + 0x95, 0x32, 0xb5, 0x92, 0xa7, 0xbc, 0xd5, 0xe5, 0xea, 0x3f, 0x70, 0x9c, 0x99, 0x24, 0x74, 0xf0, + 0x27, 0x00, 0x00, 0xff, 0xff, 0x95, 0xbb, 0xed, 0x49, 0x11, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -662,8 +686,7 @@ type PraefectInfoServiceClient interface { // back indicating which repos are consistent with the primary and which ones // need repair. ConsistencyCheck(ctx context.Context, in *ConsistencyCheckRequest, opts ...grpc.CallOption) (PraefectInfoService_ConsistencyCheckClient, error) - // DatalossCheck checks for nodes which are not up to date with the previous writable primary. - // This indicates possible data loss after a failover event. + // DatalossCheck checks for outdated repository replicas. DatalossCheck(ctx context.Context, in *DatalossCheckRequest, opts ...grpc.CallOption) (*DatalossCheckResponse, error) // SetAuthoritativeStorage sets the authoritative storage for a repository on a given virtual storage. // This causes the current version of the repository on the authoritative storage to be considered the @@ -746,8 +769,7 @@ type PraefectInfoServiceServer interface { // back indicating which repos are consistent with the primary and which ones // need repair. ConsistencyCheck(*ConsistencyCheckRequest, PraefectInfoService_ConsistencyCheckServer) error - // DatalossCheck checks for nodes which are not up to date with the previous writable primary. - // This indicates possible data loss after a failover event. + // DatalossCheck checks for outdated repository replicas. DatalossCheck(context.Context, *DatalossCheckRequest) (*DatalossCheckResponse, error) // SetAuthoritativeStorage sets the authoritative storage for a repository on a given virtual storage. // This causes the current version of the repository on the authoritative storage to be considered the diff --git a/proto/praefect.proto b/proto/praefect.proto index aaad1570f..18db7f6f9 100644 --- a/proto/praefect.proto +++ b/proto/praefect.proto @@ -25,8 +25,7 @@ service PraefectInfoService { }; } - // DatalossCheck checks for nodes which are not up to date with the previous writable primary. - // This indicates possible data loss after a failover event. + // DatalossCheck checks for outdated repository replicas. rpc DatalossCheck(DatalossCheckRequest) returns (DatalossCheckResponse) { option (op_type) = { op: ACCESSOR @@ -55,6 +54,11 @@ message SetAuthoritativeStorageResponse {} message DatalossCheckRequest { string virtual_storage = 1 [(storage)=true]; + // include_partially_replicated decides whether to include repositories which are fully up to date + // on the primary but are outdated on some secondaries. Such repositories are still writable and do + // not suffer from data loss. The data on the primary is not fully replicated which increases the + // chances of data loss following a failover. + bool include_partially_replicated = 2; } message DatalossCheckResponse { @@ -70,6 +74,8 @@ message DatalossCheckResponse { string relative_path = 1; // storages on which the repository is outdated repeated Storage storages = 2; + // read_only indicates whether the repository is in read-only mode. + bool read_only = 3; } // current primary storage diff --git a/ruby/proto/gitaly/praefect_pb.rb b/ruby/proto/gitaly/praefect_pb.rb index 2900a3368..b0bda2392 100644 --- a/ruby/proto/gitaly/praefect_pb.rb +++ b/ruby/proto/gitaly/praefect_pb.rb @@ -16,6 +16,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do end add_message "gitaly.DatalossCheckRequest" do optional :virtual_storage, :string, 1 + optional :include_partially_replicated, :bool, 2 end add_message "gitaly.DatalossCheckResponse" do optional :primary, :string, 1 @@ -24,6 +25,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do add_message "gitaly.DatalossCheckResponse.Repository" do optional :relative_path, :string, 1 repeated :storages, :message, 2, "gitaly.DatalossCheckResponse.Repository.Storage" + optional :read_only, :bool, 3 end add_message "gitaly.DatalossCheckResponse.Repository.Storage" do optional :name, :string, 1 diff --git a/ruby/proto/gitaly/praefect_services_pb.rb b/ruby/proto/gitaly/praefect_services_pb.rb index 55a931953..5d1e4ae70 100644 --- a/ruby/proto/gitaly/praefect_services_pb.rb +++ b/ruby/proto/gitaly/praefect_services_pb.rb @@ -20,8 +20,7 @@ module Gitaly # back indicating which repos are consistent with the primary and which ones # need repair. rpc :ConsistencyCheck, Gitaly::ConsistencyCheckRequest, stream(Gitaly::ConsistencyCheckResponse) - # DatalossCheck checks for nodes which are not up to date with the previous writable primary. - # This indicates possible data loss after a failover event. + # DatalossCheck checks for outdated repository replicas. rpc :DatalossCheck, Gitaly::DatalossCheckRequest, Gitaly::DatalossCheckResponse # SetAuthoritativeStorage sets the authoritative storage for a repository on a given virtual storage. # This causes the current version of the repository on the authoritative storage to be considered the |