kmonolit.go 3.8 KB

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