64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package usecase
|
||
|
||
import (
|
||
"context"
|
||
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
)
|
||
|
||
/*
|
||
charge 是一次計點呼叫的預留與結算,沿用既有四個 meter,不新增第五個(RG-04)。
|
||
|
||
用法:`defer charge.Settle(ctx, &err)` 綁在具名 error 回傳上,這樣任何失敗路徑都退點,
|
||
不會出現「AI 失敗了但點數扣掉」。
|
||
*/
|
||
type charge struct {
|
||
svc *Service
|
||
uid int64
|
||
meter string
|
||
mode string
|
||
label string
|
||
source string
|
||
settled bool
|
||
}
|
||
|
||
func (s *Service) bill(ctx context.Context, uid int64, meter, label, source string) (*charge, error) {
|
||
if s == nil || s.Usage == nil {
|
||
return &charge{settled: true}, nil
|
||
}
|
||
mode, err := s.Usage.PrepareCall(ctx, uid, meter)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &charge{svc: s, uid: uid, meter: meter, mode: mode, label: label, source: source}, nil
|
||
}
|
||
|
||
func (c *charge) Settle(ctx context.Context, errp *error) {
|
||
if errp != nil && *errp != nil {
|
||
c.Release(ctx)
|
||
return
|
||
}
|
||
c.Commit(ctx)
|
||
}
|
||
|
||
// Commit 寫入用量事件。使用者已經拿到結果,所以這裡失敗只記錄不轉成錯誤。
|
||
func (c *charge) Commit(ctx context.Context) {
|
||
if c == nil || c.settled {
|
||
return
|
||
}
|
||
c.settled = true
|
||
if _, err := c.svc.Usage.RecordCall(ctx, c.uid, c.meter, c.mode, c.label, c.source); err != nil {
|
||
logx.Errorf("usage record uid=%d meter=%s source=%s: %v", c.uid, c.meter, c.source, err)
|
||
}
|
||
}
|
||
|
||
func (c *charge) Release(ctx context.Context) {
|
||
if c == nil || c.settled {
|
||
return
|
||
}
|
||
c.settled = true
|
||
if err := c.svc.Usage.ReleaseCall(ctx, c.uid, c.meter, c.mode); err != nil {
|
||
logx.Errorf("usage release uid=%d meter=%s source=%s: %v", c.uid, c.meter, c.source, err)
|
||
}
|
||
}
|