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

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package statedb
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/cilium/stream"
    10  )
    11  
    12  // Observable creates an observable from the given table for observing the changes
    13  // to the table as a stream of events.
    14  //
    15  // For high-churn tables it's advisable to apply rate-limiting to the stream to
    16  // decrease overhead (stream.Throttle).
    17  func Observable[Obj any](db *DB, table Table[Obj]) stream.Observable[Change[Obj]] {
    18  	return &observable[Obj]{db, table}
    19  }
    20  
    21  type observable[Obj any] struct {
    22  	db    *DB
    23  	table Table[Obj]
    24  }
    25  
    26  func (to *observable[Obj]) Observe(ctx context.Context, next func(Change[Obj]), complete func(error)) {
    27  	go func() {
    28  		txn := to.db.WriteTxn(to.table)
    29  		iter, err := to.table.Changes(txn)
    30  		txn.Commit()
    31  		if err != nil {
    32  			complete(err)
    33  			return
    34  		}
    35  		defer complete(nil)
    36  
    37  		for {
    38  			changes, watch := iter.Next(to.db.ReadTxn())
    39  			for change := range changes {
    40  				if ctx.Err() != nil {
    41  					break
    42  				}
    43  				next(change)
    44  			}
    45  			select {
    46  			case <-ctx.Done():
    47  				return
    48  			case <-watch:
    49  			}
    50  		}
    51  	}()
    52  }