diff --git a/.wordlist.txt b/.wordlist.txt index a06dba04..19c689e3 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -138,15 +138,18 @@ lifecycle lifecycle lsn md +pg pluggable pluginName postgres +prefetching proto reconciler reconcilers reconcilers requeue requeue +rewind rfc rfc rpc diff --git a/docs/protocol.md b/docs/protocol.md index bdf143b7..3bc28f2c 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -141,6 +141,7 @@ - [WALStatusResult.AdditionalInformationEntry](#cnpgi-wal-v1-WALStatusResult-AdditionalInformationEntry) - [WALCapability.RPC.Type](#cnpgi-wal-v1-WALCapability-RPC-Type) + - [WALRestoreRequest.Mode](#cnpgi-wal-v1-WALRestoreRequest-Mode) - [WAL](#cnpgi-wal-v1-WAL) @@ -1703,6 +1704,7 @@ Intentionally empty. | source_wal_name | [string](#string) | | This field is REQUIRED. Value of this field is the name of the WAL to be retrieved from the archive, such as: 000000010000000100000012 | | destination_file_name | [string](#string) | | This field is REQUIRED. Value of this field is the full path where the WAL file should be stored | | parameters | [WALRestoreRequest.ParametersEntry](#cnpgi-wal-v1-WALRestoreRequest-ParametersEntry) | repeated | This field is OPTIONAL. Values are opaque. | +| mode | [WALRestoreRequest.Mode](#cnpgi-wal-v1-WALRestoreRequest-Mode) | | This field is OPTIONAL. Value of this field is the context the WAL file is being restored in | @@ -1799,6 +1801,19 @@ Intentionally empty. | TYPE_SET_FIRST_REQUIRED | 4 | TYPE_SET_FIRST_REQUIRED indicates that the Plugin is able to reply to the SetFirstRequired RPC request | + + + +### WALRestoreRequest.Mode + + +| Name | Number | Description | +| ---- | ------ | ----------- | +| MODE_UNSPECIFIED | 0 | MODE_UNSPECIFIED must be interpreted as MODE_RECOVERY: it is what an operator predating this field sends | +| MODE_RECOVERY | 1 | MODE_RECOVERY indicates that the WAL file is being restored by the restore_command of an instance in recovery | +| MODE_REWIND | 2 | MODE_REWIND indicates that the WAL file is being restored on behalf of pg_rewind. pg_rewind fetches every WAL file it needs exactly once, walking the timeline backwards, and treats any restore failure as fatal: the plugin should retrieve exactly the requested file, without WAL prefetching and without caching archive misses observed on nearby WAL files | + + diff --git a/pkg/wal/wal.pb.go b/pkg/wal/wal.pb.go index 430cdd55..05ebceee 100644 --- a/pkg/wal/wal.pb.go +++ b/pkg/wal/wal.pb.go @@ -40,6 +40,65 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type WALRestoreRequest_Mode int32 + +const ( + // MODE_UNSPECIFIED must be interpreted as MODE_RECOVERY: it is + // what an operator predating this field sends + WALRestoreRequest_MODE_UNSPECIFIED WALRestoreRequest_Mode = 0 + // MODE_RECOVERY indicates that the WAL file is being restored + // by the restore_command of an instance in recovery + WALRestoreRequest_MODE_RECOVERY WALRestoreRequest_Mode = 1 + // MODE_REWIND indicates that the WAL file is being restored on + // behalf of pg_rewind. pg_rewind fetches every WAL file it needs + // exactly once, walking the timeline backwards, and treats any + // restore failure as fatal: the plugin should retrieve exactly the + // requested file, without WAL prefetching and without caching + // archive misses observed on nearby WAL files + WALRestoreRequest_MODE_REWIND WALRestoreRequest_Mode = 2 +) + +// Enum value maps for WALRestoreRequest_Mode. +var ( + WALRestoreRequest_Mode_name = map[int32]string{ + 0: "MODE_UNSPECIFIED", + 1: "MODE_RECOVERY", + 2: "MODE_REWIND", + } + WALRestoreRequest_Mode_value = map[string]int32{ + "MODE_UNSPECIFIED": 0, + "MODE_RECOVERY": 1, + "MODE_REWIND": 2, + } +) + +func (x WALRestoreRequest_Mode) Enum() *WALRestoreRequest_Mode { + p := new(WALRestoreRequest_Mode) + *p = x + return p +} + +func (x WALRestoreRequest_Mode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (WALRestoreRequest_Mode) Descriptor() protoreflect.EnumDescriptor { + return file_proto_wal_proto_enumTypes[0].Descriptor() +} + +func (WALRestoreRequest_Mode) Type() protoreflect.EnumType { + return &file_proto_wal_proto_enumTypes[0] +} + +func (x WALRestoreRequest_Mode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use WALRestoreRequest_Mode.Descriptor instead. +func (WALRestoreRequest_Mode) EnumDescriptor() ([]byte, []int) { + return file_proto_wal_proto_rawDescGZIP(), []int{2, 0} +} + type WALCapability_RPC_Type int32 const ( @@ -87,11 +146,11 @@ func (x WALCapability_RPC_Type) String() string { } func (WALCapability_RPC_Type) Descriptor() protoreflect.EnumDescriptor { - return file_proto_wal_proto_enumTypes[0].Descriptor() + return file_proto_wal_proto_enumTypes[1].Descriptor() } func (WALCapability_RPC_Type) Type() protoreflect.EnumType { - return &file_proto_wal_proto_enumTypes[0] + return &file_proto_wal_proto_enumTypes[1] } func (x WALCapability_RPC_Type) Number() protoreflect.EnumNumber { @@ -217,7 +276,10 @@ type WALRestoreRequest struct { // where the WAL file should be stored DestinationFileName string `protobuf:"bytes,3,opt,name=destination_file_name,json=destinationFileName,proto3" json:"destination_file_name,omitempty"` // This field is OPTIONAL. Values are opaque. - Parameters map[string]string `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Parameters map[string]string `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // This field is OPTIONAL. Value of this field is the context the + // WAL file is being restored in + Mode WALRestoreRequest_Mode `protobuf:"varint,5,opt,name=mode,proto3,enum=cnpgi.wal.v1.WALRestoreRequest_Mode" json:"mode,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -280,6 +342,13 @@ func (x *WALRestoreRequest) GetParameters() map[string]string { return nil } +func (x *WALRestoreRequest) GetMode() WALRestoreRequest_Mode { + if x != nil { + return x.Mode + } + return WALRestoreRequest_MODE_UNSPECIFIED +} + type WALRestoreResult struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -728,17 +797,22 @@ const file_proto_wal_proto_rawDesc = "" + "\x0fParametersEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x12\n" + - "\x10WALArchiveResult\"\xae\x02\n" + + "\x10WALArchiveResult\"\xaa\x03\n" + "\x11WALRestoreRequest\x12-\n" + "\x12cluster_definition\x18\x01 \x01(\fR\x11clusterDefinition\x12&\n" + "\x0fsource_wal_name\x18\x02 \x01(\tR\rsourceWalName\x122\n" + "\x15destination_file_name\x18\x03 \x01(\tR\x13destinationFileName\x12O\n" + "\n" + "parameters\x18\x04 \x03(\v2/.cnpgi.wal.v1.WALRestoreRequest.ParametersEntryR\n" + - "parameters\x1a=\n" + + "parameters\x128\n" + + "\x04mode\x18\x05 \x01(\x0e2$.cnpgi.wal.v1.WALRestoreRequest.ModeR\x04mode\x1a=\n" + "\x0fParametersEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x12\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"@\n" + + "\x04Mode\x12\x14\n" + + "\x10MODE_UNSPECIFIED\x10\x00\x12\x11\n" + + "\rMODE_RECOVERY\x10\x01\x12\x0f\n" + + "\vMODE_REWIND\x10\x02\"\x12\n" + "\x10WALRestoreResult\"A\n" + "\x10WALStatusRequest\x12-\n" + "\x12cluster_definition\x18\x01 \x01(\fR\x11clusterDefinition\"\x84\x02\n" + @@ -786,48 +860,50 @@ func file_proto_wal_proto_rawDescGZIP() []byte { return file_proto_wal_proto_rawDescData } -var file_proto_wal_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_wal_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_proto_wal_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_proto_wal_proto_goTypes = []any{ - (WALCapability_RPC_Type)(0), // 0: cnpgi.wal.v1.WALCapability.RPC.Type - (*WALArchiveRequest)(nil), // 1: cnpgi.wal.v1.WALArchiveRequest - (*WALArchiveResult)(nil), // 2: cnpgi.wal.v1.WALArchiveResult - (*WALRestoreRequest)(nil), // 3: cnpgi.wal.v1.WALRestoreRequest - (*WALRestoreResult)(nil), // 4: cnpgi.wal.v1.WALRestoreResult - (*WALStatusRequest)(nil), // 5: cnpgi.wal.v1.WALStatusRequest - (*WALStatusResult)(nil), // 6: cnpgi.wal.v1.WALStatusResult - (*SetFirstRequiredRequest)(nil), // 7: cnpgi.wal.v1.SetFirstRequiredRequest - (*SetFirstRequiredResult)(nil), // 8: cnpgi.wal.v1.SetFirstRequiredResult - (*WALCapabilitiesRequest)(nil), // 9: cnpgi.wal.v1.WALCapabilitiesRequest - (*WALCapabilitiesResult)(nil), // 10: cnpgi.wal.v1.WALCapabilitiesResult - (*WALCapability)(nil), // 11: cnpgi.wal.v1.WALCapability - nil, // 12: cnpgi.wal.v1.WALArchiveRequest.ParametersEntry - nil, // 13: cnpgi.wal.v1.WALRestoreRequest.ParametersEntry - nil, // 14: cnpgi.wal.v1.WALStatusResult.AdditionalInformationEntry - (*WALCapability_RPC)(nil), // 15: cnpgi.wal.v1.WALCapability.RPC + (WALRestoreRequest_Mode)(0), // 0: cnpgi.wal.v1.WALRestoreRequest.Mode + (WALCapability_RPC_Type)(0), // 1: cnpgi.wal.v1.WALCapability.RPC.Type + (*WALArchiveRequest)(nil), // 2: cnpgi.wal.v1.WALArchiveRequest + (*WALArchiveResult)(nil), // 3: cnpgi.wal.v1.WALArchiveResult + (*WALRestoreRequest)(nil), // 4: cnpgi.wal.v1.WALRestoreRequest + (*WALRestoreResult)(nil), // 5: cnpgi.wal.v1.WALRestoreResult + (*WALStatusRequest)(nil), // 6: cnpgi.wal.v1.WALStatusRequest + (*WALStatusResult)(nil), // 7: cnpgi.wal.v1.WALStatusResult + (*SetFirstRequiredRequest)(nil), // 8: cnpgi.wal.v1.SetFirstRequiredRequest + (*SetFirstRequiredResult)(nil), // 9: cnpgi.wal.v1.SetFirstRequiredResult + (*WALCapabilitiesRequest)(nil), // 10: cnpgi.wal.v1.WALCapabilitiesRequest + (*WALCapabilitiesResult)(nil), // 11: cnpgi.wal.v1.WALCapabilitiesResult + (*WALCapability)(nil), // 12: cnpgi.wal.v1.WALCapability + nil, // 13: cnpgi.wal.v1.WALArchiveRequest.ParametersEntry + nil, // 14: cnpgi.wal.v1.WALRestoreRequest.ParametersEntry + nil, // 15: cnpgi.wal.v1.WALStatusResult.AdditionalInformationEntry + (*WALCapability_RPC)(nil), // 16: cnpgi.wal.v1.WALCapability.RPC } var file_proto_wal_proto_depIdxs = []int32{ - 12, // 0: cnpgi.wal.v1.WALArchiveRequest.parameters:type_name -> cnpgi.wal.v1.WALArchiveRequest.ParametersEntry - 13, // 1: cnpgi.wal.v1.WALRestoreRequest.parameters:type_name -> cnpgi.wal.v1.WALRestoreRequest.ParametersEntry - 14, // 2: cnpgi.wal.v1.WALStatusResult.additional_information:type_name -> cnpgi.wal.v1.WALStatusResult.AdditionalInformationEntry - 11, // 3: cnpgi.wal.v1.WALCapabilitiesResult.capabilities:type_name -> cnpgi.wal.v1.WALCapability - 15, // 4: cnpgi.wal.v1.WALCapability.rpc:type_name -> cnpgi.wal.v1.WALCapability.RPC - 0, // 5: cnpgi.wal.v1.WALCapability.RPC.type:type_name -> cnpgi.wal.v1.WALCapability.RPC.Type - 9, // 6: cnpgi.wal.v1.WAL.GetCapabilities:input_type -> cnpgi.wal.v1.WALCapabilitiesRequest - 1, // 7: cnpgi.wal.v1.WAL.Archive:input_type -> cnpgi.wal.v1.WALArchiveRequest - 3, // 8: cnpgi.wal.v1.WAL.Restore:input_type -> cnpgi.wal.v1.WALRestoreRequest - 5, // 9: cnpgi.wal.v1.WAL.Status:input_type -> cnpgi.wal.v1.WALStatusRequest - 7, // 10: cnpgi.wal.v1.WAL.SetFirstRequired:input_type -> cnpgi.wal.v1.SetFirstRequiredRequest - 10, // 11: cnpgi.wal.v1.WAL.GetCapabilities:output_type -> cnpgi.wal.v1.WALCapabilitiesResult - 2, // 12: cnpgi.wal.v1.WAL.Archive:output_type -> cnpgi.wal.v1.WALArchiveResult - 4, // 13: cnpgi.wal.v1.WAL.Restore:output_type -> cnpgi.wal.v1.WALRestoreResult - 6, // 14: cnpgi.wal.v1.WAL.Status:output_type -> cnpgi.wal.v1.WALStatusResult - 8, // 15: cnpgi.wal.v1.WAL.SetFirstRequired:output_type -> cnpgi.wal.v1.SetFirstRequiredResult - 11, // [11:16] is the sub-list for method output_type - 6, // [6:11] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 13, // 0: cnpgi.wal.v1.WALArchiveRequest.parameters:type_name -> cnpgi.wal.v1.WALArchiveRequest.ParametersEntry + 14, // 1: cnpgi.wal.v1.WALRestoreRequest.parameters:type_name -> cnpgi.wal.v1.WALRestoreRequest.ParametersEntry + 0, // 2: cnpgi.wal.v1.WALRestoreRequest.mode:type_name -> cnpgi.wal.v1.WALRestoreRequest.Mode + 15, // 3: cnpgi.wal.v1.WALStatusResult.additional_information:type_name -> cnpgi.wal.v1.WALStatusResult.AdditionalInformationEntry + 12, // 4: cnpgi.wal.v1.WALCapabilitiesResult.capabilities:type_name -> cnpgi.wal.v1.WALCapability + 16, // 5: cnpgi.wal.v1.WALCapability.rpc:type_name -> cnpgi.wal.v1.WALCapability.RPC + 1, // 6: cnpgi.wal.v1.WALCapability.RPC.type:type_name -> cnpgi.wal.v1.WALCapability.RPC.Type + 10, // 7: cnpgi.wal.v1.WAL.GetCapabilities:input_type -> cnpgi.wal.v1.WALCapabilitiesRequest + 2, // 8: cnpgi.wal.v1.WAL.Archive:input_type -> cnpgi.wal.v1.WALArchiveRequest + 4, // 9: cnpgi.wal.v1.WAL.Restore:input_type -> cnpgi.wal.v1.WALRestoreRequest + 6, // 10: cnpgi.wal.v1.WAL.Status:input_type -> cnpgi.wal.v1.WALStatusRequest + 8, // 11: cnpgi.wal.v1.WAL.SetFirstRequired:input_type -> cnpgi.wal.v1.SetFirstRequiredRequest + 11, // 12: cnpgi.wal.v1.WAL.GetCapabilities:output_type -> cnpgi.wal.v1.WALCapabilitiesResult + 3, // 13: cnpgi.wal.v1.WAL.Archive:output_type -> cnpgi.wal.v1.WALArchiveResult + 5, // 14: cnpgi.wal.v1.WAL.Restore:output_type -> cnpgi.wal.v1.WALRestoreResult + 7, // 15: cnpgi.wal.v1.WAL.Status:output_type -> cnpgi.wal.v1.WALStatusResult + 9, // 16: cnpgi.wal.v1.WAL.SetFirstRequired:output_type -> cnpgi.wal.v1.SetFirstRequiredResult + 12, // [12:17] is the sub-list for method output_type + 7, // [7:12] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_proto_wal_proto_init() } @@ -843,7 +919,7 @@ func file_proto_wal_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wal_proto_rawDesc), len(file_proto_wal_proto_rawDesc)), - NumEnums: 1, + NumEnums: 2, NumMessages: 15, NumExtensions: 0, NumServices: 1, diff --git a/proto/wal.proto b/proto/wal.proto index f9e79a1f..2a219864 100644 --- a/proto/wal.proto +++ b/proto/wal.proto @@ -55,6 +55,24 @@ message WALArchiveResult { } message WALRestoreRequest { + enum Mode { + // MODE_UNSPECIFIED must be interpreted as MODE_RECOVERY: it is + // what an operator predating this field sends + MODE_UNSPECIFIED = 0; + + // MODE_RECOVERY indicates that the WAL file is being restored + // by the restore_command of an instance in recovery + MODE_RECOVERY = 1; + + // MODE_REWIND indicates that the WAL file is being restored on + // behalf of pg_rewind. pg_rewind fetches every WAL file it needs + // exactly once, walking the timeline backwards, and treats any + // restore failure as fatal: the plugin should retrieve exactly the + // requested file, without WAL prefetching and without caching + // archive misses observed on nearby WAL files + MODE_REWIND = 2; + } + // This field is REQUIRED. Value of this field is the JSON // serialization of the Cluster corresponding to the Pod being applied bytes cluster_definition = 1; @@ -70,6 +88,10 @@ message WALRestoreRequest { // This field is OPTIONAL. Values are opaque. map parameters = 4; + + // This field is OPTIONAL. Value of this field is the context the + // WAL file is being restored in + Mode mode = 5; } message WALRestoreResult {