diff --git a/README.md b/README.md index f90e716..d882333 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ A robust cron job manager built on [robfig/cron](https://github.com/robfig/cron) * `WithSkipActive` Prevents parallel execution of the same job. * `WithMaintenance` Ensures exclusive execution for maintenance jobs. * `WithMetrics` Tracks execution metrics (count, duration, active jobs). - +* `WithDeadlineFunc` Limits job execution deadline for the job based on a user-defined function. +* `WithTimeout` Limits job execution time to a fixed duration. ## Built-in UI Preview ![Web UI](/examples/webui.png) @@ -56,6 +57,12 @@ Please see `examples/main.go` for basic usage. ```go m := cron.NewManager() + deadlineMiddleware := cron.WithDeadlineFunc(func(ctx context.Context) time.Time { + return time.Now().Add(50 * time.Second) + }) + + timeOutMiddleware := cron.WithTimeout(50 * time.Second) + m.Use( cron.WithMetrics("test"), cron.WithDevel(false), @@ -65,11 +72,12 @@ Please see `examples/main.go` for basic usage. cron.WithSkipActive(), cron.WithRecover(), // recover() inside cron.WithSentry(), // recover() inside + deadlineMiddleware, // use deadlineMiddleware or timeOutMiddleware globally ) // add simple funcs - m.AddFunc("f1", "* * * * *", newTask("f1")) - m.AddFunc("f2", "* * * * *", newTask("f2")) + m.AddFunc("f1", "* * * * *", timeOutMiddleware(newTask("f1"))) // use timeOutMiddleware per task + m.AddFunc("f2", "* * * * *", deadlineMiddleware(newTask("f2"))) // use deadlineMiddleware per task m.AddFunc("f5", "", newTask("f5")) m.AddMaintenanceFunc("f3", "*/2 * * * *", newTask("f3m")) diff --git a/examples/main.go b/examples/main.go index c17d9f9..dae558c 100644 --- a/examples/main.go +++ b/examples/main.go @@ -42,6 +42,13 @@ func main() { sl := NewLogger(false) ctx := context.Background() m := cron.NewManager() + + deadlineMiddleware := cron.WithDeadlineFunc(func(ctx context.Context) time.Time { + return time.Now().Add(50 * time.Second) + }) + + timeOutMiddleware := cron.WithTimeout(50 * time.Second) + m.Use( cron.WithMetrics("test"), cron.WithDevel(false), @@ -51,11 +58,12 @@ func main() { cron.WithSkipActive(), cron.WithRecover(), // recover() inside cron.WithSentry(), // recover() inside + deadlineMiddleware, // use deadlineMiddleware or timeOutMiddleware globally ) // add simple func - m.AddFunc("f1", "* * * * *", newTask("f1")) - m.AddFunc("f2", "* * * * *", newTask("f2")) + m.AddFunc("f1", "* * * * *", timeOutMiddleware(newTask("f1"))) // use timeOutMiddleware per task + m.AddFunc("f2", "* * * * *", deadlineMiddleware(newTask("f2"))) // use deadlineMiddleware per task m.AddFunc("f5", "", newTask("f5")) m.AddMaintenanceFunc("f3", "*/2 * * * *", newTask("f3m")) diff --git a/middleware.go b/middleware.go index f018831..7e852c6 100644 --- a/middleware.go +++ b/middleware.go @@ -248,3 +248,20 @@ func WithMetrics(app string) MiddlewareFunc { } } } + +// WithTimeout returns a MiddlewareFunc that wraps a Func with a context timeout. +func WithTimeout(timeout time.Duration) MiddlewareFunc { + return WithDeadlineFunc(func(ctx context.Context) time.Time { return time.Now().Add(timeout) }) +} + +// WithDeadlineFunc returns a MiddlewareFunc that wraps a Func with a context deadline. +// The deadline is determined by calling the provided function df. +func WithDeadlineFunc(df func(context.Context) time.Time) MiddlewareFunc { + return func(next Func) Func { + return func(ctx context.Context) error { + ctx, cancel := context.WithDeadline(ctx, df(ctx)) + defer cancel() + return next(ctx) + } + } +}