go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/incrutil/always.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package incrutil
     9  
    10  import (
    11  	"fmt"
    12  
    13  	"github.com/wcharczuk/go-incr"
    14  )
    15  
    16  // Always yields an incremental that is always stale.
    17  //
    18  // The way to use this effectively is to place this node above a tree of
    19  // nodes that should always be recomputed, but specifically you'll likely
    20  // want to pair this with a cutoff _below_ the immediate child of the always node
    21  // such that you don't just always recompute an entire subgraph.
    22  func Always[A any](scope incr.Scope) AlwaysIncr[A] {
    23  	return incr.WithinScope(scope, &alwaysIncr[A]{
    24  		n: incr.NewNode("always"),
    25  	})
    26  }
    27  
    28  // AlwaysIncr is an incremental that implements the always interface.
    29  type AlwaysIncr[A any] interface {
    30  	incr.AlwaysIncr[A]
    31  	ISetInput
    32  	IRemoveInput
    33  	IInputs
    34  }
    35  
    36  type alwaysIncr[A any] struct {
    37  	n     *incr.Node
    38  	input incr.Incr[A]
    39  }
    40  
    41  func (a *alwaysIncr[A]) Parents() []incr.INode {
    42  	if a.input != nil {
    43  		return []incr.INode{a.input}
    44  	}
    45  	return nil
    46  }
    47  
    48  func (a *alwaysIncr[A]) SetInput(name string, i incr.INode, _ bool) error {
    49  	typed, ok := i.(incr.Incr[A])
    50  	if !ok || typed == nil {
    51  		return fmt.Errorf("invalid untyped input for map node %T", i)
    52  	}
    53  	a.input = typed
    54  	LinkNodes(a, i)
    55  	return nil
    56  }
    57  
    58  func (a *alwaysIncr[A]) RemoveInput(name string) error {
    59  	if a.input != nil {
    60  		UnlinkNodes(a, a.input)
    61  		a.input = nil
    62  		return nil
    63  	}
    64  	return fmt.Errorf("remove input; input is unset")
    65  }
    66  
    67  func (a *alwaysIncr[A]) Inputs() map[string]incr.INode {
    68  	if a.input != nil {
    69  		return map[string]incr.INode{
    70  			"input": a.input,
    71  		}
    72  	}
    73  	return nil
    74  }
    75  
    76  func (a *alwaysIncr[A]) Always() {}
    77  
    78  func (a *alwaysIncr[A]) Value() A {
    79  	return a.input.Value()
    80  }
    81  
    82  func (a *alwaysIncr[A]) Node() *incr.Node { return a.n }
    83  
    84  func (a *alwaysIncr[A]) String() string {
    85  	return a.n.String()
    86  }