package usecase import ( "context" "time" member "gateway/internal/model/member/domain" domrepo "gateway/internal/model/member/domain/repository" domusecase "gateway/internal/model/member/domain/usecase" ) type verifyRateUseCase struct { store domrepo.VerifyRateStore } // VerifyRateUseCaseParam wires VerifyRateUseCase. type VerifyRateUseCaseParam struct { Store domrepo.VerifyRateStore } // MustVerifyRateUseCase constructs VerifyRateUseCase. func MustVerifyRateUseCase(param VerifyRateUseCaseParam) domusecase.VerifyRateUseCase { if param.Store == nil { panic("member: verify rate store is required") } return &verifyRateUseCase{store: param.Store} } func (uc *verifyRateUseCase) AssertResendAllowed(ctx context.Context, key string, cooldown time.Duration) error { if key == "" { return errb.InputMissingRequired("rate limit key is required") } ok, err := uc.store.TryResendLock(ctx, key, cooldown) if err != nil { return errb.DBError("rate limit check failed").WithCause(err) } if !ok { return errb.SysTooManyRequest("resend cooldown active").WithCause(member.ErrResendCooldown) } return nil } func (uc *verifyRateUseCase) AssertDailyAllowed(ctx context.Context, key string, window time.Duration, limit int) error { if key == "" { return errb.InputMissingRequired("daily limit key is required") } count, err := uc.store.IncrDaily(ctx, key, window) if err != nil { return errb.DBError("daily limit check failed").WithCause(err) } if count > int64(limit) { return errb.ResInsufficientQuota("daily verification limit exceeded").WithCause(member.ErrDailyLimit) } return nil }