Revert "feat(loyalty): EnakPoint & EnakCoin" (#32)
This reverts merge commit645da30, returning main tof0ff59f. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
645da3048e
commit
4e24f9bbb0
@@ -1,74 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"apskel-pos-be/internal/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultEarningBackfillInterval = 30 * time.Minute
|
||||
// How far back to look for paid orders that never earned.
|
||||
earningBackfillWindow = 72 * time.Hour
|
||||
// Orders looked at per run at most, so one run cannot run away.
|
||||
earningBackfillMaxOrders = 5000
|
||||
)
|
||||
|
||||
type missingEarner interface {
|
||||
EarnMissing(ctx context.Context, since time.Time, maxOrders int) (checked, earned int, err error)
|
||||
}
|
||||
|
||||
// EarningBackfillJob is the safety net behind earning at payment time
|
||||
// (docs/prd-point-coin.md F3, PC-203). Every run it earns for orders paid in the last
|
||||
// few days that should have earned and did not, for example because the database was
|
||||
// briefly unreachable right after the payment committed.
|
||||
type EarningBackfillJob struct {
|
||||
earner missingEarner
|
||||
now func() time.Time
|
||||
stopCh chan struct{}
|
||||
stopOnce sync.Once
|
||||
}
|
||||
|
||||
func NewEarningBackfillJob(earner missingEarner) *EarningBackfillJob {
|
||||
return &EarningBackfillJob{earner: earner, now: time.Now, stopCh: make(chan struct{})}
|
||||
}
|
||||
|
||||
func (j *EarningBackfillJob) Start(interval time.Duration) {
|
||||
if interval <= 0 {
|
||||
interval = defaultEarningBackfillInterval
|
||||
}
|
||||
go func() {
|
||||
j.RunOnce(context.Background())
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
j.RunOnce(context.Background())
|
||||
case <-j.stopCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
logger.NonContext.Infof("Earning backfill job started (interval: %s)", interval)
|
||||
}
|
||||
|
||||
func (j *EarningBackfillJob) Stop() {
|
||||
j.stopOnce.Do(func() { close(j.stopCh) })
|
||||
}
|
||||
|
||||
// RunOnce earns for every missed order in the window and reports how many it fixed.
|
||||
// It is quiet when nothing was missed.
|
||||
func (j *EarningBackfillJob) RunOnce(ctx context.Context) int {
|
||||
checked, earned, err := j.earner.EarnMissing(ctx, j.now().Add(-earningBackfillWindow), earningBackfillMaxOrders)
|
||||
if err != nil {
|
||||
logger.NonContext.Error("Earning backfill failed to run", err)
|
||||
}
|
||||
if earned > 0 {
|
||||
logger.NonContext.WarnWithFields("Earning backfill credited orders that had missed their earning",
|
||||
map[string]interface{}{"checked": checked, "earned": earned}, nil)
|
||||
}
|
||||
return earned
|
||||
}
|
||||
Reference in New Issue
Block a user