sub_balancer.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package service
  2. import (
  3. "strings"
  4. "github.com/mhsanaei/3x-ui/v3/internal/database"
  5. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  6. "github.com/mhsanaei/3x-ui/v3/internal/util/common"
  7. )
  8. var subBalancerStrategies = map[string]struct{}{
  9. "leastLoad": {},
  10. "leastPing": {},
  11. "random": {},
  12. "roundRobin": {},
  13. }
  14. // SubBalancerService manages client-side JSON-subscription balancers; rows
  15. // are read per request by internal/sub, so mutations need no xray restart.
  16. type SubBalancerService struct{}
  17. func (s *SubBalancerService) validate(b *model.SubBalancer) error {
  18. b.Remark = strings.TrimSpace(b.Remark)
  19. if b.Remark == "" {
  20. return common.NewError("balancer remark is required")
  21. }
  22. if len(b.Remark) > 256 {
  23. return common.NewError("balancer remark too long (max 256)")
  24. }
  25. if b.Strategy == "" {
  26. b.Strategy = "random"
  27. }
  28. if _, ok := subBalancerStrategies[b.Strategy]; !ok {
  29. return common.NewError("invalid balancer strategy:", b.Strategy)
  30. }
  31. if len(b.InboundIds) == 0 {
  32. return common.NewError("balancer must select at least one inbound")
  33. }
  34. if b.SortOrder < 1 {
  35. b.SortOrder = 1
  36. }
  37. return nil
  38. }
  39. // List returns all balancers in subscription order.
  40. func (s *SubBalancerService) List() ([]*model.SubBalancer, error) {
  41. var balancers []*model.SubBalancer
  42. err := database.GetDB().Model(&model.SubBalancer{}).
  43. Order("sort_order asc, id asc").Find(&balancers).Error
  44. return balancers, err
  45. }
  46. func (s *SubBalancerService) Get(id int) (*model.SubBalancer, error) {
  47. var balancer model.SubBalancer
  48. if err := database.GetDB().First(&balancer, id).Error; err != nil {
  49. return nil, err
  50. }
  51. return &balancer, nil
  52. }
  53. func (s *SubBalancerService) Create(balancer *model.SubBalancer) (*model.SubBalancer, error) {
  54. if err := s.validate(balancer); err != nil {
  55. return nil, err
  56. }
  57. if err := database.GetDB().Create(balancer).Error; err != nil {
  58. return nil, err
  59. }
  60. return balancer, nil
  61. }
  62. func (s *SubBalancerService) Update(id int, balancer *model.SubBalancer, enabled *bool) (*model.SubBalancer, error) {
  63. if err := s.validate(balancer); err != nil {
  64. return nil, err
  65. }
  66. current, err := s.Get(id)
  67. if err != nil {
  68. return nil, err
  69. }
  70. current.Remark = balancer.Remark
  71. current.Strategy = balancer.Strategy
  72. current.InboundIds = balancer.InboundIds
  73. current.SortOrder = balancer.SortOrder
  74. if enabled != nil {
  75. current.Enabled = *enabled
  76. }
  77. if err := database.GetDB().Save(current).Error; err != nil {
  78. return nil, err
  79. }
  80. return current, nil
  81. }
  82. func (s *SubBalancerService) Delete(id int) error {
  83. res := database.GetDB().Delete(&model.SubBalancer{}, id)
  84. if res.Error != nil {
  85. return res.Error
  86. }
  87. if res.RowsAffected == 0 {
  88. return common.NewError("sub balancer not found")
  89. }
  90. return nil
  91. }