ui_base.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package tasks
  2. import (
  3. "reflect"
  4. "github.com/seaweedfs/seaweedfs/weed/glog"
  5. "github.com/seaweedfs/seaweedfs/weed/pb/worker_pb"
  6. "github.com/seaweedfs/seaweedfs/weed/worker/types"
  7. )
  8. // BaseUIProvider provides common UIProvider functionality for all tasks
  9. type BaseUIProvider struct {
  10. taskType types.TaskType
  11. displayName string
  12. description string
  13. icon string
  14. schemaFunc func() *TaskConfigSchema
  15. configFunc func() types.TaskConfig
  16. applyTaskPolicyFunc func(policy *worker_pb.TaskPolicy) error
  17. applyTaskConfigFunc func(config types.TaskConfig) error
  18. }
  19. // NewBaseUIProvider creates a new base UI provider
  20. func NewBaseUIProvider(
  21. taskType types.TaskType,
  22. displayName string,
  23. description string,
  24. icon string,
  25. schemaFunc func() *TaskConfigSchema,
  26. configFunc func() types.TaskConfig,
  27. applyTaskPolicyFunc func(policy *worker_pb.TaskPolicy) error,
  28. applyTaskConfigFunc func(config types.TaskConfig) error,
  29. ) *BaseUIProvider {
  30. return &BaseUIProvider{
  31. taskType: taskType,
  32. displayName: displayName,
  33. description: description,
  34. icon: icon,
  35. schemaFunc: schemaFunc,
  36. configFunc: configFunc,
  37. applyTaskPolicyFunc: applyTaskPolicyFunc,
  38. applyTaskConfigFunc: applyTaskConfigFunc,
  39. }
  40. }
  41. // GetTaskType returns the task type
  42. func (ui *BaseUIProvider) GetTaskType() types.TaskType {
  43. return ui.taskType
  44. }
  45. // GetDisplayName returns the human-readable name
  46. func (ui *BaseUIProvider) GetDisplayName() string {
  47. return ui.displayName
  48. }
  49. // GetDescription returns a description of what this task does
  50. func (ui *BaseUIProvider) GetDescription() string {
  51. return ui.description
  52. }
  53. // GetIcon returns the icon CSS class for this task type
  54. func (ui *BaseUIProvider) GetIcon() string {
  55. return ui.icon
  56. }
  57. // GetCurrentConfig returns the current configuration as TaskConfig
  58. func (ui *BaseUIProvider) GetCurrentConfig() types.TaskConfig {
  59. return ui.configFunc()
  60. }
  61. // ApplyTaskPolicy applies protobuf TaskPolicy configuration
  62. func (ui *BaseUIProvider) ApplyTaskPolicy(policy *worker_pb.TaskPolicy) error {
  63. return ui.applyTaskPolicyFunc(policy)
  64. }
  65. // ApplyTaskConfig applies TaskConfig interface configuration
  66. func (ui *BaseUIProvider) ApplyTaskConfig(config types.TaskConfig) error {
  67. return ui.applyTaskConfigFunc(config)
  68. }
  69. // CommonConfigGetter provides a common pattern for getting current configuration
  70. type CommonConfigGetter[T any] struct {
  71. defaultConfig T
  72. detectorFunc func() T
  73. schedulerFunc func() T
  74. }
  75. // NewCommonConfigGetter creates a new common config getter
  76. func NewCommonConfigGetter[T any](
  77. defaultConfig T,
  78. detectorFunc func() T,
  79. schedulerFunc func() T,
  80. ) *CommonConfigGetter[T] {
  81. return &CommonConfigGetter[T]{
  82. defaultConfig: defaultConfig,
  83. detectorFunc: detectorFunc,
  84. schedulerFunc: schedulerFunc,
  85. }
  86. }
  87. // GetConfig returns the merged configuration
  88. func (cg *CommonConfigGetter[T]) GetConfig() T {
  89. config := cg.defaultConfig
  90. // Apply detector values if available
  91. if cg.detectorFunc != nil {
  92. detectorConfig := cg.detectorFunc()
  93. mergeConfigs(&config, detectorConfig)
  94. }
  95. // Apply scheduler values if available
  96. if cg.schedulerFunc != nil {
  97. schedulerConfig := cg.schedulerFunc()
  98. mergeConfigs(&config, schedulerConfig)
  99. }
  100. return config
  101. }
  102. // mergeConfigs merges non-zero values from source into dest
  103. func mergeConfigs[T any](dest *T, source T) {
  104. destValue := reflect.ValueOf(dest).Elem()
  105. sourceValue := reflect.ValueOf(source)
  106. if destValue.Kind() != reflect.Struct || sourceValue.Kind() != reflect.Struct {
  107. return
  108. }
  109. for i := 0; i < destValue.NumField(); i++ {
  110. destField := destValue.Field(i)
  111. sourceField := sourceValue.Field(i)
  112. if !destField.CanSet() {
  113. continue
  114. }
  115. // Only copy non-zero values
  116. if !sourceField.IsZero() {
  117. if destField.Type() == sourceField.Type() {
  118. destField.Set(sourceField)
  119. }
  120. }
  121. }
  122. }
  123. // RegisterUIFunc provides a common registration function signature
  124. type RegisterUIFunc[D, S any] func(uiRegistry *types.UIRegistry, detector D, scheduler S)
  125. // CommonRegisterUI provides a common registration implementation
  126. func CommonRegisterUI[D, S any](
  127. taskType types.TaskType,
  128. displayName string,
  129. uiRegistry *types.UIRegistry,
  130. detector D,
  131. scheduler S,
  132. schemaFunc func() *TaskConfigSchema,
  133. configFunc func() types.TaskConfig,
  134. applyTaskPolicyFunc func(policy *worker_pb.TaskPolicy) error,
  135. applyTaskConfigFunc func(config types.TaskConfig) error,
  136. ) {
  137. // Get metadata from schema
  138. schema := schemaFunc()
  139. description := "Task configuration"
  140. icon := "fas fa-cog"
  141. if schema != nil {
  142. description = schema.Description
  143. icon = schema.Icon
  144. }
  145. uiProvider := NewBaseUIProvider(
  146. taskType,
  147. displayName,
  148. description,
  149. icon,
  150. schemaFunc,
  151. configFunc,
  152. applyTaskPolicyFunc,
  153. applyTaskConfigFunc,
  154. )
  155. uiRegistry.RegisterUI(uiProvider)
  156. glog.V(1).Infof("Registered %s task UI provider", taskType)
  157. }