File size: 3,685 Bytes
ba7290b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""Main app file for the translation service"""
from contextlib import asynccontextmanager
from typing import List, Tuple

import asyncio
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel

from translate import translate_batch_async

class TranslateRequest(BaseModel):
    sourceLangCode: str
    targetLangCode: str
    textArray: List[str]

active_translation_requests: List[Tuple[str, str, List[str], asyncio.Future]] = [
]  # a list to store translation requests


async def process_translation(
    src_lang: str, tgt_lang: str, textArr: List[str]
) -> List[str]:
    future = asyncio.get_running_loop().create_future()
    active_translation_requests.append(
        (src_lang, tgt_lang, textArr, future))
    result = await future
    return result

async def batch_translate():
    """Background task that processes queued translation requests."""
    global active_translation_requests

    while True:
        if active_translation_requests:
            requestsProcessingNow = len(active_translation_requests)
            results = await translate_batch_async(
                [src for src, _, _, _ in active_translation_requests],
                [tgt for _, tgt, _, _ in active_translation_requests],
                [text for _, _, text, _ in active_translation_requests]
            )

            for i, (_, _, _, future) in enumerate(active_translation_requests[:requestsProcessingNow]):
                future.set_result(results[i])
            # remove the processed tasks:
            active_translation_requests = active_translation_requests[requestsProcessingNow:]
        else:
            await asyncio.sleep(0.1)


@asynccontextmanager
async def lifespan(app_instance: FastAPI):
    """Lifespan context manager for startup and shutdown events."""
    # Startup: Launch the batch translation background task
    asyncio.create_task(batch_translate())
    yield
    # Shutdown: Clean up (if needed in the future)


# Define a FastAPI app with lifespan
app = FastAPI(lifespan=lifespan)

@app.exception_handler(Exception)
async def exception_handler(request, exc):
    """Handle exceptions"""
    error_data = {
        'status': 'failure',
        'error': 'An unexpected error occurred'
    }
    return JSONResponse(content=error_data, status_code=500)


# # Serve static files
# app.mount("/static", StaticFiles(directory="static"), name="static")

# @app.get("/")
# def index():
#     """Serve UI page"""
#     return FileResponse("templates/index.html")

# @app.get("/favicon.svg")
# def favicon():
#     "Serve favicon"
#     return FileResponse("static/favicon.svg", media_type="image/svg+xml")

@app.post("/api/translate")
async def api_translate(data: TranslateRequest):
    """
    Endpoint to handle batch translation requests.
    Args:
        data (TranslateRequest): The request payload containing:
            - sourceLangCode: FLORES code for the source language.
            - targetLangCode: FLORES code for the target language.
            - textArray: List of strings to translate.   
    Returns:
        dict: A dictionary containing the translation status and the translated array.
    """
    try:
        task = asyncio.create_task(process_translation(
            data.sourceLangCode, data.targetLangCode, data.textArray))
        await task
        translation_array = task.result()

        return { 'status': 'success', 
            'data': {'translationArray': translation_array}}

    except Exception as e:
        raise HTTPException(status_code=500, detail="An error occurred during translation") from e