feat(sources)!: split source contracts into PollSource/StreamSource and add mode-aware source config

- Introduce explicit source interfaces: sources.PollSource and sources.StreamSource, with shared sources.Input (Name() only).
- Remove mandatory Kind() from the base source contract to support sources that emit multiple kinds.
- Add config.SourceMode (poll, stream, or omitted/auto) and SourceConfig.Kinds (plural expected kinds), while keeping legacy SourceConfig.Kind for compatibility.
- Enforce mode semantics in config validation (poll requires every, stream forbids every) and detect mode/driver mismatches in sources.Registry.
- Update docs and tests for the new source model and config behavior.
This commit is contained in:
2026-03-15 19:19:19 -05:00
parent fafba0f01b
commit 6c5f95ad26
12 changed files with 591 additions and 542 deletions

View File

@@ -20,7 +20,7 @@ type Logger = logging.Logf
// Job describes one scheduler task.
//
// A Job may be backed by either:
// - a polling source (sources.Source): uses Every + jitter and calls Poll()
// - a polling source (sources.PollSource): uses Every + jitter and calls Poll()
// - a stream source (sources.StreamSource): ignores Every and calls Run()
//
// Jitter behavior:
@@ -80,7 +80,7 @@ func (s *Scheduler) runJob(ctx context.Context, job Job) {
}
// Poll sources: time-based.
ps, ok := job.Source.(sources.Source)
ps, ok := job.Source.(sources.PollSource)
if !ok {
s.logf("scheduler: source %T (%s) implements neither Poll() nor Run()", job.Source, job.Source.Name())
return
@@ -108,7 +108,7 @@ func (s *Scheduler) runStream(ctx context.Context, job Job, src sources.StreamSo
}
}
func (s *Scheduler) runPoller(ctx context.Context, job Job, src sources.Source) {
func (s *Scheduler) runPoller(ctx context.Context, job Job, src sources.PollSource) {
// Compute jitter: either configured per job, or a sensible default.
jitter := effectiveJitter(job.Every, job.Jitter)
@@ -141,7 +141,7 @@ func (s *Scheduler) runPoller(ctx context.Context, job Job, src sources.Source)
}
}
func (s *Scheduler) pollOnce(ctx context.Context, src sources.Source) {
func (s *Scheduler) pollOnce(ctx context.Context, src sources.PollSource) {
events, err := src.Poll(ctx)
if err != nil {
s.logf("scheduler: poll failed (%s): %v", src.Name(), err)