github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/state/impl_bundled_host_state.go (about)

     1  /*
     2   * Copyright (c) 2022-present unTill Pro, Ltd.
     3   */
     4  
     5  package state
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/voedger/voedger/pkg/appdef"
    11  	"github.com/voedger/voedger/pkg/istructs"
    12  )
    13  
    14  type bundledHostState struct {
    15  	*hostState
    16  	bundles      map[appdef.QName]bundle
    17  	bundlesLimit int
    18  }
    19  
    20  func (s *bundledHostState) CanExist(key istructs.IStateKeyBuilder) (stateValue istructs.IStateValue, ok bool, err error) {
    21  	bundledStorage, ok := s.bundles[key.Storage()]
    22  	if ok {
    23  		// can be already in a bundles
    24  		if value, ok := bundledStorage.get(key); ok {
    25  			// TODO later: For the optimization purposes, maybe would be wise to use e.g. AsValue()
    26  			// instead of BuildValue()
    27  			return value.value.BuildValue(), true, nil
    28  		}
    29  	}
    30  
    31  	return s.hostState.CanExist(key)
    32  }
    33  func (s *bundledHostState) CanExistAll(keys []istructs.IStateKeyBuilder, callback istructs.StateValueCallback) (err error) {
    34  	for _, k := range keys {
    35  		value, ok, err := s.CanExist(k)
    36  		if err != nil {
    37  			return err
    38  		}
    39  		if err = callback(k, value, ok); err != nil {
    40  			return err
    41  		}
    42  	}
    43  	return
    44  }
    45  func (s *bundledHostState) MustExist(key istructs.IStateKeyBuilder) (value istructs.IStateValue, err error) {
    46  	value, ok, err := s.CanExist(key)
    47  	if err != nil {
    48  		return
    49  	}
    50  	if !ok {
    51  		return nil, s.err(key, ErrNotExists)
    52  	}
    53  	return
    54  }
    55  func (s *bundledHostState) MustExistAll(keys []istructs.IStateKeyBuilder, callback istructs.StateValueCallback) (err error) {
    56  	values := make([]istructs.IStateValue, len(keys))
    57  	for i, k := range keys {
    58  		value, err := s.MustExist(k)
    59  		if err != nil {
    60  			return err
    61  		}
    62  		values[i] = value
    63  	}
    64  	for i, value := range values {
    65  		if err = callback(keys[i], value, true); err != nil {
    66  			return err
    67  		}
    68  	}
    69  	return
    70  }
    71  func (s *bundledHostState) MustNotExist(key istructs.IStateKeyBuilder) (err error) {
    72  	_, ok, err := s.CanExist(key)
    73  	if err != nil {
    74  		return
    75  	}
    76  	if ok {
    77  		return s.err(key, ErrExists)
    78  	}
    79  	return
    80  }
    81  func (s *bundledHostState) MustNotExistAll(keys []istructs.IStateKeyBuilder) (err error) {
    82  	for _, k := range keys {
    83  		err = s.MustNotExist(k)
    84  		if err != nil {
    85  			return
    86  		}
    87  	}
    88  	return
    89  }
    90  func (s *bundledHostState) Read(key istructs.IStateKeyBuilder, callback istructs.ValueCallback) (err error) {
    91  	bundledStorage, ok := s.bundles[key.Storage()]
    92  	if ok {
    93  		if bundledStorage.containsKeysForSameEntity(key) {
    94  			err = s.FlushBundles()
    95  			if err != nil {
    96  				return fmt.Errorf("unable to flush on read %+v: %w", key, err)
    97  			}
    98  		}
    99  	}
   100  	return s.hostState.Read(key, callback)
   101  }
   102  func (s *bundledHostState) ApplyIntents() (readyToFlushBundle bool, err error) {
   103  	defer func() {
   104  		for sid := range s.intents {
   105  			s.intents[sid] = s.intents[sid][0:0]
   106  		}
   107  	}()
   108  	for sid, intents := range s.intents {
   109  		if len(intents) == 0 {
   110  			continue
   111  		}
   112  
   113  		err = s.withApplyBatch[sid].Validate(intents)
   114  		if err != nil {
   115  			return false, err
   116  		}
   117  
   118  		for _, item := range intents {
   119  			s.bundles[sid].put(item.key, item)
   120  		}
   121  	}
   122  	bundles := 0
   123  	for _, b := range s.bundles {
   124  		bundles += b.size()
   125  	}
   126  	return bundles >= s.bundlesLimit, nil
   127  }
   128  func (s *bundledHostState) FlushBundles() (err error) {
   129  	defer func() {
   130  		for _, b := range s.bundles {
   131  			b.clear()
   132  		}
   133  	}()
   134  	for sid, b := range s.bundles {
   135  		err = s.withApplyBatch[sid].ApplyBatch(b.values())
   136  		if err != nil {
   137  			return err
   138  		}
   139  	}
   140  	return
   141  }
   142  func (s *bundledHostState) addStorage(storageName appdef.QName, storage IStateStorage, ops int) {
   143  	s.hostState.addStorage(storageName, storage, ops)
   144  	if supports(ops, S_UPDATE) || supports(ops, S_INSERT) {
   145  		s.bundles[storageName] = newBundle()
   146  	}
   147  }