@@ -28,7 +28,7 @@ func patchLinearizableOperations(reports []report.ClientReport, persistedRequest
28
28
putRevision := putRevision (reports )
29
29
persistedPutCount := countPersistedPuts (persistedRequests )
30
30
clientPutCount := countClientPuts (reports )
31
- putReturnTime := uniquePutReturnTime (allOperations , reports , persistedRequests , clientPutCount )
31
+ putReturnTime := uniquePutReturnTime (allOperations , reports , clientPutCount )
32
32
return patchOperations (allOperations , putRevision , putReturnTime , clientPutCount , persistedPutCount )
33
33
}
34
34
@@ -96,7 +96,7 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
96
96
txnRevision = revision
97
97
}
98
98
if returnTime , ok := putReturnTime [kv ]; ok {
99
- op .Return = min ( op . Return , returnTime )
99
+ op .Return = returnTime
100
100
}
101
101
case model .DeleteOperation :
102
102
case model .RangeOperation :
@@ -110,9 +110,9 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
110
110
continue
111
111
}
112
112
if txnRevision != 0 {
113
- op .Output = model.MaybeEtcdResponse {Persisted : true , PersistedRevision : txnRevision }
113
+ op .Output = model.MaybeEtcdResponse {Persisted : true , PersistedRevision : txnRevision , Error : resp . Error }
114
114
} else {
115
- op .Output = model.MaybeEtcdResponse {Persisted : true }
115
+ op .Output = model.MaybeEtcdResponse {Persisted : true , Error : resp . Error }
116
116
}
117
117
}
118
118
// Leave operation as it is as we cannot discard it.
@@ -155,11 +155,13 @@ func hasUniqueWriteOperation(ops []model.EtcdOperation, clientRequestCount map[k
155
155
return false
156
156
}
157
157
158
- func uniquePutReturnTime (allOperations []porcupine.Operation , reports []report.ClientReport , persistedRequests []model. EtcdRequest , clientPutCount map [keyValue ]int64 ) map [keyValue ]int64 {
158
+ func uniquePutReturnTime (allOperations []porcupine.Operation , reports []report.ClientReport , clientPutCount map [keyValue ]int64 ) map [keyValue ]int64 {
159
159
earliestReturnTime := map [keyValue ]int64 {}
160
- var lastReturnTime int64
160
+ failedRequest := map [keyValue ]bool {}
161
+
161
162
for _ , op := range allOperations {
162
163
request := op .Input .(model.EtcdRequest )
164
+ resp := op .Output .(model.MaybeEtcdResponse )
163
165
switch request .Type {
164
166
case model .Txn :
165
167
for _ , etcdOp := range append (request .Txn .OperationsOnSuccess , request .Txn .OperationsOnFailure ... ) {
@@ -170,10 +172,14 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, reports []report.C
170
172
if count := clientPutCount [kv ]; count > 1 {
171
173
continue
172
174
}
175
+ if resp .Error != "" {
176
+ failedRequest [kv ] = true
177
+ }
173
178
if returnTime , ok := earliestReturnTime [kv ]; ! ok || returnTime > op .Return {
179
+ // The time that the response is received
180
+ // This doesn't mean anything for the failed request, as the request might have actually succeeded (e.g. connection dropped, etc.)
174
181
earliestReturnTime [kv ] = op .Return
175
182
}
176
- earliestReturnTime [kv ] = op .Return
177
183
}
178
184
case model .Range :
179
185
case model .LeaseGrant :
@@ -182,11 +188,11 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, reports []report.C
182
188
default :
183
189
panic (fmt .Sprintf ("Unknown request type: %q" , request .Type ))
184
190
}
185
- if op .Return > lastReturnTime {
186
- lastReturnTime = op .Return
187
- }
188
191
}
189
192
193
+ // for failed requests, we use the time that the watch is received as the return time
194
+ // since the values returned by the watch are the values that are actually written in the database
195
+ // notice that the time that the value is sent by the watch might be earlier or later than the response received time due to issues such as network problems
190
196
for _ , client := range reports {
191
197
for _ , watch := range client .Watch {
192
198
for _ , resp := range watch .Responses {
@@ -198,8 +204,12 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, reports []report.C
198
204
if count := clientPutCount [kv ]; count > 1 {
199
205
continue
200
206
}
201
- if t , ok := earliestReturnTime [kv ]; ! ok || t > resp . Time . Nanoseconds () {
207
+ if _ , ok := failedRequest [kv ]; ok {
202
208
earliestReturnTime [kv ] = resp .Time .Nanoseconds ()
209
+ } else {
210
+ if t , ok := earliestReturnTime [kv ]; ! ok || t > resp .Time .Nanoseconds () {
211
+ earliestReturnTime [kv ] = resp .Time .Nanoseconds ()
212
+ }
203
213
}
204
214
case model .DeleteOperation :
205
215
default :
@@ -210,32 +220,6 @@ func uniquePutReturnTime(allOperations []porcupine.Operation, reports []report.C
210
220
}
211
221
}
212
222
213
- for i := len (persistedRequests ) - 1 ; i >= 0 ; i -- {
214
- request := persistedRequests [i ]
215
- switch request .Type {
216
- case model .Txn :
217
- lastReturnTime --
218
- for _ , op := range request .Txn .OperationsOnSuccess {
219
- if op .Type != model .PutOperation {
220
- continue
221
- }
222
- kv := keyValue {Key : op .Put .Key , Value : op .Put .Value }
223
- if count := clientPutCount [kv ]; count > 1 {
224
- continue
225
- }
226
- returnTime , ok := earliestReturnTime [kv ]
227
- if ok {
228
- lastReturnTime = min (returnTime , lastReturnTime )
229
- earliestReturnTime [kv ] = lastReturnTime
230
- }
231
- }
232
- case model .LeaseGrant :
233
- case model .LeaseRevoke :
234
- case model .Compact :
235
- default :
236
- panic (fmt .Sprintf ("Unknown request type: %q" , request .Type ))
237
- }
238
- }
239
223
return earliestReturnTime
240
224
}
241
225
0 commit comments