00_enter.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package period_profit
  2. import (
  3. "app/commons/core"
  4. "app/commons/model/entity"
  5. "app/commons/services"
  6. "app/commons/utils"
  7. "errors"
  8. "fmt"
  9. "github.com/shopspring/decimal"
  10. "gorm.io/gorm"
  11. )
  12. type Service struct {
  13. //job *entity.SysJob
  14. services.CommonService
  15. }
  16. func NewService() *Service {
  17. return &Service{}
  18. }
  19. // 期任务
  20. // nextPeriod 是否下一期
  21. func (s *Service) RunPeriodProfit(nextPeriod bool) error {
  22. var err error
  23. // 期任务预创建
  24. if err = s.PreCreationPeriods(); err != nil {
  25. return err
  26. }
  27. // 获取最近一期 运行中或完成任务
  28. nextPeriodJob, err := s.getNextRunPeriodJob()
  29. if err != nil {
  30. return err
  31. }
  32. nowPeriodNo := utils.NowPeriodNo()
  33. // 正常运行当期任务 / 当前开启 nextPeriod 无视时间 运行下一期
  34. if nextPeriodJob.PeriodNo == nowPeriodNo || nextPeriod {
  35. if err = s.DB().Model(&entity.StakePeriodJob{}).
  36. Where("id", nextPeriodJob.Id).
  37. Update("job_state", entity.PeriodJobStateRunning).Error; err != nil {
  38. return err
  39. }
  40. if err = s.runPeriodTask(nextPeriodJob.PeriodNo); err != nil {
  41. return err
  42. }
  43. }
  44. err = s.DisProfit()
  45. if err != nil {
  46. return err
  47. }
  48. return nil
  49. }
  50. func (s *Service) runPeriodTask(periodNo string) error {
  51. err := s.calCurrentStakeProfit(periodNo)
  52. if err != nil {
  53. return err
  54. }
  55. err = s.calLevelProfit(periodNo)
  56. if err != nil {
  57. return err
  58. }
  59. updateStm := s.DB().Model(&entity.StakePeriodJob{}).
  60. Where("period_no", periodNo).
  61. Where("job_state", entity.PeriodJobStateRunning).
  62. Updates(map[string]interface{}{
  63. "level_profit_is_cal": true,
  64. "job_state": entity.PeriodJobStateSuccess,
  65. })
  66. if updateStm.RowsAffected != 1 || updateStm.Error != nil {
  67. core.JobLog.Errorf("update fail RowsAffected:%d err:%+v", updateStm.RowsAffected, updateStm.Error)
  68. return err
  69. }
  70. return nil
  71. }
  72. func (s *Service) getNextRunPeriodJob() (*entity.StakePeriodJob, error) {
  73. firstWaiting, err := s.FirstStakePeriodJob(s.DB().Where("job_state = ?", entity.PeriodJobStateWaiting))
  74. if err != nil {
  75. return nil, err
  76. }
  77. runningOrSuccessOrFailRow, err := s.FirstStakePeriodJob(s.DB().Where("job_state != ?", entity.PeriodJobStateWaiting))
  78. if err != nil {
  79. if errors.Is(err, gorm.ErrRecordNotFound) {
  80. return firstWaiting, nil
  81. }
  82. return nil, err
  83. }
  84. if runningOrSuccessOrFailRow.JobState == entity.PeriodJobStateSuccess {
  85. return firstWaiting, nil
  86. }
  87. if runningOrSuccessOrFailRow.JobState == entity.PeriodJobStateRunning {
  88. return nil, fmt.Errorf("存在运行中期任务:%s", runningOrSuccessOrFailRow.PeriodNo)
  89. }
  90. if runningOrSuccessOrFailRow.JobState == entity.PeriodJobStateFailure {
  91. return nil, fmt.Errorf("存在运行错误期任务:%s,必须处理错误后才可以正常运行", runningOrSuccessOrFailRow.PeriodNo)
  92. }
  93. return nil, fmt.Errorf("期任务:%s,未知状态错误", runningOrSuccessOrFailRow.PeriodNo)
  94. }
  95. // 预创建3期任务
  96. func (s *Service) PreCreationPeriods() error {
  97. var err error
  98. firstPeriodJob, err := s.FirstStakePeriodJob(s.DB().Where("job_state", entity.PeriodJobStateWaiting))
  99. if err != nil {
  100. // 当无法占到时创建一条
  101. if errors.Is(err, gorm.ErrRecordNotFound) {
  102. firstPeriodJob, err = s.newPeriods(utils.NowPeriodNo())
  103. if err != nil {
  104. return err
  105. }
  106. } else {
  107. return err
  108. }
  109. }
  110. lastPeriodJob, err := s.LastStakePeriodJob(s.DB().Where("job_state", entity.PeriodJobStateWaiting))
  111. if err != nil {
  112. return err
  113. }
  114. // 计算两期时间跨度
  115. n := utils.CalPeriodNosSpan(firstPeriodJob.PeriodNo, lastPeriodJob.PeriodNo)
  116. // 保持三期创建
  117. if n < 3 {
  118. // 目标期
  119. targetPeriod, err := utils.JumpToPeriodNo(firstPeriodJob.PeriodNo, 3)
  120. if err != nil {
  121. return err
  122. }
  123. nowPeriod := lastPeriodJob.PeriodNo
  124. for {
  125. nextPeriod, err := utils.NextPeriodNo(nowPeriod)
  126. if err != nil {
  127. return err
  128. }
  129. if _, err = s.newPeriods(nextPeriod); err != nil {
  130. return err
  131. }
  132. if nextPeriod >= targetPeriod {
  133. break
  134. }
  135. nowPeriod = nextPeriod
  136. }
  137. }
  138. return err
  139. }
  140. // 创建期任务
  141. func (s *Service) newPeriods(periodNo string) (*entity.StakePeriodJob, error) {
  142. newRow := &entity.StakePeriodJob{
  143. PeriodNo: periodNo,
  144. JobState: entity.PeriodJobStateWaiting,
  145. StaticSymbolProfit: decimal.Zero,
  146. StaticUsdProfit: decimal.Zero,
  147. Desc: "",
  148. }
  149. err := s.DB().Create(&newRow).Error
  150. return newRow, err
  151. }