| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- // package kmonolit -- модульный монолит на основе ядра
- package kmonolit
- import (
- "fmt"
- . "gitp78su.ipnodns.ru/svi/kern/v4/lev0/kalias"
- . "gitp78su.ipnodns.ru/svi/kern/v4/lev0/ktypes"
- . "gitp78su.ipnodns.ru/svi/kern/v4/lev1/helpers"
- "gitp78su.ipnodns.ru/svi/kern/v4/lev1/local_ctx"
- . "gitp78su.ipnodns.ru/svi/kern/v4/lev1/result"
- "gitp78su.ipnodns.ru/svi/kern/v4/lev1/safe_bool"
- "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kctx"
- )
- // kMonolit -- объект модульного монолита
- type kMonolit struct {
- kCtx IKernelCtx
- lCtx ILocalCtx
- log ILogBuf
- name string
- isLocal bool
- isWork ISafeBool
- isEnd ISafeBool
- dict map[AModuleName]IKernelModule // Словарь модулей монолита
- }
- var (
- mon *kMonolit
- )
- // GetMonolit -- возвращает монолит
- func GetMonolit(name string) IResult[*kMonolit] {
- if mon != nil {
- return NewRes(mon)
- }
- Hassert(name != "", "NewMonolit(): name is empty")
- resKernCtx := kctx.GetKernelCtx()
- if resKernCtx.IsErr() {
- err := fmt.Errorf("GetMonolit(): err=\n\t%w", resKernCtx.Err())
- return NewErr[*kMonolit](err)
- }
- kCtx := resKernCtx.Val()
- res := kCtx.Get("isLocal")
- if res.IsNone() {
- err := fmt.Errorf("GetMonolit(): in get from kernCtx isLocal -- not found")
- return NewErr[*kMonolit](err)
- }
- isLocalCtx := res.Val()
- isLocal := isLocalCtx.Val().(bool)
- resLocCtx := local_ctx.NewLocalCtx(kCtx.Ctx())
- if resLocCtx.IsErr() {
- err := fmt.Errorf("GetMonolit(): in new local_ctx, err=\n\t%w", resLocCtx.Err())
- return NewErr[*kMonolit](err)
- }
- lCtx := resLocCtx.Val()
- sf := &kMonolit{
- kCtx: kCtx,
- lCtx: lCtx,
- name: name,
- dict: map[AModuleName]IKernelModule{},
- isWork: safe_bool.NewSafeBool(),
- isEnd: safe_bool.NewSafeBool(),
- isLocal: isLocal,
- }
- sf.log = sf.lCtx.Log()
- resSet := sf.kCtx.Set("monolitName", name, "name of monolit")
- if resSet.IsErr() {
- err := fmt.Errorf("GetMonolit(): in set to kernCtx monolitName, err=\n\t%w", resSet.Err())
- return NewErr[*kMonolit](err)
- }
- resSet = sf.kCtx.Set("monolit", sf, "monolit-app")
- if resSet.IsErr() {
- err := fmt.Errorf("GetMonolit(): in set to kernCtx monolit-app, err=\n\t%w", resSet.Err())
- return NewErr[*kMonolit](err)
- }
- mon = sf
- _ = IKernelMonolit(sf)
- return NewRes(sf)
- }
- // Ctx -- возвращает контекст монолита
- func (sf *kMonolit) Ctx() ILocalCtx {
- return sf.lCtx
- }
- // Log -- возвращает лог монолита
- func (sf *kMonolit) Log() ILogBuf {
- return sf.lCtx.Log()
- }
- // Name -- возвращает имя монолита
- func (sf *kMonolit) Name() string {
- return sf.name
- }
- // Add -- добавляет модуль в монолит
- func (sf *kMonolit) Add(module IKernelModule) IResult[bool] {
- sf.kCtx.RLock()
- defer sf.kCtx.RUnlock()
- if module == nil {
- return NewErr[bool](fmt.Errorf("kMonolit.Add(): module==nil"))
- }
- _, isOk := sf.dict[module.Name()]
- if isOk {
- err := fmt.Errorf("kMonolit.Add(): module(%v) already exists", module.Name())
- return NewErr[bool](err)
- }
- sf.dict[module.Name()] = 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 := string(module.Name())
- resSet := sf.lCtx.Set(key, module, "kMonolit.Add(): module="+moduleName)
- if resSet.IsErr() {
- err := fmt.Errorf("kMonolit.Add(): in set module(%v) to kernel ctx, err=\n\t%w", moduleName, resSet.Err())
- return NewErr[bool](err)
- }
- return NewRes(true)
- }
- // 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() bool {
- return sf.isLocal
- }
- // IsWork -- возвращает признак работы монолита
- func (sf *kMonolit) IsWork() bool {
- return sf.isWork.Get()
- }
- // Ожидание завершения работы монолита
- 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")
- }
|