From c3bf93f1b6e21508f0ab29e32e5fb866e5f61d0f Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Wed, 21 May 2025 11:08:30 +0300 Subject: [PATCH] Fix context lifecycle in scheduled actions Remove ctx field from scheduledActs struct and create a fresh context when actions execute via cron. This prevents "context canceled" errors that occurred when stored contexts from API calls were used for delayed execution. The context is now properly received from the caller in case of "*asap" actions. --- actions/actions.go | 2 +- actions/actions_test.go | 1 - actions/libactions.go | 11 ++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actions/actions.go b/actions/actions.go index b952e3541..0ebc1f90e 100644 --- a/actions/actions.go +++ b/actions/actions.go @@ -268,7 +268,7 @@ func (aS *ActionS) asapExecuteActions(ctx *context.Context, sActs *scheduledActs utils.ActionS, sActs.tenant, sActs.apID, err)) return } - if err = sActs.Execute(); err != nil { // cannot remove due to errors on execution + if err = sActs.Execute(ctx); err != nil { // cannot remove due to errors on execution return } delete(ap.Targets[sActs.trgTyp], sActs.trgID) diff --git a/actions/actions_test.go b/actions/actions_test.go index a7af6a713..bac0a5a0b 100644 --- a/actions/actions_test.go +++ b/actions/actions_test.go @@ -1051,7 +1051,6 @@ func TestACScheduledActions(t *testing.T) { trgTyp: utils.MetaStats, trgID: "ID_TEST", schedule: utils.EmptyString, - ctx: context.Background(), data: mapStorage, }, } diff --git a/actions/libactions.go b/actions/libactions.go index 7070539e6..970f63529 100644 --- a/actions/libactions.go +++ b/actions/libactions.go @@ -50,7 +50,6 @@ func newScheduledActs(ctx *context.Context, tenant, apID, trgTyp, trgID, schedul trgTyp: trgTyp, trgID: trgID, schedule: schedule, - ctx: ctx, data: data, acts: acts, cch: ltcache.NewTransCache(map[string]*ltcache.CacheConfig{}), @@ -64,7 +63,6 @@ type scheduledActs struct { trgTyp string trgID string schedule string - ctx *context.Context data utils.MapStorage acts []actioner @@ -73,15 +71,18 @@ type scheduledActs struct { // Execute is called when we want the ActionProfile to be executed func (s *scheduledActs) ScheduledExecute() { - s.Execute() + // Create a fresh root context when cron triggers execution. + // TODO: decide whether a timeout should be configured. + ctx := context.Background() + s.Execute(ctx) } // Execute notifies possible errors on execution -func (s *scheduledActs) Execute() (err error) { +func (s *scheduledActs) Execute(ctx *context.Context) (err error) { var partExec bool for _, act := range s.acts { //ctx, cancel := context.WithTimeout(s.ctx, act.cfg().TTL) - if err := act.execute(s.ctx, s.data, s.trgID); err != nil { + if err := act.execute(ctx, s.data, s.trgID); err != nil { utils.Logger.Warning(fmt.Sprintf("executing action: <%s>, error: <%s>", act.id(), err)) partExec = true }