3
3
package streamhelper_test
4
4
5
5
import (
6
+ "bytes"
6
7
"context"
7
8
"fmt"
8
9
"strings"
@@ -356,48 +357,60 @@ func TestResolveLock(t *testing.T) {
356
357
lockRegion := c .findRegionByKey ([]byte ("01" ))
357
358
allLocks := []* txnlock.Lock {
358
359
{
359
- Key : []byte { 1 } ,
360
+ Key : []byte ( "011" ) ,
360
361
// TxnID == minCheckpoint
361
362
TxnID : minCheckpoint ,
362
363
},
363
364
{
364
- Key : []byte { 2 } ,
365
+ Key : []byte ( "012" ) ,
365
366
// TxnID > minCheckpoint
366
367
TxnID : minCheckpoint + 1 ,
367
368
},
369
+ {
370
+ Key : []byte ("013" ),
371
+ // this lock cannot be resolved due to scan version
372
+ TxnID : oracle .GoTimeToTS (oracle .GetTimeFromTS (minCheckpoint ).Add (2 * time .Minute )),
373
+ },
368
374
}
369
375
c .LockRegion (lockRegion , allLocks )
370
376
371
377
// ensure resolve locks triggered and collect all locks from scan locks
372
378
resolveLockRef := atomic .NewBool (false )
373
379
env .resolveLocks = func (locks []* txnlock.Lock , loc * tikv.KeyLocation ) (* tikv.KeyLocation , error ) {
374
380
resolveLockRef .Store (true )
375
- require .ElementsMatch (t , locks , allLocks )
381
+ // The third lock has skipped, because it's less than max version.
382
+ require .ElementsMatch (t , locks , allLocks [:2 ])
376
383
return loc , nil
377
384
}
378
385
adv := streamhelper .NewCheckpointAdvancer (env )
379
- // make lastCheckpoint stuck at 123
380
- adv .UpdateLastCheckpoint (streamhelper .NewCheckpointWithSpan (spans.Valued {
381
- Key : kv.KeyRange {
382
- StartKey : kv .Key ([]byte ("1" )),
383
- EndKey : kv .Key ([]byte ("2" )),
384
- },
385
- Value : 123 ,
386
- }))
387
- adv .NewCheckpoints (
388
- spans .Sorted (spans .NewFullWith ([]kv.KeyRange {
389
- {
390
- StartKey : kv .Key ([]byte ("1" )),
391
- EndKey : kv .Key ([]byte ("2" )),
392
- },
393
- }, 0 )),
394
- )
395
386
adv .StartTaskListener (ctx )
396
- require . Eventually ( t , func () bool { return adv . OnTick ( ctx ) == nil },
397
- time . Second , 50 * time . Millisecond )
387
+
388
+ maxTargetTs := uint64 ( 0 )
398
389
coll := streamhelper .NewClusterCollector (ctx , env )
390
+ coll .SetOnSuccessHook (func (u uint64 , kr kv.KeyRange ) {
391
+ adv .WithCheckpoints (func (s * spans.ValueSortedFull ) {
392
+ for _ , lock := range allLocks {
393
+ // if there is any lock key in the range
394
+ if bytes .Compare (kr .StartKey , lock .Key ) <= 0 && (bytes .Compare (lock .Key , kr .EndKey ) < 0 || len (kr .EndKey ) == 0 ) {
395
+ // mock lock behavior, do not update checkpoint
396
+ s .Merge (spans.Valued {Key : kr , Value : minCheckpoint })
397
+ return
398
+ }
399
+ }
400
+ s .Merge (spans.Valued {Key : kr , Value : u })
401
+ maxTargetTs = max (maxTargetTs , u )
402
+ })
403
+ })
399
404
err := adv .GetCheckpointInRange (ctx , []byte {}, []byte {}, coll )
400
405
require .NoError (t , err )
406
+ r , err := coll .Finish (ctx )
407
+ require .NoError (t , err )
408
+ require .Len (t , r .FailureSubRanges , 0 )
409
+ require .Equal (t , r .Checkpoint , minCheckpoint , "%d %d" , r .Checkpoint , minCheckpoint )
410
+
411
+ env .maxTs = maxTargetTs + 1
412
+ require .Eventually (t , func () bool { return adv .OnTick (ctx ) == nil },
413
+ time .Second , 50 * time .Millisecond )
401
414
// now the lock state must be ture. because tick finished and asyncResolveLocks got stuck.
402
415
require .True (t , adv .GetInResolvingLock ())
403
416
require .NoError (t , failpoint .Disable ("github.com/pingcap/tidb/br/pkg/streamhelper/AsyncResolveLocks" ))
@@ -406,10 +419,6 @@ func TestResolveLock(t *testing.T) {
406
419
// state must set to false after tick
407
420
require .Eventually (t , func () bool { return ! adv .GetInResolvingLock () },
408
421
8 * time .Second , 50 * time .Microsecond )
409
- r , err := coll .Finish (ctx )
410
- require .NoError (t , err )
411
- require .Len (t , r .FailureSubRanges , 0 )
412
- require .Equal (t , r .Checkpoint , minCheckpoint , "%d %d" , r .Checkpoint , minCheckpoint )
413
422
}
414
423
415
424
func TestOwnerDropped (t * testing.T ) {
0 commit comments