Upgraded feedkit's handling of stream sources
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
// - Input: common source identity surface
|
||||
// - PollSource: polling source interface
|
||||
// - StreamSource: streaming source interface
|
||||
// - StreamRetryable / StreamFatal / IsStreamRetryable / IsStreamFatal:
|
||||
// stream exit classification helpers
|
||||
// - Registry / NewRegistry: source driver registry and builders
|
||||
// - HTTPSource / NewHTTPSource: reusable HTTP polling helper
|
||||
//
|
||||
|
||||
@@ -35,6 +35,9 @@ type PollSource interface {
|
||||
//
|
||||
// Run should block, producing events into `out` until ctx is cancelled or a fatal error occurs.
|
||||
// It MUST NOT close out (the scheduler/daemon owns the bus).
|
||||
//
|
||||
// Stream sources can classify exits by wrapping errors with StreamRetryable or
|
||||
// StreamFatal. Plain non-nil errors are treated as retryable by the scheduler.
|
||||
type StreamSource interface {
|
||||
Input
|
||||
Run(ctx context.Context, out chan<- event.Event) error
|
||||
|
||||
63
sources/stream_errors.go
Normal file
63
sources/stream_errors.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package sources
|
||||
|
||||
import "errors"
|
||||
|
||||
type streamRetryableError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *streamRetryableError) Error() string {
|
||||
if e.err == nil {
|
||||
return "retryable stream error"
|
||||
}
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e *streamRetryableError) Unwrap() error { return e.err }
|
||||
|
||||
type streamFatalError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *streamFatalError) Error() string {
|
||||
if e.err == nil {
|
||||
return "fatal stream error"
|
||||
}
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e *streamFatalError) Unwrap() error { return e.err }
|
||||
|
||||
// StreamRetryable marks a stream-source exit as retryable.
|
||||
func StreamRetryable(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &streamRetryableError{err: err}
|
||||
}
|
||||
|
||||
// StreamFatal marks a stream-source exit as fatal.
|
||||
func StreamFatal(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &streamFatalError{err: err}
|
||||
}
|
||||
|
||||
// IsStreamRetryable reports whether err contains a retryable stream marker.
|
||||
func IsStreamRetryable(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var target *streamRetryableError
|
||||
return errors.As(err, &target)
|
||||
}
|
||||
|
||||
// IsStreamFatal reports whether err contains a fatal stream marker.
|
||||
func IsStreamFatal(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var target *streamFatalError
|
||||
return errors.As(err, &target)
|
||||
}
|
||||
52
sources/stream_errors_test.go
Normal file
52
sources/stream_errors_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package sources
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStreamRetryableWrapsThroughErrorChains(t *testing.T) {
|
||||
base := errors.New("retry me")
|
||||
err := fmt.Errorf("outer: %w", StreamRetryable(base))
|
||||
|
||||
if !IsStreamRetryable(err) {
|
||||
t.Fatalf("IsStreamRetryable() = false, want true")
|
||||
}
|
||||
if IsStreamFatal(err) {
|
||||
t.Fatalf("IsStreamFatal() = true, want false")
|
||||
}
|
||||
if !errors.Is(err, base) {
|
||||
t.Fatalf("errors.Is(err, base) = false, want true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStreamFatalWrapsThroughErrorChains(t *testing.T) {
|
||||
base := errors.New("fatal")
|
||||
err := fmt.Errorf("outer: %w", StreamFatal(base))
|
||||
|
||||
if !IsStreamFatal(err) {
|
||||
t.Fatalf("IsStreamFatal() = false, want true")
|
||||
}
|
||||
if IsStreamRetryable(err) {
|
||||
t.Fatalf("IsStreamRetryable() = true, want false")
|
||||
}
|
||||
if !errors.Is(err, base) {
|
||||
t.Fatalf("errors.Is(err, base) = false, want true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStreamErrorHelpersNil(t *testing.T) {
|
||||
if StreamRetryable(nil) != nil {
|
||||
t.Fatalf("StreamRetryable(nil) != nil")
|
||||
}
|
||||
if StreamFatal(nil) != nil {
|
||||
t.Fatalf("StreamFatal(nil) != nil")
|
||||
}
|
||||
if IsStreamRetryable(nil) {
|
||||
t.Fatalf("IsStreamRetryable(nil) = true")
|
||||
}
|
||||
if IsStreamFatal(nil) {
|
||||
t.Fatalf("IsStreamFatal(nil) = true")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user