// package kmonolit -- модульный монолит на основе ядра. package kmonolit import ( "fmt" "sync" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/core_spec" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/etypes/ebool" mKh "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers" mL1 "gitp78su.ipnodns.ru/svi/kern/v4/lev1" "gitp78su.ipnodns.ru/svi/kern/v4/lev1/comp_spec" "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kctx" "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kspec" "gitp78su.ipnodns.ru/svi/kern/v4/lev3/mod_ent" "gitp78su.ipnodns.ru/svi/kern/v4/lev3/mod_spec" ) // kMonolit -- объект модульного монолита. type kMonolit struct { kCtx kspec.IKernelCtx lCtx comp_spec.ILocalCtx log comp_spec.ILogBuf name string isLocal core_spec.EBool isWork core_spec.ISafeBool isEnd core_spec.ISafeBool dict map[mod_ent.AModuleName]mod_spec.IKernelModule // Словарь модулей монолита } var ( mon *kMonolit block sync.Mutex ) // GetMonolit -- возвращает монолит. func GetMonolit(name string) *kMonolit { block.Lock() defer block.Unlock() if mon != nil { return mon } mKh.Hassert(name != "", "NewMonolit(): name is empty") kCtx := kctx.GetKernelCtx() opt := kCtx.Get("isLocal") opt.Hassert("GetMonolit(): in get from kernCtx isLocal -- not found") isLocalCtx := opt.Some() isLocal := isLocalCtx.Val().(bool) lCtx := mL1.NewLocalCtx(kCtx.Ctx()) sf := &kMonolit{ kCtx: kCtx, lCtx: lCtx, name: name, dict: map[mod_ent.AModuleName]mod_spec.IKernelModule{}, isWork: mL1.NewSafeBool(false), isEnd: mL1.NewSafeBool(false), isLocal: ebool.NewEBool(isLocal), } sf.log = sf.lCtx.Log() sf.kCtx.Set("monolitName", name, "name of monolit") sf.kCtx.Set("monolit", sf, "monolit-app") mon = sf _ = mod_spec.IKernelMonolit(sf) return sf } // Ctx -- возвращает контекст монолита. func (sf *kMonolit) Ctx() comp_spec.ILocalCtx { return sf.lCtx } // Log -- возвращает лог монолита. func (sf *kMonolit) Log() comp_spec.ILogBuf { return sf.lCtx.Log() } // Name -- возвращает имя монолита. func (sf *kMonolit) Name() string { return sf.name } // Add -- добавляет модуль в монолит. func (sf *kMonolit) Add(module mod_spec.IKernelModule) { sf.kCtx.RLock() defer sf.kCtx.RUnlock() mKh.Hassert(module != nil, "kMonolit.Add(): module==nil", []any{}) _, isOk := sf.dict[module.Name().Get()] mKh.Hassert(!isOk, "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.Get() { go module.Run() sf.log.Debug("kMonolit.Add(): module='%v' is run", module.Name()) } key := fmt.Sprintf("module_%v", len(sf.dict)) moduleName := module.Name() sf.lCtx.Set(key, module, "kMonolit.Add(): module="+moduleName.String()) } // Run -- запускает монолит в работу. func (sf *kMonolit) Run() { sf.kCtx.RLock() defer sf.kCtx.RUnlock() if sf.isEnd.Get() { return } if sf.isWork.Get() { return } sf.isWork.Set() for _, module := range sf.dict { go module.Run() } sf.log.Debug("kMonolit.Run()") } // IsLocal -- возвращает признак локальной шины. func (sf *kMonolit) IsLocal() core_spec.EBool { return sf.isLocal } // IsWork -- возвращает признак работы монолита. func (sf *kMonolit) IsWork() core_spec.EBool { res := sf.isWork.Get() return ebool.NewEBool(res) } // Ожидание завершения работы монолита. func (sf *kMonolit) 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") }