Skip to content

Commit db47b48

Browse files
craig[bot]pav-kv
andcommitted
Merge #149657
149657: kvstorage: introduce WAG encoding r=arulajmani a=pav-kv Introduce encoding for WAG. It consists of nodes encompassing replica lifecycle events, and encodes the corresponding state machine engine mutations. Once stored in the raft engine, a WAG node signifies a completed cross-engine write. The ensemble of `RangeID`, `ReplicaID` and log index is used to define the replica's applied state. The same coordinate system is used by WAG, which allows for an easy "has the WAG node been applied?" check. Part of #149604 Co-authored-by: Pavel Kalinnikov <[email protected]>
2 parents 8765705 + 5af2831 commit db47b48

File tree

5 files changed

+160
-0
lines changed

5 files changed

+160
-0
lines changed

pkg/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,7 @@ GO_TARGETS = [
15401540
"//pkg/kv/kvserver/kvserverpb:kvserverpb",
15411541
"//pkg/kv/kvserver/kvstorage/snaprecv:snaprecv",
15421542
"//pkg/kv/kvserver/kvstorage/snaprecv:snaprecv_test",
1543+
"//pkg/kv/kvserver/kvstorage/wag/wagpb:wagpb",
15431544
"//pkg/kv/kvserver/kvstorage:kvstorage",
15441545
"//pkg/kv/kvserver/kvstorage:kvstorage_test",
15451546
"//pkg/kv/kvserver/leases:leases",

pkg/gen/protobuf.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ PROTOBUF_SRCS = [
3333
"//pkg/kv/kvserver/kvflowcontrol/kvflowcontrolpb:kvflowcontrolpb_go_proto",
3434
"//pkg/kv/kvserver/kvflowcontrol/kvflowinspectpb:kvflowinspectpb_go_proto",
3535
"//pkg/kv/kvserver/kvserverpb:kvserverpb_go_proto",
36+
"//pkg/kv/kvserver/kvstorage/wag/wagpb:wagpb_go_proto",
3637
"//pkg/kv/kvserver/liveness/livenesspb:livenesspb_go_proto",
3738
"//pkg/kv/kvserver/loqrecovery/loqrecoverypb:loqrecoverypb_go_proto",
3839
"//pkg/kv/kvserver/protectedts/ptpb:ptpb_go_proto",
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
load("@rules_proto//proto:defs.bzl", "proto_library")
2+
load("@io_bazel_rules_go//go:def.bzl", "go_library")
3+
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
4+
5+
proto_library(
6+
name = "wagpb_proto",
7+
srcs = ["wag.proto"],
8+
strip_import_prefix = "/pkg",
9+
visibility = ["//visibility:public"],
10+
deps = [
11+
"//pkg/kv/kvserver/kvserverpb:kvserverpb_proto",
12+
"//pkg/roachpb:roachpb_proto",
13+
"@com_github_gogo_protobuf//gogoproto:gogo_proto",
14+
],
15+
)
16+
17+
go_proto_library(
18+
name = "wagpb_go_proto",
19+
compilers = ["//pkg/cmd/protoc-gen-gogoroach:protoc-gen-gogoroach_compiler"],
20+
importpath = "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvstorage/wag/wagpb",
21+
proto = ":wagpb_proto",
22+
visibility = ["//visibility:public"],
23+
deps = [
24+
"//pkg/kv/kvserver/kvserverpb",
25+
"//pkg/roachpb",
26+
"@com_github_gogo_protobuf//gogoproto",
27+
],
28+
)
29+
30+
go_library(
31+
name = "wagpb",
32+
srcs = ["wag.go"],
33+
embed = [":wagpb_go_proto"],
34+
importpath = "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvstorage/wag/wagpb",
35+
visibility = ["//visibility:public"],
36+
deps = ["//pkg/kv/kvpb"],
37+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package wagpb
7+
8+
// TODO(pav-kv): remove this once the dev gen bazel picks up this dependency
9+
// from the .pb.go file.
10+
import _ "github.com/cockroachdb/cockroach/pkg/kv/kvpb"
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
syntax = "proto3";
7+
package wagpb;
8+
option go_package = "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvstorage/wag/wagpb";
9+
10+
import "gogoproto/gogo.proto";
11+
import "kv/kvserver/kvserverpb/raft.proto";
12+
import "roachpb/data.proto";
13+
14+
// NodeType defines the type of the WAG node. It corresponds to a replica
15+
// lifecycle event, and specifies how the node is addressed and interpreted.
16+
enum NodeType {
17+
// NodeEmpty is the "empty" type. Can be used as a nil/no-op indicator. We
18+
// just have it so that all "real" types are specified explicitly.
19+
NodeEmpty = 0;
20+
// NodeCreate corresponds to a creation of an uninitialized replica. All
21+
// replicas on a Store go through this transition.
22+
NodeCreate = 1;
23+
// NodeSnap corresponds to initializing/resetting a replica state machine with
24+
// a snapshot. Happens when an uninitialized replica is initialized, or when
25+
// an initialized replica is caught up on a later applied state. A NodeSnap
26+
// also subsumes replicas (if any) that overlap with this replica in keyspace.
27+
NodeSnap = 2;
28+
// NodeApply corresponds to applying a replica's raft log up to a specific
29+
// committed index.
30+
NodeApply = 3;
31+
// NodeSplit corresponds to applying a split command on a replica, and
32+
// creating the replica of the post-split RHS range.
33+
NodeSplit = 4;
34+
// NodeMerge corresponds to applying a merge command on this replica and its
35+
// immediate RHS neighbour in the keyspace.
36+
NodeMerge = 5;
37+
// NodeDestroy correspond to destroying the replica and its state machine.
38+
NodeDestroy = 6;
39+
}
40+
41+
// Addr describes the full address of a WAG node, consisting of RangeID,
42+
// ReplicaID, and index into the raft log.
43+
//
44+
// It establishes "happens before" relationships between WAG nodes of a RangeID.
45+
// For example, when applying a node with Addr.ReplicaID, we know that all nodes
46+
// with lower ReplicaIDs (including their destruction), or same ReplicaID and
47+
// lower Index have been applied.
48+
message Addr {
49+
// RangeID is the ID of the range that the WAG node pertains to.
50+
int64 range_id = 1 [
51+
(gogoproto.customname) = "RangeID",
52+
(gogoproto.casttype) = "github.com/cockroachdb/cockroach/pkg/roachpb.RangeID"];
53+
// ReplicaID is the ID of the RangeID replica that the WAG node pertains to.
54+
int32 replica_id = 2 [
55+
(gogoproto.customname) = "ReplicaID",
56+
(gogoproto.casttype) = "github.com/cockroachdb/cockroach/pkg/roachpb.ReplicaID"];
57+
// Index identifies the raft log entry associated with this WAG node.
58+
// - For NodeCreate, it is 0 and signifies an uninitialized replica.
59+
// - For NodeSnap, it is the index of the snapshot, and the index at which
60+
// the raft log is initialized.
61+
// - For NodeApply, it is the log index identifying a prefix of the raft log.
62+
// - For NodeSplit and NodeMerge, it identifies the raft log command
63+
// containing the corresponding split/merge trigger.
64+
// - For NodeDestroy, it is MaxUint64.
65+
uint64 index = 4 [
66+
(gogoproto.casttype) = "github.com/cockroachdb/cockroach/pkg/kv/kvpb.RaftIndex"];
67+
}
68+
69+
// Node describes a node of the WAG.
70+
message Node {
71+
// Addr is the full address of the node, consisting of RangeID, ReplicaID, and
72+
// index into the raft log.
73+
Addr addr = 1 [(gogoproto.nullable) = false];
74+
// Type identifies the type of the replica lifecycle event that this node
75+
// represents, such as replica creation, destruction, split or merge.
76+
NodeType type = 2;
77+
// Mutation contains the mutation that will be applied to the state machine
78+
// engine when applying this WAG node.
79+
Mutation mutation = 3 [(gogoproto.nullable) = false];
80+
81+
// Create is the RangeID that this node brings into existence in the state
82+
// machine, or 0 if the node does not create new ranges. It is non-zero for
83+
// NodeCreate and NodeSplit.
84+
int64 create = 4 [
85+
(gogoproto.casttype) = "github.com/cockroachdb/cockroach/pkg/roachpb.RangeID"];
86+
// Destroy contains the RangeIDs that this node removes from the state
87+
// machine, because they are known to have been merged.
88+
// - For NodeMerge, it contains the ID of the RHS range being merged.
89+
// - For NodeSnap, it contains the list of subsumed ranges.
90+
repeated int64 destroy = 5 [
91+
(gogoproto.casttype) = "github.com/cockroachdb/cockroach/pkg/roachpb.RangeID"];
92+
}
93+
94+
// Mutation contains a mutation that can be applied to the state machine engine.
95+
// It can be represented by an encoded Pebble write batch or SSTable ingestion.
96+
message Mutation {
97+
// Batch contains an encoded Pebble write batch.
98+
bytes batch = 1;
99+
// Ingestion contains a Pebble ingestion.
100+
Ingestion ingestion = 2;
101+
}
102+
103+
// Ingestion describes a Pebble ingestion.
104+
message Ingestion {
105+
repeated string SSTs = 1;
106+
repeated cockroach.kv.kvserver.kvserverpb.SnapshotRequest.SharedTable shared_tables = 2;
107+
repeated cockroach.kv.kvserver.kvserverpb.SnapshotRequest.ExternalTable external_tables = 3;
108+
109+
// TODO(pav-kv): add the excise span, to mirror the IngestAndExciseFiles call
110+
// on storage.Engine.
111+
}

0 commit comments

Comments
 (0)