github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/appparts/impl_app.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  	"sync"
    11  
    12  	"github.com/voedger/voedger/pkg/appdef"
    13  	"github.com/voedger/voedger/pkg/appparts/internal/pool"
    14  	"github.com/voedger/voedger/pkg/iextengine"
    15  	"github.com/voedger/voedger/pkg/istructs"
    16  	"github.com/voedger/voedger/pkg/pipeline"
    17  )
    18  
    19  // engine placeholder
    20  type engines struct {
    21  	byKind [appdef.ExtensionEngineKind_Count]iextengine.IExtensionEngine
    22  	pool   *pool.Pool[*engines]
    23  }
    24  
    25  func newEngines() *engines {
    26  	return &engines{}
    27  }
    28  
    29  func (e *engines) release() {
    30  	if p := e.pool; p != nil {
    31  		e.pool = nil
    32  		p.Release(e)
    33  	}
    34  }
    35  
    36  type app struct {
    37  	apps       *apps
    38  	name       istructs.AppQName
    39  	partsCount istructs.NumAppPartitions
    40  	def        appdef.IAppDef
    41  	structs    istructs.IAppStructs
    42  	engines    [ProcessorKind_Count]*pool.Pool[*engines]
    43  	// no locks need. Owned apps structure will locks access to this structure
    44  	parts map[istructs.PartitionID]*partition
    45  }
    46  
    47  func newApplication(apps *apps, name istructs.AppQName, partsCount istructs.NumAppPartitions) *app {
    48  	return &app{
    49  		apps:       apps,
    50  		name:       name,
    51  		partsCount: partsCount,
    52  		parts:      map[istructs.PartitionID]*partition{},
    53  	}
    54  }
    55  
    56  func (a *app) deploy(def appdef.IAppDef, structs istructs.IAppStructs, numEngines [ProcessorKind_Count]int) {
    57  	a.def = def
    58  	a.structs = structs
    59  
    60  	eef := a.apps.extEngineFactories
    61  
    62  	ctx := context.Background()
    63  	for k, cnt := range numEngines {
    64  		extEngines := make([][]iextengine.IExtensionEngine, appdef.ExtensionEngineKind_Count)
    65  
    66  		for ek, ef := range eef {
    67  			// TODO: prepare []iextengine.ExtensionPackage from IAppDef
    68  			// TODO: should pass iextengine.ExtEngineConfig from somewhere (Provide?)
    69  			ee, err := ef.New(ctx, a.name, []iextengine.ExtensionPackage{}, &iextengine.DefaultExtEngineConfig, cnt)
    70  			if err != nil {
    71  				panic(err)
    72  			}
    73  			extEngines[ek] = ee
    74  		}
    75  
    76  		ee := make([]*engines, cnt)
    77  		for i := 0; i < cnt; i++ {
    78  			ee[i] = newEngines()
    79  			for ek := range eef {
    80  				ee[i].byKind[ek] = extEngines[ek][i]
    81  			}
    82  		}
    83  		a.engines[k] = pool.New(ee)
    84  	}
    85  }
    86  
    87  type partition struct {
    88  	app            *app
    89  	id             istructs.PartitionID
    90  	syncActualizer pipeline.ISyncOperator
    91  }
    92  
    93  func newPartition(app *app, id istructs.PartitionID) *partition {
    94  	part := &partition{
    95  		app:            app,
    96  		id:             id,
    97  		syncActualizer: app.apps.syncActualizerFactory(app.structs, id),
    98  	}
    99  	return part
   100  }
   101  
   102  func (p *partition) borrow(proc ProcessorKind) (*partitionRT, error) {
   103  	b := newPartitionRT(p)
   104  
   105  	if err := b.init(proc); err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	return b, nil
   110  }
   111  
   112  type partitionRT struct {
   113  	part       *partition
   114  	appDef     appdef.IAppDef
   115  	appStructs istructs.IAppStructs
   116  	borrowed   *engines
   117  }
   118  
   119  var partionRTPool = sync.Pool{
   120  	New: func() interface{} {
   121  		return &partitionRT{}
   122  	},
   123  }
   124  
   125  func newPartitionRT(part *partition) *partitionRT {
   126  	rt := partionRTPool.Get().(*partitionRT)
   127  
   128  	rt.part = part
   129  	rt.appDef = part.app.def
   130  	rt.appStructs = part.app.structs
   131  
   132  	return rt
   133  }
   134  
   135  func (rt *partitionRT) App() istructs.AppQName { return rt.part.app.name }
   136  
   137  func (rt *partitionRT) AppStructs() istructs.IAppStructs { return rt.appStructs }
   138  
   139  func (rt *partitionRT) DoSyncActualizer(ctx context.Context, work interface{}) error {
   140  	return rt.part.syncActualizer.DoSync(ctx, work)
   141  }
   142  
   143  func (rt *partitionRT) ID() istructs.PartitionID { return rt.part.id }
   144  
   145  func (rt *partitionRT) Invoke(ctx context.Context, name appdef.QName, state istructs.IState, intents istructs.IIntents) error {
   146  	e := rt.appDef.Extension(name)
   147  	if e == nil {
   148  		return errUndefinedExtension(name)
   149  	}
   150  
   151  	extName := rt.appDef.FullQName(name)
   152  	if extName == appdef.NullFullQName {
   153  		return errUndefinedExtension(name)
   154  	}
   155  	io := iextengine.NewExtensionIO(rt.appDef, state, intents)
   156  
   157  	return rt.borrowed.byKind[e.Engine()].Invoke(ctx, extName, io)
   158  }
   159  
   160  func (rt *partitionRT) Release() {
   161  	if e := rt.borrowed; e != nil {
   162  		rt.borrowed = nil
   163  		e.release()
   164  	}
   165  	partionRTPool.Put(rt)
   166  }
   167  
   168  // Initialize partition RT structures for use
   169  func (rt *partitionRT) init(proc ProcessorKind) error {
   170  	pool := rt.part.app.engines[proc]
   171  	engine, err := pool.Borrow() // will be released in (*engine).release()
   172  	if err != nil {
   173  		return errNotAvailableEngines[proc]
   174  	}
   175  	engine.pool = pool
   176  	rt.borrowed = engine
   177  	return nil
   178  }