kmonolit.go 4.3 KB

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