kmonolit.go 4.3 KB

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