kmonolit.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // package kmonolit -- модульный монолит на основе ядра.
  2. package kmonolit
  3. import (
  4. "sync"
  5. "gitp78su.ipnodns.ru/svi/kern/v4/lev0"
  6. "gitp78su.ipnodns.ru/svi/kern/v4/lev1"
  7. "gitp78su.ipnodns.ru/svi/kern/v4/lev2"
  8. "gitp78su.ipnodns.ru/svi/kern/v4/lev3/mod_ent"
  9. "gitp78su.ipnodns.ru/svi/kern/v4/lev3/mod_spec"
  10. )
  11. // LModMonolit -- объект модульного монолита.
  12. type LModMonolit struct {
  13. kCtx *lev2.KernCtx
  14. lCtx *lev1.LocalCtx
  15. log *lev1.LogBuf
  16. name mod_ent.AModuleName
  17. isLocal *lev0.LBool
  18. isWork *lev0.MSafeBool
  19. isEnd *lev0.MSafeBool
  20. dict map[mod_ent.AModuleName]mod_spec.IKernelModule // Словарь модулей монолита
  21. }
  22. var (
  23. mon *LModMonolit
  24. block sync.Mutex
  25. )
  26. var (
  27. txtIsLocal = lev0.LetTxt("isLocal")
  28. )
  29. // LetModMonolit -- возвращает синглтон модуля-монолита.
  30. func LetModMonolit(name mod_ent.AModuleName) *LModMonolit {
  31. block.Lock()
  32. defer block.Unlock()
  33. if mon != nil {
  34. return mon
  35. }
  36. lev0.If(name == "").Hassert("NewMonolit(): name is empty")
  37. kCtx := lev2.GetKernCtx()
  38. opt := kCtx.Get(txtIsLocal)
  39. opt.Hassert("GetMonolit(): in get from kernCtx isLocal -- not found")
  40. isLocalCtx := opt.Some()
  41. isLocal := isLocalCtx.Val().(lev0.Bool)
  42. lCtx := lev1.NewLocalCtx(kCtx.SelfCtx())
  43. sf := &LModMonolit{
  44. kCtx: kCtx,
  45. lCtx: lCtx,
  46. name: name,
  47. dict: map[mod_ent.AModuleName]mod_spec.IKernelModule{},
  48. isWork: lev0.MutSafeBool(false),
  49. isEnd: lev0.MutSafeBool(false),
  50. isLocal: lev0.LetBool(isLocal),
  51. }
  52. sf.log = sf.lCtx.Log()
  53. sf.kCtx.Set(lev0.LetTxt("monolitName"), name, "name of monolit")
  54. sf.kCtx.Set(lev0.LetTxt("monolit"), sf, "monolit-app")
  55. mon = sf
  56. _ = mod_spec.IKernelMonolit(sf)
  57. return sf
  58. }
  59. // Ctx -- возвращает контекст монолита.
  60. func (sf *LModMonolit) Ctx() *lev1.LocalCtx {
  61. return sf.lCtx
  62. }
  63. // Log -- возвращает лог монолита.
  64. func (sf *LModMonolit) Log() *lev1.LogBuf {
  65. return sf.lCtx.Log()
  66. }
  67. // Name -- возвращает имя монолита.
  68. func (sf *LModMonolit) Name() mod_ent.AModuleName {
  69. return sf.name
  70. }
  71. // Add -- добавляет модуль в монолит.
  72. func (sf *LModMonolit) Add(module mod_spec.IKernelModule) {
  73. sf.kCtx.RLock()
  74. defer sf.kCtx.RUnlock()
  75. lev0.If(module == nil).Hassert("kMonolit.Add(): module==nil", []any{})
  76. _, isOk := sf.dict[module.Name().Get()]
  77. lev0.If(lev0.Bool(isOk)).Hassert("kMonolit.Add(): module(%v) already exists", []any{module.Name()})
  78. sf.dict[module.Name().Get()] = module
  79. sf.log.Debug("kMonolit.Add(): module='%v'", module.Name())
  80. if sf.isWork.Get() {
  81. go module.Run()
  82. sf.log.Debug("kMonolit.Add(): module='%v' is run", module.Name())
  83. }
  84. key := lev0.LetTxt("module_%v", len(sf.dict))
  85. moduleName := module.Name()
  86. comment := lev0.LetTxt("kMonolit.Add(): module=" + moduleName.Txt())
  87. sf.lCtx.Set(key, module, comment.Get())
  88. }
  89. // Run -- запускает монолит в работу.
  90. func (sf *LModMonolit) Run() {
  91. sf.kCtx.RLock()
  92. defer sf.kCtx.RUnlock()
  93. if sf.isEnd.Get() {
  94. return
  95. }
  96. if sf.isWork.Get() {
  97. return
  98. }
  99. sf.isWork.Set()
  100. for _, module := range sf.dict {
  101. go module.Run()
  102. }
  103. sf.log.Debug("kMonolit.Run()")
  104. }
  105. // IsLocal -- возвращает признак локальной шины.
  106. func (sf *LModMonolit) IsLocal() *lev0.LBool {
  107. return sf.isLocal
  108. }
  109. // IsWork -- возвращает признак работы монолита.
  110. func (sf *LModMonolit) IsWork() *lev0.LBool {
  111. res := sf.isWork.Get()
  112. return lev0.LetBool(res)
  113. }
  114. // Ожидание завершения работы монолита.
  115. func (sf *LModMonolit) Wait() {
  116. sf.kCtx.Wait()
  117. sf.kCtx.Wg().Wait()
  118. sf.kCtx.Lock()
  119. defer sf.kCtx.Unlock()
  120. sf.isWork.Reset()
  121. sf.isEnd.Set()
  122. sf.log.Debug("kMonolit.close(): end")
  123. }