kmonolit.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // package kmonolit -- модульный монолит на основе ядра.
  2. package kmonolit
  3. import (
  4. "fmt"
  5. mL0 "gitp78su.ipnodns.ru/svi/kern/v4/lev0"
  6. mKa "gitp78su.ipnodns.ru/svi/kern/v4/lev0/alias"
  7. mKh "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers"
  8. mKt "gitp78su.ipnodns.ru/svi/kern/v4/lev0/ktypes"
  9. mL1 "gitp78su.ipnodns.ru/svi/kern/v4/lev1"
  10. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kctx"
  11. )
  12. // kMonolit -- объект модульного монолита.
  13. type kMonolit struct {
  14. kCtx mKt.IKernelCtx
  15. lCtx mKt.ILocalCtx
  16. log mKt.ILogBuf
  17. name string
  18. isLocal bool
  19. isWork mKt.ISafeBool
  20. isEnd mKt.ISafeBool
  21. dict map[*mKa.AModuleName]mKt.IKernelModule // Словарь модулей монолита
  22. }
  23. var (
  24. mon *kMonolit
  25. )
  26. // GetMonolit -- возвращает монолит.
  27. func GetMonolit(name string) *mL0.Result[*kMonolit] {
  28. if mon != nil {
  29. return mL0.NewRes(mon)
  30. }
  31. mKh.Hassert(name != "", "NewMonolit(): name is empty")
  32. resKernCtx := kctx.GetKernelCtx()
  33. if resKernCtx.IsErr() {
  34. err := fmt.Errorf("GetMonolit(): err=\n\t%w", resKernCtx.Err())
  35. return mL0.NewErr[*kMonolit](err)
  36. }
  37. kCtx := resKernCtx.Val()
  38. res := kCtx.Get("isLocal")
  39. if res.IsNone() {
  40. err := fmt.Errorf("GetMonolit(): in get from kernCtx isLocal -- not found")
  41. return mL0.NewErr[*kMonolit](err)
  42. }
  43. isLocalCtx := res.Val()
  44. isLocal := isLocalCtx.Val().(bool)
  45. resLocCtx := mL1.NewLocalCtx(kCtx.Ctx())
  46. if resLocCtx.IsErr() {
  47. err := fmt.Errorf("GetMonolit(): in new local_ctx, err=\n\t%w", resLocCtx.Err())
  48. return mL0.NewErr[*kMonolit](err)
  49. }
  50. lCtx := resLocCtx.Val()
  51. sf := &kMonolit{
  52. kCtx: kCtx,
  53. lCtx: lCtx,
  54. name: name,
  55. dict: map[*mKa.AModuleName]mKt.IKernelModule{},
  56. isWork: mL1.NewSafeBool(),
  57. isEnd: mL1.NewSafeBool(),
  58. isLocal: isLocal,
  59. }
  60. sf.log = sf.lCtx.Log()
  61. resSet := sf.kCtx.Set("monolitName", name, "name of monolit")
  62. if resSet.IsErr() {
  63. err := fmt.Errorf("GetMonolit(): in set to kernCtx monolitName, err=\n\t%w", resSet.Err())
  64. return mL0.NewErr[*kMonolit](err)
  65. }
  66. resSet = sf.kCtx.Set("monolit", sf, "monolit-app")
  67. if resSet.IsErr() {
  68. err := fmt.Errorf("GetMonolit(): in set to kernCtx monolit-app, err=\n\t%w", resSet.Err())
  69. return mL0.NewErr[*kMonolit](err)
  70. }
  71. mon = sf
  72. _ = mKt.IKernelMonolit(sf)
  73. return mL0.NewRes(sf)
  74. }
  75. // Ctx -- возвращает контекст монолита.
  76. func (sf *kMonolit) Ctx() mKt.ILocalCtx {
  77. return sf.lCtx
  78. }
  79. // Log -- возвращает лог монолита.
  80. func (sf *kMonolit) Log() mKt.ILogBuf {
  81. return sf.lCtx.Log()
  82. }
  83. // Name -- возвращает имя монолита.
  84. func (sf *kMonolit) Name() string {
  85. return sf.name
  86. }
  87. // Add -- добавляет модуль в монолит.
  88. func (sf *kMonolit) Add(module mKt.IKernelModule) *mL0.Result[bool] {
  89. sf.kCtx.RLock()
  90. defer sf.kCtx.RUnlock()
  91. if module == nil {
  92. return mL0.NewErr[bool](fmt.Errorf("kMonolit.Add(): module==nil"))
  93. }
  94. _, isOk := sf.dict[module.Name()]
  95. if isOk {
  96. err := fmt.Errorf("kMonolit.Add(): module(%v) already exists", module.Name())
  97. return mL0.NewErr[bool](err)
  98. }
  99. sf.dict[module.Name()] = module
  100. sf.log.Debug("kMonolit.Add(): module='%v'", module.Name())
  101. if sf.isWork.Get() {
  102. go module.Run()
  103. sf.log.Debug("kMonolit.Add(): module='%v' is run", module.Name())
  104. }
  105. key := fmt.Sprintf("module_%v", len(sf.dict))
  106. moduleName := module.Name()
  107. resSet := sf.lCtx.Set(key, module, "kMonolit.Add(): module="+moduleName.Get())
  108. if resSet.IsErr() {
  109. err := fmt.Errorf("kMonolit.Add(): in set module(%v) to kernel ctx, err=\n\t%w", moduleName, resSet.Err())
  110. return mL0.NewErr[bool](err)
  111. }
  112. return mL0.NewRes(true)
  113. }
  114. // Run -- запускает монолит в работу.
  115. func (sf *kMonolit) Run() {
  116. sf.kCtx.RLock()
  117. defer sf.kCtx.RUnlock()
  118. if sf.isEnd.Get() {
  119. return
  120. }
  121. if sf.isWork.Get() {
  122. return
  123. }
  124. sf.isWork.Set()
  125. for _, module := range sf.dict {
  126. go module.Run()
  127. }
  128. sf.log.Debug("kMonolit.Run()")
  129. }
  130. // IsLocal -- возвращает признак локальной шины.
  131. func (sf *kMonolit) IsLocal() bool {
  132. return sf.isLocal
  133. }
  134. // IsWork -- возвращает признак работы монолита.
  135. func (sf *kMonolit) IsWork() bool {
  136. return sf.isWork.Get()
  137. }
  138. // Ожидание завершения работы монолита.
  139. func (sf *kMonolit) Wait() {
  140. sf.kCtx.Wait()
  141. sf.kCtx.Wg().Wait()
  142. sf.kCtx.Lock()
  143. defer sf.kCtx.Unlock()
  144. sf.isWork.Reset()
  145. sf.isEnd.Set()
  146. sf.log.Debug("kMonolit.close(): end")
  147. }