github.com/cilium/statedb@v0.3.2/reconciler/index.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package reconciler
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/cilium/statedb"
    10  	"github.com/cilium/statedb/index"
    11  )
    12  
    13  // NewStatusIndex creates a status index for a table of reconcilable objects.
    14  // This is optional and should be only used when there is a need to often check that all
    15  // objects are fully reconciled that outweighs the cost of maintaining a status index.
    16  func NewStatusIndex[Obj any](getObjectStatus func(Obj) Status) statedb.Index[Obj, StatusKind] {
    17  	return statedb.Index[Obj, StatusKind]{
    18  		Name: "status",
    19  		FromObject: func(obj Obj) index.KeySet {
    20  			return index.NewKeySet(getObjectStatus(obj).Kind.Key())
    21  		},
    22  		FromKey: StatusKind.Key,
    23  		Unique:  false,
    24  	}
    25  }
    26  
    27  // WaitForReconciliation blocks until all objects have been reconciled or the context
    28  // has cancelled.
    29  func WaitForReconciliation[Obj any](ctx context.Context, db *statedb.DB, table statedb.Table[Obj], statusIndex statedb.Index[Obj, StatusKind]) error {
    30  	for {
    31  		txn := db.ReadTxn()
    32  
    33  		// See if there are any pending or error'd objects.
    34  		_, _, watchPending, okPending := table.GetWatch(txn, statusIndex.Query(StatusKindPending))
    35  		_, _, watchError, okError := table.GetWatch(txn, statusIndex.Query(StatusKindError))
    36  		if !okPending && !okError {
    37  			return nil
    38  		}
    39  
    40  		// Wait for updates before checking again.
    41  		select {
    42  		case <-ctx.Done():
    43  			return ctx.Err()
    44  		case <-watchPending:
    45  		case <-watchError:
    46  		}
    47  	}
    48  }