From cba2e5150c1529108fd3ac5efd814b706f850404 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Fri, 24 Jul 2026 17:51:33 -0700 Subject: [PATCH] plugin: fix flaky scheduler lock test (#10432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit plugin: stop the scheduler lock test racing its own background loops TestRunLaneSchedulerIterationLockBehavior constructed the plugin with a cluster-context provider, which makes New start a background scheduler loop per lane. Those loops call runLaneSchedulerIteration on the same lane the test then drives by hand, so a loop could consume the due job — running detection and pushing the next-detection time forward — before the manual call observed the lock. The Default case then saw the lock acquired zero times and failed intermittently. Construct without the provider so no loops start, and set the provider afterward so the manual iteration can still detect. This is the pattern scheduler_status_test.go already uses for the same reason. Reproduced under -race -count=100 -p 4 before, green after. Claude-Session: https://claude.ai/code/session_01Ks16jnt4S7gdDk8cheQ3xu --- weed/admin/plugin/plugin_scheduler_test.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/weed/admin/plugin/plugin_scheduler_test.go b/weed/admin/plugin/plugin_scheduler_test.go index 371f6a0b0..9b1d5e810 100644 --- a/weed/admin/plugin/plugin_scheduler_test.go +++ b/weed/admin/plugin/plugin_scheduler_test.go @@ -633,16 +633,19 @@ func TestRunLaneSchedulerIterationLockBehavior(t *testing.T) { t.Parallel() lm := &trackingLockManager{} - pluginSvc, err := New(Options{ - LockManager: lm, - ClusterContextProvider: func(context.Context) (*plugin_pb.ClusterContext, error) { - return &plugin_pb.ClusterContext{}, nil - }, - }) + // Construct without a cluster-context provider so the background + // lane loops do not start: they call runLaneSchedulerIteration on + // the same lane and would race this test's own manual call, + // consuming the due job before it observes the lock. The provider + // is set afterward so the manual iteration can still detect. + pluginSvc, err := New(Options{LockManager: lm}) if err != nil { t.Fatalf("New: %v", err) } defer pluginSvc.Shutdown() + pluginSvc.clusterContextProvider = func(context.Context) (*plugin_pb.ClusterContext, error) { + return &plugin_pb.ClusterContext{}, nil + } // Register a detectable worker for the job type. pluginSvc.registry.UpsertFromHello(&plugin_pb.WorkerHello{