Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Bug: Idempotency Key Not Checked Before Processing in order_service

Chiusa
#10 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

@kushpatel2601 ci sta già lavorando.

Dal 25/2/2026.

  • #11 di @kushpatel2601 — chiusa senza merge

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
58/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
flask, mysql, python
Ambito
api, backend, databases

Direzione di ricerca

Inizia in order_service/app.py, in create_order(), soprattutto nella gestione di Idempotency-Key e nella ricerca nella tabella orders descritta nell’issue. Esegui docker compose up -d --build e riproduci la richiesta duplicata POST /api/v1/orders per osservare le chiamate esterne e la prenotazione delle scorte. Il lavoro è completato quando una chiave ripetuta restituisce l’id e lo stato originali con HTTP 200 e non causa chiamate a servizi esterni né effetti collaterali sulle scorte.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Bug: Idempotency Key Not Checked Before Processing in order_service

Summary

The POST /api/v1/orders endpoint accepts an Idempotency-Key header to prevent duplicate order creation. However, the key is only enforced at the database INSERT level via a UNIQUE KEY constraint — after all expensive and side-effectful operations have already been executed. This means duplicate requests will call the User Service, call the Product Service, and reserve stock before ultimately failing at the DB insert, leaving the inventory in a corrupted state.


Affected File

  • order_service/app.py → create_order() function

Steps to Reproduce

  1. Start all services with docker compose up -d --build.
  2. Login and obtain a JWT token via POST /api/v1/login.
  3. Send POST /api/v1/orders with a valid body and an Idempotency-Key: test-key-123 header.
  4. Immediately send the exact same request again with the same Idempotency-Key: test-key-123.
  5. Observe that on the second request, the system still calls the Product Service and reserves stock again before returning an error.

Expected Behavior

If an Idempotency-Key is provided and a matching order already exists in the database, the endpoint should:

  • Return the original order's response (id + status) immediately with HTTP 200.
  • Skip all external service calls — no User Service call, no Product Service call, no stock reservation.
  • Be a pure no-op with zero side effects.

Actual Behavior

The duplicate request goes through the full execution pipeline:

  1. ✅ Idempotency key is read from the header.
  2. ❌ No early DB lookup is performed.
  3. ❌ User Service is called unnecessarily.
  4. ❌ Product Service is called unnecessarily.
  5. ❌ Stock is reserved again for all items in the order.
  6. ❌ DB INSERT fails with a UNIQUE KEY constraint violation.
  7. ❌ Stock that was just reserved is released (rollback), but this adds extra load and a race condition window.

Root Cause

In order_service/app.py, inside create_order(), the Idempotency-Key is read early but never looked up in the database until the INSERT statement:

# Line 105 — key is read
idmp_key = request.headers.get('Idempotency-Key')

Lines 111–210 — full business logic runs regardless of whether key is duplicate:

user validation → address validation → product validation → stock reservation → DB insert

The UNIQUE KEY constraint on the idempotency_key column only prevents the duplicate record from being saved — it does not prevent the side effects that already happened before the insert.


Fix

Add an early database lookup for the Idempotency-Key immediately after reading it, before any external service calls:

idmp_key = request.headers.get('Idempotency-Key')

Check idempotency key FIRST — before any external service calls

if idmp_key:
conn = get_db_connection()
if not conn:
return jsonify({'error': 'Database connection failed'}), 500
try:
cur = conn.cursor(dictionary=True)
cur.execute(
"SELECT id, status FROM orders WHERE idempotency_key = %s LIMIT 1",
(idmp_key,)
)
existing = cur.fetchone()
finally:
conn.close()
if existing:
# Return the original order response — idempotent, no side effects
return jsonify({'id': existing['id'], 'status': existing['status']}), 200


Impact

Scenario Before Fix After Fix
Duplicate request with same key Reserves stock again, then fails Returns cached response immediately ✅
Network retry by client May cause double stock deduction Safely returns original order ✅
First-time request Works normally Works normally ✅
Request without key Works normally Works normally ✅

Severity: 🔴 Critical — In a production environment with retrying clients or unreliable networks, this bug can cause inventory to be incorrectly decremented on every duplicate request, leading to stock going negative or orders being unfulfillable.


Environment

  • Service: order_service
  • Language: Python 3 / Flask
  • Database: MySQL 8.0
  • Relevant endpoint: POST /api/v1/orders
Lingua principale
Python
Stelle
3
Fork
8
Merge medio
1h 6m
PR unite (30g)
3

Preparare l'ambiente

  • Include un Dockerfile o un file Docker Compose
  • Nessun modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di keploy/ecommerce_sample_app

Tutte le issue di keploy/ecommerce_sample_app

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.