|
| 1 | +package flyt |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "time" |
| 6 | +) |
| 7 | + |
| 8 | +// NodeBuilder provides a fluent interface for creating and configuring nodes. |
| 9 | +// It implements the Node interface while also providing chainable methods |
| 10 | +// for configuration. This allows both styles: |
| 11 | +// - Traditional: flyt.NewNode(WithExecFunc(...), WithMaxRetries(3)) |
| 12 | +// - Builder: flyt.NewNode().WithExecFunc(...).WithMaxRetries(3) |
| 13 | +type NodeBuilder struct { |
| 14 | + *CustomNode |
| 15 | +} |
| 16 | + |
| 17 | +// Prep implements Node.Prep by delegating to the embedded CustomNode |
| 18 | +func (b *NodeBuilder) Prep(ctx context.Context, shared *SharedStore) (any, error) { |
| 19 | + return b.CustomNode.Prep(ctx, shared) |
| 20 | +} |
| 21 | + |
| 22 | +// Exec implements Node.Exec by delegating to the embedded CustomNode |
| 23 | +func (b *NodeBuilder) Exec(ctx context.Context, prepResult any) (any, error) { |
| 24 | + return b.CustomNode.Exec(ctx, prepResult) |
| 25 | +} |
| 26 | + |
| 27 | +// Post implements Node.Post by delegating to the embedded CustomNode |
| 28 | +func (b *NodeBuilder) Post(ctx context.Context, shared *SharedStore, prepResult, execResult any) (Action, error) { |
| 29 | + return b.CustomNode.Post(ctx, shared, prepResult, execResult) |
| 30 | +} |
| 31 | + |
| 32 | +// ExecFallback implements FallbackNode.ExecFallback by delegating to the embedded CustomNode |
| 33 | +func (b *NodeBuilder) ExecFallback(prepResult any, err error) (any, error) { |
| 34 | + return b.CustomNode.ExecFallback(prepResult, err) |
| 35 | +} |
| 36 | + |
| 37 | +// GetMaxRetries implements RetryableNode.GetMaxRetries by delegating to the embedded BaseNode |
| 38 | +func (b *NodeBuilder) GetMaxRetries() int { |
| 39 | + return b.CustomNode.BaseNode.GetMaxRetries() |
| 40 | +} |
| 41 | + |
| 42 | +// GetWait implements RetryableNode.GetWait by delegating to the embedded BaseNode |
| 43 | +func (b *NodeBuilder) GetWait() time.Duration { |
| 44 | + return b.CustomNode.BaseNode.GetWait() |
| 45 | +} |
| 46 | + |
| 47 | +// WithMaxRetries sets the maximum number of retries for the node's Exec phase. |
| 48 | +// Returns the builder for method chaining. |
| 49 | +func (b *NodeBuilder) WithMaxRetries(retries int) *NodeBuilder { |
| 50 | + WithMaxRetries(retries)(b.CustomNode.BaseNode) |
| 51 | + return b |
| 52 | +} |
| 53 | + |
| 54 | +// WithWait sets the wait duration between retries. |
| 55 | +// Returns the builder for method chaining. |
| 56 | +func (b *NodeBuilder) WithWait(wait time.Duration) *NodeBuilder { |
| 57 | + WithWait(wait)(b.CustomNode.BaseNode) |
| 58 | + return b |
| 59 | +} |
| 60 | + |
| 61 | +// WithPrepFunc sets a custom Prep implementation using Result types. |
| 62 | +// Returns the builder for method chaining. |
| 63 | +func (b *NodeBuilder) WithPrepFunc(fn func(context.Context, *SharedStore) (Result, error)) *NodeBuilder { |
| 64 | + b.CustomNode.prepFunc = fn |
| 65 | + return b |
| 66 | +} |
| 67 | + |
| 68 | +// WithExecFunc sets a custom Exec implementation using Result types. |
| 69 | +// Returns the builder for method chaining. |
| 70 | +func (b *NodeBuilder) WithExecFunc(fn func(context.Context, Result) (Result, error)) *NodeBuilder { |
| 71 | + b.CustomNode.execFunc = fn |
| 72 | + return b |
| 73 | +} |
| 74 | + |
| 75 | +// WithPostFunc sets a custom Post implementation using Result types. |
| 76 | +// Returns the builder for method chaining. |
| 77 | +func (b *NodeBuilder) WithPostFunc(fn func(context.Context, *SharedStore, Result, Result) (Action, error)) *NodeBuilder { |
| 78 | + b.CustomNode.postFunc = fn |
| 79 | + return b |
| 80 | +} |
| 81 | + |
| 82 | +// WithExecFallbackFunc sets a custom ExecFallback implementation. |
| 83 | +// Returns the builder for method chaining. |
| 84 | +func (b *NodeBuilder) WithExecFallbackFunc(fn func(any, error) (any, error)) *NodeBuilder { |
| 85 | + b.CustomNode.execFallbackFunc = fn |
| 86 | + return b |
| 87 | +} |
| 88 | + |
| 89 | +// WithPrepFuncAny sets a custom Prep implementation using any types. |
| 90 | +// Returns the builder for method chaining. |
| 91 | +func (b *NodeBuilder) WithPrepFuncAny(fn func(context.Context, *SharedStore) (any, error)) *NodeBuilder { |
| 92 | + b.CustomNode.prepFunc = func(ctx context.Context, shared *SharedStore) (Result, error) { |
| 93 | + val, err := fn(ctx, shared) |
| 94 | + if err != nil { |
| 95 | + return Result{}, err |
| 96 | + } |
| 97 | + return NewResult(val), nil |
| 98 | + } |
| 99 | + return b |
| 100 | +} |
| 101 | + |
| 102 | +// WithExecFuncAny sets a custom Exec implementation using any types. |
| 103 | +// Returns the builder for method chaining. |
| 104 | +func (b *NodeBuilder) WithExecFuncAny(fn func(context.Context, any) (any, error)) *NodeBuilder { |
| 105 | + b.CustomNode.execFunc = func(ctx context.Context, prepResult Result) (Result, error) { |
| 106 | + val, err := fn(ctx, prepResult.Value()) |
| 107 | + if err != nil { |
| 108 | + return Result{}, err |
| 109 | + } |
| 110 | + return NewResult(val), nil |
| 111 | + } |
| 112 | + return b |
| 113 | +} |
| 114 | + |
| 115 | +// WithPostFuncAny sets a custom Post implementation using any types. |
| 116 | +// Returns the builder for method chaining. |
| 117 | +func (b *NodeBuilder) WithPostFuncAny(fn func(context.Context, *SharedStore, any, any) (Action, error)) *NodeBuilder { |
| 118 | + b.CustomNode.postFunc = func(ctx context.Context, shared *SharedStore, prepResult, execResult Result) (Action, error) { |
| 119 | + return fn(ctx, shared, prepResult.Value(), execResult.Value()) |
| 120 | + } |
| 121 | + return b |
| 122 | +} |
| 123 | + |
| 124 | +// Build returns the configured Node. |
| 125 | +// This method is optional as NodeBuilder already implements Node, |
| 126 | +// but it provides explicit intent when ending the builder chain. |
| 127 | +func (b *NodeBuilder) Build() Node { |
| 128 | + return b |
| 129 | +} |
0 commit comments