bichnhan2701 commited on
Commit
4f0eb4e
·
1 Parent(s): b55d9e8

Add exponential backoff

Browse files
Files changed (1) hide show
  1. app/services/note_client.py +37 -19
app/services/note_client.py CHANGED
@@ -1,37 +1,55 @@
1
  import logging
 
2
  import httpx
3
  from app.config.settings import NOTE_SERVICE_URL
4
 
5
 
6
  class NoteServiceClient:
 
 
 
7
  async def create_audio_note(self, payload: dict):
8
  """Call the Note Service to create an audio note.
9
 
10
  This method catches HTTP errors and logs them instead of raising,
11
  to avoid making transcription endpoints return 500 when the
12
  Note Service is unavailable or returns 4xx/5xx.
 
13
  Returns parsed JSON on success or None on failure.
14
  """
15
- try:
16
- async with httpx.AsyncClient(timeout=30) as client:
17
- r = await client.post(
18
- f"{NOTE_SERVICE_URL}/internal/notes/audio",
19
- json=payload,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  )
21
- r.raise_for_status()
22
- return r.json()
23
- except httpx.HTTPStatusError as exc:
24
- status = getattr(exc.response, "status_code", "?")
25
- logging.warning(
26
- "NoteService returned HTTP %s for %s: %s",
27
- status,
28
- f"{NOTE_SERVICE_URL}/internal/notes/audio",
29
- exc,
30
- )
31
- return None
32
- except Exception as exc: # network errors, timeouts, etc.
33
- logging.exception("Failed to call NoteService: %s", exc)
34
- return None
35
 
36
  async def save_transcript(self, payload: dict):
37
  # alias used elsewhere in the codebase
 
1
  import logging
2
+ import asyncio
3
  import httpx
4
  from app.config.settings import NOTE_SERVICE_URL
5
 
6
 
7
  class NoteServiceClient:
8
+ MAX_RETRIES = 3
9
+ RETRY_DELAYS = [1, 2, 4] # exponential backoff in seconds
10
+
11
  async def create_audio_note(self, payload: dict):
12
  """Call the Note Service to create an audio note.
13
 
14
  This method catches HTTP errors and logs them instead of raising,
15
  to avoid making transcription endpoints return 500 when the
16
  Note Service is unavailable or returns 4xx/5xx.
17
+ Retries on 429 (rate limit) with exponential backoff.
18
  Returns parsed JSON on success or None on failure.
19
  """
20
+ url = f"{NOTE_SERVICE_URL}/internal/notes/audio"
21
+
22
+ for attempt in range(self.MAX_RETRIES):
23
+ try:
24
+ async with httpx.AsyncClient(timeout=30) as client:
25
+ r = await client.post(url, json=payload)
26
+ r.raise_for_status()
27
+ return r.json()
28
+ except httpx.HTTPStatusError as exc:
29
+ status = getattr(exc.response, "status_code", None)
30
+
31
+ # Retry on 429 Too Many Requests
32
+ if status == 429 and attempt < self.MAX_RETRIES - 1:
33
+ delay = self.RETRY_DELAYS[attempt]
34
+ logging.warning(
35
+ "NoteService rate limited (429), retrying in %ds (attempt %d/%d)",
36
+ delay, attempt + 1, self.MAX_RETRIES
37
+ )
38
+ await asyncio.sleep(delay)
39
+ continue
40
+
41
+ logging.warning(
42
+ "NoteService returned HTTP %s for %s: %s",
43
+ status,
44
+ url,
45
+ exc,
46
  )
47
+ return None
48
+ except Exception as exc: # network errors, timeouts, etc.
49
+ logging.exception("Failed to call NoteService: %s", exc)
50
+ return None
51
+
52
+ return None
 
 
 
 
 
 
 
 
53
 
54
  async def save_transcript(self, payload: dict):
55
  # alias used elsewhere in the codebase