github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/state/impl_view_records_storage.go (about) 1 /* 2 * Copyright (c) 2022-present unTill Pro, Ltd. 3 */ 4 5 package state 6 7 import ( 8 "context" 9 "errors" 10 11 "github.com/voedger/voedger/pkg/appdef" 12 "github.com/voedger/voedger/pkg/istructs" 13 "github.com/voedger/voedger/pkg/istructsmem" 14 ) 15 16 type viewRecordsStorage struct { 17 ctx context.Context 18 appStructsFunc AppStructsFunc 19 wsidFunc WSIDFunc 20 n10nFunc N10nFunc 21 wsTypeVailidator wsTypeVailidator 22 } 23 24 func newViewRecordsStorage(ctx context.Context, appStructsFunc AppStructsFunc, wsidFunc WSIDFunc, n10nFunc N10nFunc) *viewRecordsStorage { 25 return &viewRecordsStorage{ 26 ctx: ctx, 27 appStructsFunc: appStructsFunc, 28 wsidFunc: wsidFunc, 29 n10nFunc: n10nFunc, 30 wsTypeVailidator: newWsTypeValidator(appStructsFunc), 31 } 32 } 33 34 func (s *viewRecordsStorage) NewKeyBuilder(entity appdef.QName, _ istructs.IStateKeyBuilder) (newKeyBuilder istructs.IStateKeyBuilder) { 35 return &viewKeyBuilder{ 36 IKeyBuilder: s.appStructsFunc().ViewRecords().KeyBuilder(entity), 37 view: entity, 38 wsid: s.wsidFunc(), 39 } 40 } 41 42 func (s *viewRecordsStorage) Get(key istructs.IStateKeyBuilder) (value istructs.IStateValue, err error) { 43 k := key.(*viewKeyBuilder) 44 err = s.wsTypeVailidator.validate(k.wsid, k.view) 45 if err != nil { 46 return nil, err 47 } 48 v, err := s.appStructsFunc().ViewRecords().Get(k.wsid, k.IKeyBuilder) 49 if err != nil { 50 if errors.Is(err, istructsmem.ErrRecordNotFound) { 51 return nil, nil 52 } 53 return nil, err 54 } 55 if v == nil { 56 return nil, nil 57 } 58 return &viewValue{ 59 value: v, 60 }, nil 61 } 62 63 func (s *viewRecordsStorage) GetBatch(items []GetBatchItem) (err error) { 64 wsidToItemIdx := make(map[istructs.WSID][]int) 65 batches := make(map[istructs.WSID][]istructs.ViewRecordGetBatchItem) 66 for itemIdx, item := range items { 67 k := item.key.(*viewKeyBuilder) 68 if err = s.wsTypeVailidator.validate(k.wsid, k.view); err != nil { 69 return err 70 } 71 wsidToItemIdx[k.wsid] = append(wsidToItemIdx[k.wsid], itemIdx) 72 batches[k.wsid] = append(batches[k.wsid], istructs.ViewRecordGetBatchItem{Key: k.IKeyBuilder}) 73 } 74 for wsid, batch := range batches { 75 err = s.appStructsFunc().ViewRecords().GetBatch(wsid, batch) 76 if err != nil { 77 return 78 } 79 for i, batchItem := range batch { 80 itemIndex := wsidToItemIdx[wsid][i] 81 if !batchItem.Ok { 82 continue 83 } 84 items[itemIndex].value = &viewValue{ 85 value: batchItem.Value, 86 } 87 } 88 } 89 return err 90 } 91 func (s *viewRecordsStorage) Read(kb istructs.IStateKeyBuilder, callback istructs.ValueCallback) (err error) { 92 cb := func(k istructs.IKey, v istructs.IValue) (err error) { 93 return callback(k, &viewValue{ 94 value: v, 95 }) 96 } 97 k := kb.(*viewKeyBuilder) 98 if err = s.wsTypeVailidator.validate(k.wsid, k.view); err != nil { 99 return err 100 } 101 return s.appStructsFunc().ViewRecords().Read(s.ctx, k.wsid, k.IKeyBuilder, cb) 102 } 103 func (s *viewRecordsStorage) Validate([]ApplyBatchItem) (err error) { return err } 104 func (s *viewRecordsStorage) ApplyBatch(items []ApplyBatchItem) (err error) { 105 batches := make(map[istructs.WSID][]istructs.ViewKV) 106 nn := make(map[n10n]istructs.Offset) 107 for _, item := range items { 108 k := item.key.(*viewKeyBuilder) 109 v := item.value.(*viewValueBuilder) 110 batches[k.wsid] = append(batches[k.wsid], istructs.ViewKV{Key: k.IKeyBuilder, Value: v.IValueBuilder}) 111 if nn[n10n{wsid: k.wsid, view: k.view}] < v.offset { 112 nn[n10n{wsid: k.wsid, view: k.view}] = v.offset 113 } 114 } 115 var nullWsidBatch []istructs.ViewKV 116 for wsid, batch := range batches { 117 if wsid == istructs.NullWSID { // Actualizer offsets must be updated in the last order 118 nullWsidBatch = batch 119 continue 120 } 121 err = s.appStructsFunc().ViewRecords().PutBatch(wsid, batch) 122 if err != nil { 123 return err 124 } 125 } 126 if len(nullWsidBatch) > 0 { 127 err = s.appStructsFunc().ViewRecords().PutBatch(istructs.NullWSID, nullWsidBatch) 128 if err != nil { 129 return err 130 } 131 } 132 for n, newOffset := range nn { 133 s.n10nFunc(n.view, n.wsid, newOffset) 134 } 135 return err 136 } 137 func (s *viewRecordsStorage) ProvideValueBuilder(kb istructs.IStateKeyBuilder, _ istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 138 k := kb.(*viewKeyBuilder) 139 if err := s.wsTypeVailidator.validate(k.wsid, k.view); err != nil { 140 return nil, err 141 } 142 return &viewValueBuilder{ 143 IValueBuilder: s.appStructsFunc().ViewRecords().NewValueBuilder(k.view), 144 offset: istructs.NullOffset, 145 entity: kb.Entity(), 146 }, nil 147 } 148 func (s *viewRecordsStorage) ProvideValueBuilderForUpdate(kb istructs.IStateKeyBuilder, existingValue istructs.IStateValue, _ istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 149 k := kb.(*viewKeyBuilder) 150 if err := s.wsTypeVailidator.validate(k.wsid, k.view); err != nil { 151 return nil, err 152 } 153 return &viewValueBuilder{ 154 IValueBuilder: s.appStructsFunc().ViewRecords().UpdateValueBuilder(kb.(*viewKeyBuilder).view, existingValue.(*viewValue).value), 155 offset: istructs.NullOffset, 156 entity: kb.Entity(), 157 }, nil 158 }