Как обеспечить идемпотентность API?

Middle+
868 просмотров
AFK Offer AI

Самый распространённый подход — Idempotency Key. Клиент генерирует уникальный ключ (UUID) и отправляет его в заголовке. Сервер хранит маппинг ключ → результат.

func CreatePayment(ctx context.Context, key string, req PaymentReq) (*Payment, error) {
    // проверяем, был ли уже такой запрос
    if cached, err := redis.Get(ctx, "idempotency:"+key); err == nil {
        return cached, nil
    }

payment, err := processPayment(ctx, req) if err != nil { return nil, err }

// сохраняем результат на 24 часа redis.Set(ctx, "idempotency:"+key, payment, 24*time.Hour) return payment, nil }

Альтернативы: UPSERT в БД (ON CONFLICT DO NOTHING), уникальный constraint на бизнес-ключ, версионирование ресурсов (optimistic locking). Для платежей idempotency key обязателен — Stripe, T-Bank, все платёжные системы его поддерживают. Храни результаты минимум 24 часа, потому что клиент может повторить запрос не сразу.

Следующий вопрос

Как внедрять зависимости в Go?