| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- package service
- import (
- "context"
- "maps"
- "time"
- infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
- )
- var ErrProtectionConflict = infraerrors.Conflict("PROTECTION_CONFLICT", "账号配置已变化,请刷新后重试")
- type protectionWriteExpectationKey struct{}
- type ProtectionWriteExpectation struct {
- AccountID int64
- UpdatedAt time.Time
- }
- func GetProtectionWriteExpectation(ctx context.Context) (ProtectionWriteExpectation, bool) {
- v, ok := ctx.Value(protectionWriteExpectationKey{}).(ProtectionWriteExpectation)
- return v, ok
- }
- // Calculate transitions without publishing an intermediate disabled account.
- // The repository compares the original revision under its row lock before the
- // single final update, outbox insert and transaction commit.
- func (s *AntiDegradeService) transition(ctx context.Context, id int64, plan func(*AntiDegradeService) error) (*Account, error) {
- if s == nil || s.admin == nil {
- return nil, infraerrors.ServiceUnavailable("PROTECTION_UNAVAILABLE", "账号保护服务不可用")
- }
- original, err := s.admin.GetAccount(ctx, id)
- if err != nil {
- return nil, err
- }
- draft := *original
- draft.Extra = maps.Clone(original.Extra)
- store := &protectionDraftStore{account: &draft}
- planner := &AntiDegradeService{admin: store, cfg: s.cfg, pluginManager: s.pluginManager}
- if err := plan(planner); err != nil {
- return nil, err
- }
- if !store.changed {
- return original, nil
- }
- ctx = context.WithValue(ctx, mode1ManagedWriteKey{}, true)
- ctx = context.WithValue(ctx, protectionWriteExpectationKey{}, ProtectionWriteExpectation{id, original.UpdatedAt})
- return s.admin.UpdateAccount(ctx, id, &UpdateAccountInput{Extra: store.account.Extra, Concurrency: &store.account.Concurrency})
- }
- type protectionDraftStore struct {
- account *Account
- changed bool
- }
- func (s *protectionDraftStore) GetAccount(context.Context, int64) (*Account, error) {
- a := *s.account
- a.Extra = maps.Clone(a.Extra)
- return &a, nil
- }
- func (s *protectionDraftStore) UpdateAccount(_ context.Context, _ int64, in *UpdateAccountInput) (*Account, error) {
- a := *s.account
- if in.Extra != nil {
- a.Extra = prepareCodexFingerprintExtraForUpdate(&a, in.Extra)
- }
- if in.Concurrency != nil {
- a.Concurrency = *in.Concurrency
- }
- BoundAccountProtectionConcurrency(&a)
- if err := ValidateAccountProtectionConfiguration(&a); err != nil {
- return nil, err
- }
- s.account, s.changed = &a, true
- return s.GetAccount(context.Background(), a.ID)
- }
|