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 }