| """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]] = [ |
| ] |
|
|
|
|
| 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]) |
| |
| 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.""" |
| |
| asyncio.create_task(batch_translate()) |
| yield |
| |
|
|
|
|
| |
| 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) |
|
|
|
|
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| @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 |