> Как реализовать взаимодействие фронтенда и бэкенда для генерации тяжелого отчета без таймаута (Python)

Уровень: senior · Роль: backend · Язык: Python · Категория: Технические вопросы

Компании: JEDai

Стек: Python

> Пример ответа

Для генерации тяжелого отчета без таймаута используем асинхронный подход с очередью задач. Основная идея: клиент отправляет запрос на создание отчета, бэкенд ставит задачу в очередь (например, через Celery или RQ), а фронтенд периодически опрашивает статус через отдельный эндпоинт.

Пример реализации на Python с Celery и Redis:

  1. Бэкенд (Flask + Celery):
PYTHON
from flask import Flask, request, jsonify
from celery import Celery
app = Flask(__name__)
celery = Celery(app.name, broker='redis://localhost:6379/0')
@celery.task(bind=True, max_retries=3)
def generate_report(self, params):
# Тяжелая генерация отчета
report_data = long_running_computation(params)
return {'status': 'completed', 'data': report_data}
@app.route('/api/report', methods=['POST'])
def create_report():
task = generate_report.delay(request.json)
return jsonify({'task_id': task.id}), 202
@app.route('/api/report/<task_id>', methods=['GET'])
def get_report_status(task_id):
task = generate_report.AsyncResult(task_id)
if task.state == 'PENDING':
response = {'status': 'pending'}
elif task.state == 'FAILURE':
response = {'status': 'failed', 'error': str(task.info)}
elif task.state == 'SUCCESS':
response = {'status': 'completed', 'data': task.result}
return jsonify(response)
  1. Фронтенд (JavaScript):
JAVASCRIPT
async function generateReport(params) {
const response = await fetch('/api/report', {
method: 'POST',
body: JSON.stringify(params)
});
const { task_id } = await response.json();
// Polling каждые 2 секунды
while (true) {
const statusResponse = await fetch(`/api/report/${task_id}`);
const result = await statusResponse.json();
if (result.status === 'completed') {
displayReport(result.data);
break;
} else if (result.status === 'failed') {
showError(result.error);
break;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
}

Дополнительные оптимизации:

  • Используйте WebSocket вместо polling для реального времени
  • Сохраняйте готовый отчет в S3/локальное хранилище и отдавайте ссылку
  • Установите разумный TTL для задач в Celery (например, result_expires=3600)
  • Для очень больших отчетов используйте стриминг через StreamingResponse в Flask

Этот подход гарантирует отсутствие таймаута, так как HTTP-запросы короткие, а тяжелая работа выполняется в фоне.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью