Skip to content

Commit 66b29a4

Browse files
committed
etcdserver: add --max-txn-ops flag
--max-txn-ops allows users to define the maximum transaction operations for each txn request. it defaults at 128. Fixes etcd-io#7826
1 parent f75e333 commit 66b29a4

File tree

8 files changed

+20
-10
lines changed

8 files changed

+20
-10
lines changed

clientv3/integration/txn_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func TestTxnError(t *testing.T) {
4141
t.Fatalf("expected %v, got %v", rpctypes.ErrDuplicateKey, err)
4242
}
4343

44-
ops := make([]clientv3.Op, v3rpc.MaxOpsPerTxn+10)
44+
ops := make([]clientv3.Op, v3rpc.MaxTxnOps+10)
4545
for i := range ops {
4646
ops[i] = clientv3.OpPut(fmt.Sprintf("foo%d", i), "")
4747
}

embed/config.go

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const (
4040
DefaultName = "default"
4141
DefaultMaxSnapshots = 5
4242
DefaultMaxWALs = 5
43+
DefaultMaxTxnOps = uint(128)
4344

4445
DefaultListenPeerURLs = "http://localhost:2380"
4546
DefaultListenClientURLs = "http://localhost:2379"
@@ -85,6 +86,7 @@ type Config struct {
8586
TickMs uint `json:"heartbeat-interval"`
8687
ElectionMs uint `json:"election-timeout"`
8788
QuotaBackendBytes int64 `json:"quota-backend-bytes"`
89+
MaxTxnOps uint `json:"max-txn-ops"`
8890

8991
// clustering
9092

@@ -172,6 +174,7 @@ func NewConfig() *Config {
172174
MaxWalFiles: DefaultMaxWALs,
173175
Name: DefaultName,
174176
SnapCount: etcdserver.DefaultSnapCount,
177+
MaxTxnOps: DefaultMaxTxnOps,
175178
TickMs: 100,
176179
ElectionMs: 1000,
177180
LPUrls: []url.URL{*lpurl},

embed/etcd.go

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) {
139139
ElectionTicks: cfg.ElectionTicks(),
140140
AutoCompactionRetention: cfg.AutoCompactionRetention,
141141
QuotaBackendBytes: cfg.QuotaBackendBytes,
142+
MaxTxnOps: cfg.MaxTxnOps,
142143
StrictReconfigCheck: cfg.StrictReconfigCheck,
143144
ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth,
144145
AuthToken: cfg.AuthToken,

etcdmain/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ func newConfig() *config {
138138
fs.UintVar(&cfg.TickMs, "heartbeat-interval", cfg.TickMs, "Time (in milliseconds) of a heartbeat interval.")
139139
fs.UintVar(&cfg.ElectionMs, "election-timeout", cfg.ElectionMs, "Time (in milliseconds) for an election to timeout.")
140140
fs.Int64Var(&cfg.QuotaBackendBytes, "quota-backend-bytes", cfg.QuotaBackendBytes, "Raise alarms when backend size exceeds the given quota. 0 means use the default quota.")
141+
fs.UintVar(&cfg.MaxTxnOps, "max-txn-ops", cfg.MaxTxnOps, "Maximum operations per txn that etcd server allows; defaults to 128.")
141142

142143
// clustering
143144
fs.Var(flags.NewURLsValue(embed.DefaultInitialAdvertisePeerURLs), "initial-advertise-peer-urls", "List of this member's peer URLs to advertise to the rest of the cluster.")

etcdmain/help.go

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ member flags:
6666
comma-separated whitelist of origins for CORS (cross-origin resource sharing).
6767
--quota-backend-bytes '0'
6868
raise alarms when backend size exceeds the given quota (0 defaults to low space quota).
69+
--max-txn-ops '128'
70+
maximum operations per txn that etcd server allows; defaults to 128.
6971
7072
clustering flags:
7173

etcdserver/api/v3rpc/key.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,20 @@ import (
2727

2828
var (
2929
plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "etcdserver/api/v3rpc")
30-
31-
// Max operations per txn list. For example, Txn.Success can have at most 128 operations,
32-
// and Txn.Failure can have at most 128 operations.
33-
MaxOpsPerTxn = 128
3430
)
3531

3632
type kvServer struct {
3733
hdr header
3834
kv etcdserver.RaftKV
35+
// maxTxnOps is the max operations per txn.
36+
// e.g suppose maxOpsPerTxn = 128.
37+
// Txn.Success can have at most 128 operations,
38+
// and Txn.Failure can have at most 128 operations.
39+
maxTxnOps uint
3940
}
4041

4142
func NewKVServer(s *etcdserver.EtcdServer) pb.KVServer {
42-
return &kvServer{hdr: newHeader(s), kv: s}
43+
return &kvServer{hdr: newHeader(s), kv: s, maxTxnOps: s.Cfg.MaxTxnOps}
4344
}
4445

4546
func (s *kvServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
@@ -94,7 +95,7 @@ func (s *kvServer) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*
9495
}
9596

9697
func (s *kvServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
97-
if err := checkTxnRequest(r); err != nil {
98+
if err := checkTxnRequest(r, int(s.maxTxnOps)); err != nil {
9899
return nil, err
99100
}
100101

@@ -150,8 +151,9 @@ func checkDeleteRequest(r *pb.DeleteRangeRequest) error {
150151
return nil
151152
}
152153

153-
func checkTxnRequest(r *pb.TxnRequest) error {
154-
if len(r.Compare) > MaxOpsPerTxn || len(r.Success) > MaxOpsPerTxn || len(r.Failure) > MaxOpsPerTxn {
154+
func checkTxnRequest(r *pb.TxnRequest, maxTxnOps int) error {
155+
plog.Infof("maxTxnOps %v", maxTxnOps)
156+
if len(r.Compare) > maxTxnOps || len(r.Success) > maxTxnOps || len(r.Failure) > maxTxnOps {
155157
return rpctypes.ErrGRPCTooManyOps
156158
}
157159

etcdserver/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type ServerConfig struct {
5454

5555
AutoCompactionRetention int
5656
QuotaBackendBytes int64
57+
MaxTxnOps uint
5758

5859
StrictReconfigCheck bool
5960

integration/v3_grpc_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func TestV3TxnTooManyOps(t *testing.T) {
201201

202202
for i, tt := range tests {
203203
txn := &pb.TxnRequest{}
204-
for j := 0; j < v3rpc.MaxOpsPerTxn+1; j++ {
204+
for j := 0; j < v3rpc.MaxTxnOps+1; j++ {
205205
tt(txn)
206206
}
207207

0 commit comments

Comments
 (0)