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 }