// package kmonolit -- модульный монолит на основе ядра. package kmonolit import ( "gitp78su.ipnodns.ru/svi/kern/v4/d0" "gitp78su.ipnodns.ru/svi/kern/v4/d1" "gitp78su.ipnodns.ru/svi/kern/v4/d2" "gitp78su.ipnodns.ru/svi/kern/v4/d3/mod_ent" "gitp78su.ipnodns.ru/svi/kern/v4/d3/mod_spec" ) // LModMonolit -- объект модульного монолита. type LModMonolit struct { owner *d0.LOwner kCtx *d2.KernCtx lCtx *d1.LocalCtx log *d1.LogBuf name mod_ent.AModuleName isLocal *d0.LBool isWork *d0.MSafeBool isEnd *d0.MSafeBool dict map[mod_ent.AModuleName]mod_spec.IKernelModule // Словарь модулей монолита } var ( mon *LModMonolit block = d0.MutSafeMutex() ) var ( owner = d0.LetOwner(0, "owner_test") txtIsLocal = d0.LetTxt(owner, "isLocal") ) // LetModMonolit -- возвращает синглтон модуля-монолита. func LetModMonolit(name mod_ent.AModuleName) *LModMonolit { block.Lock() defer block.Unlock() if mon != nil { return mon } owner := d0.LetOwner(1, "isol_core") d0.If(name == "").Hassert("NewMonolit(): name is empty") kCtx := d2.GetKernCtx() opt := kCtx.Get(txtIsLocal) opt.Hassert("GetMonolit(): in get from kernCtx isLocal -- not found") isLocalCtx := opt.Some() isLocal := isLocalCtx.Val().(d0.Bool) lCtx := d1.NewLocalCtx(owner, kCtx.SelfCtx()) sf := &LModMonolit{ owner: owner, kCtx: kCtx, lCtx: lCtx, name: name, dict: map[mod_ent.AModuleName]mod_spec.IKernelModule{}, isWork: d0.MutSafeBool(owner, false), isEnd: d0.MutSafeBool(owner, false), isLocal: d0.LetBool(owner, isLocal), } sf.log = sf.lCtx.Log() sf.kCtx.Set(d0.LetTxt(owner, "monolitName"), name, "name of monolit") sf.kCtx.Set(d0.LetTxt(owner, "monolit"), sf, "monolit-app") mon = sf _ = mod_spec.IKernelMonolit(sf) return sf } // Owner -- возвращает владельца монолита func (sf *LModMonolit) Owner() *d0.LOwner { return sf.owner } // Ctx -- возвращает контекст монолита. func (sf *LModMonolit) Ctx() *d1.LocalCtx { return sf.lCtx } // Log -- возвращает лог монолита. func (sf *LModMonolit) Log() *d1.LogBuf { return sf.lCtx.Log() } // Name -- возвращает имя монолита. func (sf *LModMonolit) Name() mod_ent.AModuleName { return sf.name } // Add -- добавляет модуль в монолит. func (sf *LModMonolit) Add(module mod_spec.IKernelModule) { sf.kCtx.RLock() defer sf.kCtx.RUnlock() d0.If(module == nil).Hassert("kMonolit.Add(): module==nil", []any{}) _, isOk := sf.dict[module.Name().Get()] d0.If(d0.Bool(isOk)).Hassert("kMonolit.Add(): module(%v) already exists", []any{module.Name()}) sf.dict[module.Name().Get()] = module sf.log.Debug("kMonolit.Add(): module='%v'", module.Name()) if sf.isWork.IsOk() { go module.Run() sf.log.Debug("kMonolit.Add(): module='%v' is run", module.Name()) } key := d0.LetTxt(owner, "module_%v", len(sf.dict)) moduleName := module.Name() comment := d0.LetTxt(owner, "kMonolit.Add(): module="+moduleName.Txt()) sf.lCtx.Set(key, module, comment.Get()) } // Run -- запускает монолит в работу. func (sf *LModMonolit) Run() { sf.kCtx.RLock() defer sf.kCtx.RUnlock() if sf.isEnd.IsOk() { return } if sf.isWork.IsOk() { return } sf.isWork.Set() for _, module := range sf.dict { go module.Run() } sf.log.Debug("kMonolit.Run()") } // IsLocal -- возвращает признак локальной шины. func (sf *LModMonolit) IsLocal() *d0.LBool { return sf.isLocal } // IsWork -- возвращает признак работы монолита. func (sf *LModMonolit) IsWork() *d0.LBool { res := sf.isWork.Let() return res } // Ожидание завершения работы монолита. func (sf *LModMonolit) Wait() { sf.kCtx.Wait() sf.kCtx.Wg().Wait() sf.kCtx.Lock() defer sf.kCtx.Unlock() sf.isWork.Reset() sf.isEnd.Set() sf.log.Debug("kMonolit.close(): end") }