gatewayip.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package repository
  2. import (
  3. "context"
  4. "fmt"
  5. v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
  6. "github.com/go-nunu/nunu-layout-advanced/internal/model"
  7. "gorm.io/gorm"
  8. )
  9. type GatewayipRepository interface {
  10. GetGatewayip(ctx context.Context, id int64) (*model.Gatewayip, error)
  11. AddGatewayip(ctx context.Context, req model.Gatewayip) error
  12. EditGatewayip(ctx context.Context, req model.Gatewayip) error
  13. DeleteGatewayip(ctx context.Context, req model.Gatewayip) error
  14. GetGatewayipByHostId(ctx context.Context, hostId int64) (*model.Gatewayip, error)
  15. GetGatewayipByHostIdAll(ctx context.Context, hostId int64) (*model.Gatewayip, error)
  16. UpdateGatewayipByHostId(ctx context.Context, req model.Gatewayip) error
  17. DeleteGatewayipByHostId(ctx context.Context, hostId int64) error
  18. GetIpWhereHostIdNull(ctx context.Context,req v1.GlobalLimitRequireResponse) error
  19. CleanIPByHostId(ctx context.Context, hostId []int64) error
  20. }
  21. func NewGatewayipRepository(
  22. repository *Repository,
  23. ) GatewayipRepository {
  24. return &gatewayipRepository{
  25. Repository: repository,
  26. }
  27. }
  28. type gatewayipRepository struct {
  29. *Repository
  30. }
  31. func (r *gatewayipRepository) GetGatewayip(ctx context.Context, id int64) (*model.Gatewayip, error) {
  32. var req model.Gatewayip
  33. return &req, r.DB(ctx).Where("id = ?", id).First(&req).Error
  34. }
  35. func (r *gatewayipRepository) AddGatewayip(ctx context.Context, req model.Gatewayip) error {
  36. return r.DB(ctx).Create(&req).Error
  37. }
  38. func (r *gatewayipRepository) EditGatewayip(ctx context.Context, req model.Gatewayip) error {
  39. return r.DB(ctx).Model(&model.Gatewayip{}).Where("id = ?", req.Id).Updates(req).Error
  40. }
  41. func (r *gatewayipRepository) DeleteGatewayip(ctx context.Context, req model.Gatewayip) error {
  42. return r.DB(ctx).Model(&model.Gatewayip{}).Where("id = ?", req.Id).Delete(req).Error
  43. }
  44. func (r *gatewayipRepository) GetGatewayipByHostId(ctx context.Context, hostId int64) (*model.Gatewayip, error) {
  45. var req model.Gatewayip
  46. return &req, r.DB(ctx).Where("host_id = ?", hostId).First(&req).Error
  47. }
  48. func (r *gatewayipRepository) GetGatewayipByHostIdAll(ctx context.Context, hostId int64) (*model.Gatewayip, error) {
  49. var req model.Gatewayip
  50. return &req, r.DB(ctx).Where("host_id = ?", hostId).Find(&req).Error
  51. }
  52. func (r *gatewayipRepository) UpdateGatewayipByHostId(ctx context.Context, req model.Gatewayip) error {
  53. return r.DB(ctx).Where("host_id = ?", req.HostId).Updates(&req).Error
  54. }
  55. func (r *gatewayipRepository) DeleteGatewayipByHostId(ctx context.Context, hostId int64) error {
  56. return r.DB(ctx).Model(&model.Gatewayip{}).Where("host_id = ?", hostId).Delete(&model.Gatewayip{}).Error
  57. }
  58. func (r *gatewayipRepository) GetIpWhereHostIdNull(ctx context.Context,req v1.GlobalLimitRequireResponse) error {
  59. if req.IpCount <= 0 {
  60. return fmt.Errorf("套餐IP数量错误, 请联系客服")
  61. }
  62. if req.HostId <= 0 {
  63. return fmt.Errorf("主机ID错误, 请联系客服")
  64. }
  65. // 使用事务保证操作的原子性
  66. return r.DB(ctx).Transaction(func(tx *gorm.DB) error {
  67. var idsToAssign []uint // 只需一个切片来接收ID
  68. // 步骤 1: 查询所需数量的可用IP ID。使用 Limit 可以提升性能,避免捞出所有可用IP。
  69. err := tx.Model(&model.Gatewayip{}).
  70. Where("operator = ?", req.Operator).
  71. Where("ban_udp = ?", req.IsBanUdp).
  72. Where("ban_overseas = ?", req.IsBanOverseas).
  73. Where("host_id IS NULL OR host_id = ?", 0).
  74. Order("id ASC").
  75. Limit(req.IpCount). // 优化点:直接用Limit限制查询数量
  76. Pluck("id", &idsToAssign).Error
  77. if err != nil {
  78. return err // 查询出错,事务回滚
  79. }
  80. // 步骤 2: 判断实际查到的数量是否足够
  81. if len(idsToAssign) < req.IpCount {
  82. return fmt.Errorf("库存不足, 请联系客服补充") // 数量不足,返回特定错误,事务回滚
  83. }
  84. // 步骤 3: 更新这些IP的 host_id
  85. // 注意:因为上面已经Limit了,所以idsToAssign的长度就是我们要更新的数量
  86. updateResult := tx.Model(&model.Gatewayip{}).
  87. Where("id IN ?", idsToAssign).
  88. Update("host_id", req.HostId)
  89. if updateResult.Error != nil {
  90. return updateResult.Error // 更新失败,事务回滚
  91. }
  92. // (可选) 健壮性检查
  93. if updateResult.RowsAffected != int64(req.IpCount) {
  94. return fmt.Errorf("IP分配异常: 期望更新 %d 条记录, 实际更新了 %d 条", req.IpCount, updateResult.RowsAffected)
  95. }
  96. // 返回 nil, GORM 会提交事务
  97. return nil
  98. })
  99. }
  100. func (r *gatewayipRepository) CleanIPByHostId(ctx context.Context, hostId []int64) error {
  101. return r.DB(ctx).Model(&model.Gatewayip{}).Where("host_id IN ?", hostId).Update("host_id", 0).Error
  102. }