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

     1  /*
     2   * Copyright (c) 2021-present Sigma-Soft, Ltd.
     3   * @author: Nikolay Nikitin
     4   */
     5  
     6  package appparts
     7  
     8  import (
     9  	"context"
    10  	"errors"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/voedger/voedger/pkg/appdef"
    15  	"github.com/voedger/voedger/pkg/iextengine"
    16  	"github.com/voedger/voedger/pkg/istructs"
    17  	coreutils "github.com/voedger/voedger/pkg/utils"
    18  )
    19  
    20  type apps struct {
    21  	structs               istructs.IAppStructsProvider
    22  	syncActualizerFactory SyncActualizerFactory
    23  	extEngineFactories    iextengine.ExtensionEngineFactories
    24  	apps                  map[istructs.AppQName]*app
    25  	mx                    sync.RWMutex
    26  }
    27  
    28  func newAppPartitions(asp istructs.IAppStructsProvider, saf SyncActualizerFactory, eef iextengine.ExtensionEngineFactories) (ap IAppPartitions, cleanup func(), err error) {
    29  	a := &apps{
    30  		structs:               asp,
    31  		syncActualizerFactory: saf,
    32  		extEngineFactories:    eef,
    33  		apps:                  map[istructs.AppQName]*app{},
    34  		mx:                    sync.RWMutex{},
    35  	}
    36  	return a, func() {}, err
    37  }
    38  
    39  func (aps *apps) DeployApp(name istructs.AppQName, def appdef.IAppDef, partsCount istructs.NumAppPartitions, engines [ProcessorKind_Count]int) {
    40  	aps.mx.Lock()
    41  	defer aps.mx.Unlock()
    42  
    43  	if _, ok := aps.apps[name]; ok {
    44  		panic(errAppCannotBeRedeployed(name))
    45  	}
    46  
    47  	a := newApplication(aps, name, partsCount)
    48  	aps.apps[name] = a
    49  
    50  	appStructs, err := aps.structs.AppStructsByDef(name, def)
    51  	if err != nil {
    52  		panic(err)
    53  	}
    54  
    55  	a.deploy(def, appStructs, engines)
    56  }
    57  
    58  func (aps *apps) DeployAppPartitions(appName istructs.AppQName, partIDs []istructs.PartitionID) {
    59  	aps.mx.Lock()
    60  	defer aps.mx.Unlock()
    61  
    62  	a, ok := aps.apps[appName]
    63  	if !ok {
    64  		panic(errAppNotFound(appName))
    65  	}
    66  
    67  	for _, id := range partIDs {
    68  		p := newPartition(a, id)
    69  		a.parts[id] = p
    70  	}
    71  }
    72  
    73  func (aps *apps) AppDef(appName istructs.AppQName) (appdef.IAppDef, error) {
    74  	aps.mx.Lock()
    75  	defer aps.mx.Unlock()
    76  
    77  	app, ok := aps.apps[appName]
    78  	if !ok {
    79  		return nil, errAppNotFound(appName)
    80  	}
    81  	return app.def, nil
    82  }
    83  
    84  // Returns _total_ application partitions count.
    85  //
    86  // This is a configuration value for the application, independent of how many sections are currently deployed.
    87  func (aps *apps) AppPartsCount(appName istructs.AppQName) (istructs.NumAppPartitions, error) {
    88  	aps.mx.Lock()
    89  	defer aps.mx.Unlock()
    90  
    91  	app, ok := aps.apps[appName]
    92  	if !ok {
    93  		return 0, errAppNotFound(appName)
    94  	}
    95  	return app.partsCount, nil
    96  }
    97  
    98  func (aps *apps) Borrow(appName istructs.AppQName, partID istructs.PartitionID, proc ProcessorKind) (IAppPartition, error) {
    99  	aps.mx.RLock()
   100  	defer aps.mx.RUnlock()
   101  
   102  	app, ok := aps.apps[appName]
   103  	if !ok {
   104  		return nil, errAppNotFound(appName)
   105  	}
   106  
   107  	part, ok := app.parts[partID]
   108  	if !ok {
   109  		return nil, errPartitionNotFound(appName, partID)
   110  	}
   111  
   112  	borrowed, err := part.borrow(proc)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	return borrowed, nil
   118  }
   119  
   120  func (aps *apps) AppWorkspacePartitionID(appName istructs.AppQName, ws istructs.WSID) (istructs.PartitionID, error) {
   121  	pc, err := aps.AppPartsCount(appName)
   122  	if err != nil {
   123  		return 0, err
   124  	}
   125  	return coreutils.AppPartitionID(ws, pc), nil
   126  }
   127  
   128  func (aps *apps) WaitForBorrow(ctx context.Context, appName istructs.AppQName, partID istructs.PartitionID, proc ProcessorKind) (IAppPartition, error) {
   129  	for ctx.Err() == nil {
   130  		ap, err := aps.Borrow(appName, partID, proc)
   131  		if err == nil {
   132  			return ap, nil
   133  		}
   134  		if errors.Is(err, ErrNotAvailableEngines) {
   135  			time.Sleep(AppPartitionBorrowRetryDelay)
   136  			continue
   137  		}
   138  		return nil, err
   139  	}
   140  	return nil, ctx.Err()
   141  }