github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/persistence/protocb/provider_state.go (about)

     1  package protocb
     2  
     3  import (
     4  	"log"
     5  	"sync"
     6  
     7  	"github.com/couchbase/gocb"
     8  	"google.golang.org/protobuf/proto"
     9  )
    10  
    11  type cbState struct {
    12  	*Provider
    13  	wg sync.WaitGroup
    14  }
    15  
    16  func (state *cbState) Restart() {
    17  	// wait for any pending writes to complete
    18  	state.wg.Wait()
    19  }
    20  
    21  func (state *cbState) GetEvents(actorName string, eventIndexStart int, eventIndexEnd int, callback func(event interface{})) {
    22  	q := gocb.NewN1qlQuery("SELECT b.* FROM `" + state.bucketName + "` b WHERE meta(b).id >= $1 and meta(b).id <= $2")
    23  	q.Consistency(gocb.RequestPlus)
    24  
    25  	// read all
    26  	if eventIndexEnd == 0 {
    27  		eventIndexEnd = 9999999999
    28  	}
    29  
    30  	var p []interface{}
    31  	p = append(p, formatEventKey(actorName, eventIndexStart))
    32  	p = append(p, formatEventKey(actorName, eventIndexEnd))
    33  
    34  	rows, err := state.bucket.ExecuteN1qlQuery(q, p)
    35  	if err != nil {
    36  		log.Fatalf("Error executing N1ql: %v", err)
    37  	}
    38  	defer func() {
    39  		err := rows.Close()
    40  		if err != nil {
    41  			log.Fatalf("Error closing gocb reader: %v", err)
    42  		}
    43  	}()
    44  
    45  	var row envelope
    46  	i := eventIndexStart
    47  	for rows.Next(&row) {
    48  		e := row.message()
    49  		if row.EventIndex != i {
    50  			log.Printf("%v, Invalid actor state, missing event %v", actorName, i)
    51  			return
    52  		}
    53  		callback(e)
    54  		i++
    55  	}
    56  }
    57  
    58  func (state *cbState) GetSnapshot(actorName string) (snapshot interface{}, eventIndex int, ok bool) {
    59  	q := gocb.NewN1qlQuery("SELECT b.* FROM `" + state.bucketName + "` b WHERE meta(b).id >= $1 and meta(b).id <= $2 order by b.eventIndex desc limit 1")
    60  	q.Consistency(gocb.RequestPlus)
    61  
    62  	var p []interface{}
    63  	p = append(p, formatSnapshotKey(actorName, 0))
    64  	p = append(p, formatSnapshotKey(actorName, 9999999999))
    65  
    66  	rows, err := state.bucket.ExecuteN1qlQuery(q, p)
    67  	if err != nil {
    68  		log.Fatalf("Error executing N1ql: %v", err)
    69  	}
    70  	defer func() {
    71  		err := rows.Close()
    72  		if err != nil {
    73  			log.Fatalf("Error closing gocb reader: %v", err)
    74  		}
    75  	}()
    76  
    77  	var row envelope
    78  	if rows.Next(&row) {
    79  		return row.message(), row.EventIndex, true
    80  	}
    81  	return nil, 0, false
    82  }
    83  
    84  func (provider *Provider) GetSnapshotInterval() int {
    85  	return provider.snapshotInterval
    86  }
    87  
    88  func (state *cbState) PersistEvent(actorName string, eventIndex int, event proto.Message) {
    89  	key := formatEventKey(actorName, eventIndex)
    90  	envelope := newEnvelope(event, "event", eventIndex)
    91  	state.persistEnvelope(key, envelope)
    92  }
    93  
    94  func (state *cbState) DeleteEvents(actorName string, inclusiveToIndex int) {
    95  	panic("implement me")
    96  }
    97  
    98  func (state *cbState) PersistSnapshot(actorName string, eventIndex int, snapshot proto.Message) {
    99  	key := formatSnapshotKey(actorName, eventIndex)
   100  	envelope := newEnvelope(snapshot, "snapshot", eventIndex)
   101  	state.persistEnvelope(key, envelope)
   102  }
   103  
   104  func (state *cbState) DeleteSnapshots(actorName string, inclusiveToIndex int) {
   105  	panic("implement me")
   106  }
   107  
   108  func (state *cbState) persistEnvelope(key string, envelope *envelope) {
   109  	state.wg.Add(1)
   110  	persist := func() {
   111  		_, err := state.bucket.Insert(key, envelope, 0)
   112  		if err != nil {
   113  			log.Fatal(err)
   114  		}
   115  		state.wg.Done()
   116  	}
   117  	if state.async {
   118  		//	state.writer.Tell(&write{fun: persist})
   119  	} else {
   120  		persist()
   121  	}
   122  }