File size: 2,828 Bytes
7158b5e
4f0eb4e
f84ed9c
598fc2d
f84ed9c
598fc2d
7158b5e
4f0eb4e
 
 
7158b5e
 
598fc2d
7158b5e
 
 
4f0eb4e
7158b5e
 
4f0eb4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7158b5e
4f0eb4e
 
 
 
 
 
598fc2d
7158b5e
 
cc65c05
 
 
 
 
938a5c7
cc65c05
 
 
f6d47a2
 
 
 
 
 
 
 
 
cc65c05
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import logging
import asyncio
import httpx
from app.config.settings import NOTE_SERVICE_URL


class NoteServiceClient:
    MAX_RETRIES = 3
    RETRY_DELAYS = [1, 2, 4]  # exponential backoff in seconds

    async def create_audio_note(self, payload: dict):
        """Call the Note Service to create an audio note.

        This method catches HTTP errors and logs them instead of raising,
        to avoid making transcription endpoints return 500 when the
        Note Service is unavailable or returns 4xx/5xx.
        Retries on 429 (rate limit) with exponential backoff.
        Returns parsed JSON on success or None on failure.
        """
        url = f"{NOTE_SERVICE_URL}/internal/notes/audio"
        
        for attempt in range(self.MAX_RETRIES):
            try:
                async with httpx.AsyncClient(timeout=30) as client:
                    r = await client.post(url, json=payload)
                    r.raise_for_status()
                    return r.json()
            except httpx.HTTPStatusError as exc:
                status = getattr(exc.response, "status_code", None)
                
                # Retry on 429 Too Many Requests
                if status == 429 and attempt < self.MAX_RETRIES - 1:
                    delay = self.RETRY_DELAYS[attempt]
                    logging.warning(
                        "NoteService rate limited (429), retrying in %ds (attempt %d/%d)",
                        delay, attempt + 1, self.MAX_RETRIES
                    )
                    await asyncio.sleep(delay)
                    continue
                
                logging.warning(
                    "NoteService returned HTTP %s for %s: %s",
                    status,
                    url,
                    exc,
                )
                return None
            except Exception as exc:  # network errors, timeouts, etc.
                logging.exception("Failed to call NoteService: %s", exc)
                return None
        
        return None

    async def save_transcript(self, payload: dict):
        # alias used elsewhere in the codebase
        return await self.create_audio_note(payload)
    
    async def update_note(self, note_id: str, payload: dict):
        async with httpx.AsyncClient(timeout=30) as client:
            r = await client.patch(
                f"{NOTE_SERVICE_URL}/notes/{note_id}",
                json=payload,
            )
            r.raise_for_status()
            return r.json()

    async def update_note_internal(self, note_id: str, payload: dict):
        async with httpx.AsyncClient(timeout=30) as client:
            r = await client.patch(
                f"{NOTE_SERVICE_URL}/internal/notes/{note_id}",
                json=payload,
            )
            r.raise_for_status()
            return r.json()