schedx

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package schedx provides concurrent job schedulers with bounded pending queues and graceful shutdown.

Scheduler

Scheduler is fire-and-forget: enqueue with Scheduler.Push, start workers with Scheduler.Run, shut down with Scheduler.Close. Jobs are Job / JobFunc. Completion is observed via WithCallback; remaining queued items on exit via WithExitCallback.

RetrievableScheduler

RetrievableScheduler returns a Result per successful RetrievableScheduler.Push. Callers wait with Result.Result. There is no completion Callback - Result is the completion channel. On Close, all unfinished Results are failed immediately so waiters do not block; queued work is discarded and not executed.

Shared lifecycle

New* → Run → Push* → Close

Constraints (both schedulers):

  • Scheduler.Run / RetrievableScheduler.Run may succeed only once (ERROR__SCHEDULER_RERUN on retry)
  • Push before Run → ERROR__SCHEDULER_NOT_RUNNING
  • Push after Close / nest canceled → ERROR__SCHEDULER_CANCELED
  • Pending limit exceeded → ERROR__REACH_MAX_PENDING
  • Parent context cancel and manual Close both surface as ERROR__SCHEDULER_CANCELED (optionally wrapping the underlying cause)

Pending counts queue depth (decremented on Pop), not in-flight Job execution.

Options

Scheduler: MaxPending, Parallel, FIFO/LIFO, Callback, ExitCallback, CloseTimeout, WithoutDetached.

RetrievableScheduler: MaxPending, Parallel, FIFO/LIFO, CloseTimeout, WithoutDetached (no Callback / ExitCallback).

By default, running jobs use context.WithoutCancel (detached from scheduler cancel). Use WithoutDetached / WithoutRetrievableDetached to propagate cancel into Job.Do. CloseTimeout bounds waiting for workers via nest, not Result unblocking (Retrievable fails Results in BeforeClose).

Usage (Scheduler):

s := schedx.NewScheduler(
	schedx.JobFunc[int](func(ctx context.Context, v int) error {
		return nil
	}),
	schedx.WithMaxPending[int](100),
	schedx.WithParallel[int](8),
)
if err := s.Run(ctx); err != nil {
	return err
}
defer func() { _ = s.Close() }()
_ = s.Push(ctx, 42)

Usage (RetrievableScheduler):

s := schedx.NewRetrievableScheduler(
	schedx.RetrievableJobFunc[int, int](func(ctx context.Context, in int) (int, error) {
		return in * 2, nil
	}),
	schedx.WithRetrievableMaxPending[int, int](100),
)
if err := s.Run(ctx); err != nil {
	return err
}
defer func() { _ = s.Close() }()
ret, err := s.Push(ctx, 21)
if err != nil {
	return err
}
out, err := ret.Result(ctx)

For structured concurrency without a job queue, use package nest directly.

Code generated by genx:code@v0.3.7 DO NOT EDIT.

Index

Examples

Constants

View Source
const MaxParallel = 10000

Variables

This section is empty.

Functions

This section is empty.

Types

type Error

type Error uint8

Error defines error codes of scheduler +genx:code @code domain=SCHED

const (
	ERROR_UNDEFINED               Error = iota
	ERROR__REACH_MAX_PENDING            // reached max pending limitation
	ERROR__SCHEDULER_NOT_RUNNING        // Push before Run
	ERROR__SCHEDULER_RERUN              // scheduler is already running
	ERROR__SCHEDULER_CANCELED           // scheduler is canceled (Close or parent ctx)
	ERROR__SCHEDULER_JOB_PANICKED       // scheduler job panicked
)

func (Error) Message

func (e Error) Message() string

type ExitingCallback

type ExitingCallback[T any] func([]T, error)

type HandlerCallback

type HandlerCallback[T any] func(T, error)

type Job

type Job[T any] interface {
	Do(context.Context, T) error
}

type JobFunc

type JobFunc[T any] func(context.Context, T) error

func (JobFunc[T]) Do

func (f JobFunc[T]) Do(ctx context.Context, v T) error

type Result added in v0.2.2

type Result[Out any] interface {
	Result(context.Context) (Out, error)
}

type RetrievableJob added in v0.2.2

type RetrievableJob[In, Out any] interface {
	Do(context.Context, In) (Out, error)
}

type RetrievableJobFunc added in v0.2.2

type RetrievableJobFunc[In, Out any] func(context.Context, In) (Out, error)

func (RetrievableJobFunc[In, Out]) Do added in v0.2.2

func (f RetrievableJobFunc[In, Out]) Do(ctx context.Context, in In) (Out, error)

type RetrievableScheduler added in v0.2.2

type RetrievableScheduler[In, Out any] interface {
	Push(context.Context, In) (Result[Out], error)
	Run(context.Context) error
	Pending() int
	Close() error
}

func NewRetrievableScheduler added in v0.2.2

