@@ -374,6 +374,166 @@ func (suite *regionTestSuite) TestAccelerateRegionsScheduleInRanges() {
374374 suite .Len (idList , 4 )
375375}
376376
377+ func (suite * regionTestSuite ) TestAddForceMergeRanges () {
378+ re := suite .Require ()
379+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"false"}` ), tu .StatusOK (re )))
380+ defer func () {
381+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"true"}` ), tu .StatusOK (re )))
382+ }()
383+
384+ manager := suite .svr .GetRaftCluster ().GetForceMergeManager ()
385+ re .NotNil (manager )
386+
387+ startKey := []byte ("force-merge/a" )
388+ middleKey := []byte ("force-merge/b" )
389+ endKey := []byte ("force-merge/c" )
390+ cleanupEndKey := []byte ("force-merge/d" )
391+ body , err := json .Marshal (addForceMergeRangesRequest {
392+ StartKeysHex : []string {
393+ hex .EncodeToString (startKey ),
394+ hex .EncodeToString (middleKey ),
395+ },
396+ EndKeysHex : []string {
397+ hex .EncodeToString (middleKey ),
398+ hex .EncodeToString (endKey ),
399+ },
400+ })
401+ suite .NoError (err )
402+
403+ err = tu .CheckPostJSON (testDialClient , fmt .Sprintf ("%s/regions/force-merge" , suite .urlPrefix ), body , tu .StatusOK (re ))
404+ suite .NoError (err )
405+
406+ exactRegion := core .NewRegionInfo (& metapb.Region {Id : 10001 , StartKey : startKey , EndKey : endKey }, nil )
407+ suite .True (manager .SolveRegion (exactRegion ))
408+
409+ cleanupRegion := core .NewRegionInfo (& metapb.Region {Id : 10002 , StartKey : startKey , EndKey : cleanupEndKey }, nil )
410+ suite .False (manager .SolveRegion (cleanupRegion ))
411+ suite .False (manager .SolveRegion (exactRegion ))
412+ }
413+
414+ func (suite * regionTestSuite ) TestAddForceMergeRangesValidation () {
415+ re := suite .Require ()
416+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"false"}` ), tu .StatusOK (re )))
417+ defer func () {
418+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"true"}` ), tu .StatusOK (re )))
419+ }()
420+
421+ startKey := []byte ("force-merge/x" )
422+ endKey := []byte ("force-merge/y" )
423+ body , err := json .Marshal (addForceMergeRangesRequest {
424+ StartKeysHex : []string {hex .EncodeToString (startKey )},
425+ })
426+ suite .NoError (err )
427+
428+ err = tu .CheckPostJSON (
429+ testDialClient ,
430+ fmt .Sprintf ("%s/regions/force-merge" , suite .urlPrefix ),
431+ body ,
432+ tu .Status (re , http .StatusBadRequest ),
433+ tu .StringContain (re , "start key count 1 does not match end key count 0" ),
434+ )
435+ suite .NoError (err )
436+
437+ exactRegion := core .NewRegionInfo (& metapb.Region {Id : 10003 , StartKey : startKey , EndKey : endKey }, nil )
438+ suite .False (suite .svr .GetRaftCluster ().GetForceMergeManager ().SolveRegion (exactRegion ))
439+ }
440+
441+ func (suite * regionTestSuite ) TestAddForceMergeRangesCrossTableMergeEnabled () {
442+ re := suite .Require ()
443+ startKey := []byte ("force-merge/enable/x" )
444+ endKey := []byte ("force-merge/enable/y" )
445+ body , err := json .Marshal (addForceMergeRangesRequest {
446+ StartKeysHex : []string {hex .EncodeToString (startKey )},
447+ EndKeysHex : []string {hex .EncodeToString (endKey )},
448+ })
449+ suite .NoError (err )
450+
451+ err = tu .CheckPostJSON (
452+ testDialClient ,
453+ fmt .Sprintf ("%s/regions/force-merge" , suite .urlPrefix ),
454+ body ,
455+ tu .Status (re , http .StatusBadRequest ),
456+ tu .StringContain (re , "enable-cross-table-merge is true" ),
457+ )
458+ suite .NoError (err )
459+
460+ exactRegion := core .NewRegionInfo (& metapb.Region {Id : 10004 , StartKey : startKey , EndKey : endKey }, nil )
461+ suite .False (suite .svr .GetRaftCluster ().GetForceMergeManager ().SolveRegion (exactRegion ))
462+ }
463+
464+ func (suite * regionTestSuite ) TestAddForceMergeRangesNonTableKeyType () {
465+ re := suite .Require ()
466+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"false"}` ), tu .StatusOK (re )))
467+ defer func () {
468+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"true"}` ), tu .StatusOK (re )))
469+ }()
470+
471+ originalCfg := suite .svr .GetConfig ().PDServerCfg
472+ rawCfg := originalCfg
473+ rawCfg .KeyType = core .Raw .String ()
474+ suite .NoError (suite .svr .SetPDServerConfig (rawCfg ))
475+ defer func () {
476+ suite .NoError (suite .svr .SetPDServerConfig (originalCfg ))
477+ }()
478+
479+ startKey := []byte ("force-merge/raw/x" )
480+ endKey := []byte ("force-merge/raw/y" )
481+ body , err := json .Marshal (addForceMergeRangesRequest {
482+ StartKeysHex : []string {hex .EncodeToString (startKey )},
483+ EndKeysHex : []string {hex .EncodeToString (endKey )},
484+ })
485+ suite .NoError (err )
486+
487+ err = tu .CheckPostJSON (
488+ testDialClient ,
489+ fmt .Sprintf ("%s/regions/force-merge" , suite .urlPrefix ),
490+ body ,
491+ tu .Status (re , http .StatusBadRequest ),
492+ tu .StringContain (re , "key-type raw does not support force merge" ),
493+ )
494+ suite .NoError (err )
495+
496+ exactRegion := core .NewRegionInfo (& metapb.Region {Id : 10005 , StartKey : startKey , EndKey : endKey }, nil )
497+ suite .False (suite .svr .GetRaftCluster ().GetForceMergeManager ().SolveRegion (exactRegion ))
498+ }
499+
500+ func (suite * regionTestSuite ) TestDeleteForceMergeRanges () {
501+ re := suite .Require ()
502+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"false"}` ), tu .StatusOK (re )))
503+ defer func () {
504+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"true"}` ), tu .StatusOK (re )))
505+ }()
506+
507+ startKey := []byte ("force-merge/delete/x" )
508+ endKey := []byte ("force-merge/delete/y" )
509+ body , err := json .Marshal (addForceMergeRangesRequest {
510+ StartKeysHex : []string {hex .EncodeToString (startKey )},
511+ EndKeysHex : []string {hex .EncodeToString (endKey )},
512+ })
513+ suite .NoError (err )
514+ suite .NoError (tu .CheckPostJSON (
515+ testDialClient ,
516+ fmt .Sprintf ("%s/regions/force-merge" , suite .urlPrefix ),
517+ body ,
518+ tu .StatusOK (re ),
519+ ))
520+
521+ manager := suite .svr .GetRaftCluster ().GetForceMergeManager ()
522+ exactRegion := core .NewRegionInfo (& metapb.Region {Id : 10006 , StartKey : startKey , EndKey : endKey }, nil )
523+ suite .True (manager .SolveRegion (exactRegion ))
524+
525+ suite .NoError (tu .CheckPostJSON (testDialClient , suite .urlPrefix + "/config" , []byte (`{"enable-cross-table-merge":"true"}` ), tu .StatusOK (re )))
526+
527+ req , err := http .NewRequest (http .MethodDelete , fmt .Sprintf ("%s/regions/force-merge" , suite .urlPrefix ), nil )
528+ suite .NoError (err )
529+ resp , err := testDialClient .Do (req )
530+ suite .NoError (err )
531+ defer resp .Body .Close ()
532+ suite .Equal (http .StatusOK , resp .StatusCode )
533+
534+ suite .False (manager .SolveRegion (exactRegion ))
535+ }
536+
377537func (suite * regionTestSuite ) TestScatterRegions () {
378538 re := suite .Require ()
379539 r1 := newTestRegionInfo (601 , 13 , []byte ("b1" ), []byte ("b2" ))
0 commit comments