@@ -2056,6 +2056,190 @@ func TestTxnWriteBufferBatchRequestValidation(t *testing.T) {
2056
2056
}
2057
2057
}
2058
2058
2059
+ // TestTxnWriteBufferHasBufferedAllPrecedingWrites verifies that the
2060
+ // txnWriteBuffer correctly sets the HasBufferedAllPrecedingWrites flag.
2061
+ func TestTxnWriteBufferHasBufferedAllPrecedingWrites (t * testing.T ) {
2062
+ defer leaktest .AfterTest (t )()
2063
+ defer log .Scope (t ).Close (t )
2064
+
2065
+ txn := makeTxnProto ()
2066
+ txn .Sequence = 1
2067
+ keyA , keyB , keyC := roachpb .Key ("a" ), roachpb .Key ("b" ), roachpb .Key ("c" )
2068
+
2069
+ for _ , tc := range []struct {
2070
+ name string
2071
+ setup func (* txnWriteBuffer )
2072
+ ba func (ba * kvpb.BatchRequest )
2073
+ mockSend func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error )
2074
+ expHasBufferedAllPrecedingWrites bool
2075
+ }{
2076
+ {
2077
+ name : "batch with two Get requests" ,
2078
+ ba : func (ba * kvpb.BatchRequest ) {
2079
+ getA := & kvpb.GetRequest {RequestHeader : kvpb.RequestHeader {Key : keyA , Sequence : txn .Sequence }}
2080
+ getB := & kvpb.GetRequest {RequestHeader : kvpb.RequestHeader {Key : keyB , Sequence : txn .Sequence }}
2081
+ ba .Add (getA , getB )
2082
+ },
2083
+ mockSend : func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2084
+ require .Len (t , ba .Requests , 2 )
2085
+ require .IsType (t , & kvpb.GetRequest {}, ba .Requests [0 ].GetInner ())
2086
+ require .IsType (t , & kvpb.GetRequest {}, ba .Requests [1 ].GetInner ())
2087
+
2088
+ require .True (t , ba .HasBufferedAllPrecedingWrites )
2089
+
2090
+ br := ba .CreateReply ()
2091
+ br .Txn = ba .Txn
2092
+ return br , nil
2093
+ },
2094
+ expHasBufferedAllPrecedingWrites : true ,
2095
+ },
2096
+ {
2097
+ name : "batch with one Put and one Get request" ,
2098
+ ba : func (ba * kvpb.BatchRequest ) {
2099
+ putA := putArgs (keyA , "valA" , txn .Sequence )
2100
+ getB := & kvpb.GetRequest {RequestHeader : kvpb.RequestHeader {Key : keyB , Sequence : txn .Sequence }}
2101
+ ba .Add (putA , getB )
2102
+ },
2103
+ mockSend : func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2104
+ require .Len (t , ba .Requests , 1 )
2105
+ require .IsType (t , & kvpb.GetRequest {}, ba .Requests [0 ].GetInner ())
2106
+
2107
+ require .True (t , ba .HasBufferedAllPrecedingWrites )
2108
+
2109
+ br := ba .CreateReply ()
2110
+ br .Txn = ba .Txn
2111
+ return br , nil
2112
+ },
2113
+ expHasBufferedAllPrecedingWrites : true ,
2114
+ },
2115
+ {
2116
+ name : "batch with one Put, one Get, and one Delete request" ,
2117
+ ba : func (ba * kvpb.BatchRequest ) {
2118
+ putA := putArgs (keyA , "valA" , txn .Sequence )
2119
+ getB := & kvpb.GetRequest {RequestHeader : kvpb.RequestHeader {Key : keyB , Sequence : txn .Sequence }}
2120
+ delC := delArgs (keyC , txn .Sequence )
2121
+
2122
+ ba .Add (putA , getB , delC )
2123
+ },
2124
+ mockSend : func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2125
+ require .Len (t , ba .Requests , 1 )
2126
+ require .IsType (t , & kvpb.GetRequest {}, ba .Requests [0 ].GetInner ())
2127
+
2128
+ require .True (t , ba .HasBufferedAllPrecedingWrites )
2129
+
2130
+ br := ba .CreateReply ()
2131
+ br .Txn = ba .Txn
2132
+ return br , nil
2133
+ },
2134
+ expHasBufferedAllPrecedingWrites : true ,
2135
+ },
2136
+ {
2137
+ name : "batch with one DeleteRange and one Get request" ,
2138
+ ba : func (ba * kvpb.BatchRequest ) {
2139
+ delRange := delRangeArgs (keyA , keyB , txn .Sequence )
2140
+ getB := & kvpb.GetRequest {RequestHeader : kvpb.RequestHeader {Key : keyB , Sequence : txn .Sequence }}
2141
+
2142
+ ba .Add (delRange , getB )
2143
+ },
2144
+ mockSend : func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2145
+ require .Len (t , ba .Requests , 2 )
2146
+ require .IsType (t , & kvpb.DeleteRangeRequest {}, ba .Requests [0 ].GetInner ())
2147
+ require .IsType (t , & kvpb.GetRequest {}, ba .Requests [1 ].GetInner ())
2148
+
2149
+ require .True (t , ba .HasBufferedAllPrecedingWrites )
2150
+
2151
+ br := ba .CreateReply ()
2152
+ br .Txn = ba .Txn
2153
+ return br , nil
2154
+ },
2155
+ expHasBufferedAllPrecedingWrites : false ,
2156
+ },
2157
+ {
2158
+ name : "flushed due to size limit" ,
2159
+ setup : func (twb * txnWriteBuffer ) {
2160
+ bufferedWritesMaxBufferSize .Override (context .Background (), & twb .st .SV , 1 )
2161
+ },
2162
+ ba : func (ba * kvpb.BatchRequest ) {
2163
+ putA := putArgs (keyA , "valA" , txn .Sequence )
2164
+
2165
+ ba .Add (putA )
2166
+ },
2167
+ mockSend : func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2168
+ require .Len (t , ba .Requests , 1 )
2169
+ require .IsType (t , & kvpb.PutRequest {}, ba .Requests [0 ].GetInner ())
2170
+
2171
+ require .True (t , ba .HasBufferedAllPrecedingWrites )
2172
+
2173
+ br := ba .CreateReply ()
2174
+ br .Txn = ba .Txn
2175
+ return br , nil
2176
+ },
2177
+ expHasBufferedAllPrecedingWrites : false ,
2178
+ },
2179
+ {
2180
+ name : "write buffering disabled" ,
2181
+ setup : func (twb * txnWriteBuffer ) {
2182
+ twb .setEnabled (false )
2183
+ },
2184
+ ba : func (ba * kvpb.BatchRequest ) {
2185
+ putA := putArgs (keyA , "valA" , txn .Sequence )
2186
+
2187
+ ba .Add (putA )
2188
+ },
2189
+ mockSend : func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2190
+ require .Len (t , ba .Requests , 1 )
2191
+ require .IsType (t , & kvpb.PutRequest {}, ba .Requests [0 ].GetInner ())
2192
+
2193
+ // NB: Should never be set if write buffering is disabled
2194
+ require .False (t , ba .HasBufferedAllPrecedingWrites )
2195
+
2196
+ br := ba .CreateReply ()
2197
+ br .Txn = ba .Txn
2198
+ return br , nil
2199
+ },
2200
+ expHasBufferedAllPrecedingWrites : false ,
2201
+ },
2202
+ } {
2203
+ t .Run (tc .name , func (t * testing.T ) {
2204
+ ctx := context .Background ()
2205
+ st := cluster .MakeTestingClusterSettings ()
2206
+ twb , mockSender := makeMockTxnWriteBuffer (st )
2207
+
2208
+ if tc .setup != nil {
2209
+ tc .setup (& twb )
2210
+ }
2211
+
2212
+ ba := & kvpb.BatchRequest {}
2213
+ tc .ba (ba )
2214
+ mockSender .MockSend (tc .mockSend )
2215
+
2216
+ br , pErr := twb .SendLocked (ctx , ba )
2217
+ require .Nil (t , pErr )
2218
+ require .NotNil (t , br )
2219
+
2220
+ // Go to commit the transaction and ensure HasBufferedAllPrecedingWrites
2221
+ // is set correctly.
2222
+ mockSender .MockSend (func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
2223
+ require .Equal (t , tc .expHasBufferedAllPrecedingWrites , ba .HasBufferedAllPrecedingWrites )
2224
+
2225
+ br = ba .CreateReply ()
2226
+ br .Txn = ba .Txn
2227
+ return br , nil
2228
+ })
2229
+
2230
+ ba = & kvpb.BatchRequest {}
2231
+ ba .Header = kvpb.Header {Txn : & txn }
2232
+ ba .Add (& kvpb.EndTxnRequest {Commit : true })
2233
+
2234
+ br , pErr = twb .SendLocked (ctx , ba )
2235
+ require .Nil (t , pErr )
2236
+ require .NotNil (t , br )
2237
+ require .Len (t , br .Responses , 1 )
2238
+ require .IsType (t , & kvpb.EndTxnResponse {}, br .Responses [0 ].GetInner ())
2239
+ })
2240
+ }
2241
+ }
2242
+
2059
2243
// BenchmarkTxnWriteBuffer benchmarks the txnWriteBuffer. The test sets up a
2060
2244
// transaction with an existing buffer and runs a single batch through
2061
2245
// SendLocked and flushBufferAndSendBatch. The test varies the state of the
0 commit comments