func NewRetrievableScheduler[In, Out any](
	f RetrievableJob[In, Out],
	appliers ...RetrievableSchedulerApplier,
) RetrievableScheduler[In, Out]

NewRetrievableScheduler builds a scheduler that returns a Result per Push.

Lifecycle: New → Run → Push* → Close. Push before Run returns ERROR__SCHEDULER_NOT_RUNNING.

Close fails all unfinished Results immediately so waiters do not block; leftover queued work is not executed. Job.Do follows nest / Detached options and is independent of Result completion.

Example

ExampleNewRetrievableScheduler shows Run → Push → Result → Close.

ctx := context.Background()

s := schedx.NewRetrievableScheduler(
	schedx.RetrievableJobFunc[int, string](func(_ context.Context, in int) (string, error) {
		return fmt.Sprintf("n=%d", in*2), nil
	}),
	schedx.WithRetrievableMaxPending(8),
	schedx.WithRetrievableParallel(2),
)

_ = s.Run(ctx)
defer func() {
	_ = s.Close()
}()

ret, _ := s.Push(ctx, 21)

out, _ := ret.Result(ctx)
fmt.Println(out)
Output:
n=42

type RetrievableSchedulerApplier added in v0.2.2

type RetrievableSchedulerApplier func(*retrievableOption)

func WithRetrievableCloseTimeout added in v0.2.2

func WithRetrievableCloseTimeout(d time.Duration) RetrievableSchedulerApplier

func WithRetrievableFifoScheduleMode added in v0.2.2

func WithRetrievableFifoScheduleMode() RetrievableSchedulerApplier

func WithRetrievableLifoScheduleMode added in v0.2.2

func WithRetrievableLifoScheduleMode() RetrievableSchedulerApplier

func WithRetrievableMaxPending added in v0.2.2

func WithRetrievableMaxPending(n int) RetrievableSchedulerApplier

func WithRetrievableParallel added in v0.2.2

func WithRetrievableParallel(n int) RetrievableSchedulerApplier

func WithoutRetrievableDetached added in v0.2.2

func WithoutRetrievableDetached() RetrievableSchedulerApplier

func WithoutRetrievablePendingLimitation added in v0.2.2

func WithoutRetrievablePendingLimitation() RetrievableSchedulerApplier

type ScheduleMode

type ScheduleMode int
const (
	FIFO ScheduleMode = iota
	LIFO
)

type Scheduler

type Scheduler[T any] interface {
	Push(context.Context, T) error
	Run(context.Context) error
	Pending() int
	Close() error
}

func NewScheduler

func NewScheduler[T any](f Job[T], appliers ...SchedulerOptionApplier[T]) Scheduler[T]

type SchedulerOptionApplier

type SchedulerOptionApplier[T any] func(*option[T])

func WithCallback

func WithCallback[T any](cb HandlerCallback[T]) SchedulerOptionApplier[T]

WithCallback sets a callback that is invoked after task execution.

func WithCloseTimeout

func WithCloseTimeout[T any](du time.Duration) SchedulerOptionApplier[T]

WithCloseTimeout sets timeout to handle post-close when Scheduler.Close The default value is 0 means waiting all paralleled goroutines exited gracefully

func WithExitCallback

func WithExitCallback[T any](cb ExitingCallback[T]) SchedulerOptionApplier[T]

WithExitCallback sets a callback invoked when the scheduler exits. It receives remaining pending jobs and the exit reason. The callback is guaranteed to be called at most once.

func WithFifoScheduleMode

func WithFifoScheduleMode[T any]() SchedulerOptionApplier[T]

WithFifoScheduleMode sets the scheduler mode to FIFO.

func WithLifoScheduleMode

func WithLifoScheduleMode[T any]() SchedulerOptionApplier[T]

WithLifoScheduleMode sets the scheduler mode to LIFO.

func WithMaxPending

func WithMaxPending[T any](maxPending int) SchedulerOptionApplier[T]

WithMaxPending sets the maximum number of pending tasks allowed. the default value is 1.

func WithParallel

func WithParallel[T any](parallel int) SchedulerOptionApplier[T]

WithParallel sets the number of tasks processed in parallel. the default value is 1.

func WithoutDetached

func WithoutDetached[T any]() SchedulerOptionApplier[T]

WithoutDetached (Decouple from parent lifecycle) If false(the default mode), the internal context is derived using context.WithoutCancel(parent). This allows the popped task to ignore cancellation signals or deadlines from the parent context, while still inheriting and propagating existing context values (e.g., TraceID, UserID).

func WithoutPendingLimitation

func WithoutPendingLimitation[T any]() SchedulerOptionApplier[T]

WithoutPendingLimitation disables the pending-task limit by setting it to -1.

type Tasks

type Tasks[T any] interface {
	Len() int
	Push(T)
	Pop() (T, bool)
	Range(func(T) bool)
	Clear()
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL