File size: 3,747 Bytes
826cc86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
110
111
from fastapi import APIRouter, UploadFile, File, Form, HTTPException
from fastapi.responses import FileResponse, JSONResponse
import os
import uuid
import aiofiles
from app.core.config import settings
from custom_logger import logger_config as logger
from app.db import crud
from app.services.worker import start_worker, is_worker_running

router = APIRouter()

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in settings.ALLOWED_EXTENSIONS

@router.get("/")
async def index():
    return FileResponse('index.html')

@router.post("/api/tasks/upload")
async def upload_task(image: UploadFile = File(...), hide_from_ui: str = Form("")):
    if not image.filename:
        raise HTTPException(status_code=400, detail="No file selected")
    
    if not allowed_file(image.filename):
        raise HTTPException(status_code=400, detail="Invalid file type")
    
    task_id = str(uuid.uuid4())
    filename = image.filename
    filepath = os.path.join(settings.UPLOAD_FOLDER, f"{task_id}_{filename}")
    
    try:
        async with aiofiles.open(filepath, 'wb') as out_file:
            content = await image.read()
            await out_file.write(content)
        logger.info(f"File uploaded successfully: {filename} -> {filepath}")
    except Exception as e:
        logger.error(f"Error saving uploaded file {filename}: {e}")
        raise HTTPException(status_code=500, detail="Could not save file")
    
    hide_from_ui_val = 1 if hide_from_ui.lower() in ['true', '1'] else 0
    
    await crud.insert_task(task_id, filename, filepath, 'not_started', hide_from_ui_val)
    
    await start_worker()
    
    return JSONResponse(status_code=201, content={
        'id': task_id,
        'filename': filename,
        'status': 'not_started',
        'message': 'File uploaded successfully'
    })

@router.get("/api/tasks")
async def get_tasks():
    rows, queue_ids, processing_count, avg_time = await crud.get_all_tasks()
    
    tasks = []
    for row in rows:
        queue_position = None
        estimated_start_seconds = None
        
        if row['status'] == 'not_started' and row['id'] in queue_ids:
            queue_position = queue_ids.index(row['id']) + 1
            tasks_ahead = queue_position - 1 + processing_count
            estimated_start_seconds = round(tasks_ahead * avg_time)
        
        tasks.append({
            'id': row['id'],
            'filename': row['filename'],
            'status': row['status'],
            'result': "HIDDEN_IN_LIST_VIEW",
            'created_at': row['created_at'],
            'processed_at': row['processed_at'],
            'progress': row['progress'] or 0,
            'progress_text': row['progress_text'],
            'queue_position': queue_position,
            'estimated_start_seconds': estimated_start_seconds
        })
    
    return tasks

@router.get("/api/tasks/{task_id}")
async def get_task(task_id: str):
    result = await crud.get_task_by_id(task_id)
    if not result:
        raise HTTPException(status_code=404, detail="Task not found")
        
    row, queue_position, estimated_start_seconds = result
    
    return {
        'id': row['id'],
        'filename': row['filename'],
        'status': row['status'],
        'result': row['result'],
        'created_at': row['created_at'],
        'processed_at': row['processed_at'],
        'progress': row['progress'] or 0,
        'progress_text': row['progress_text'],
        'queue_position': queue_position,
        'estimated_start_seconds': estimated_start_seconds
    }

@router.get("/health")
async def health():
    return {
        'status': 'healthy',
        'service': 'ocr-runner',
        'worker_running': is_worker_running()
    }