Ë
    |v…jX
  ã                   ó¨  — U d Z ddlZddlZddlZddlZddlmZmZ ddlmZ  ee	«      j                  dz  Zej                  d¬«       i Zeeej                   f   ed<    ej                   «       Zd	ed
ej                   fd„Zd	ed
efd„Zd	ed
efd„Zddee   dedz  d
efd„Zd	ed
efd„Zd	efd„Zd	ed
edz  fd„Zd	ed
efd„Zd	efd„Zd
ee   fd„Zy)uJ  
Job storage: each uploaded file becomes a "job" with its own isolated
directory (named by a random UUID, never derived from user input) containing
the raw upload, the cleaned/rejected Parquet outputs, and a status file.

Kept intentionally simple (filesystem + JSON status file) for an MVP that's
easy to self-host. For heavier production use, swap the in-memory job lock
and background-thread execution for a real task queue (Celery/RQ/Arq) and
the status file for a row in Postgres/Redis â€” the interface here (`create_job`,
`get_status`, `set_status`) is small enough to swap out.
é    N)ÚdatetimeÚtimezone)ÚPathÚdataT)Úexist_okÚ_locksÚjob_idÚreturnc                 ó’   — t         5  | t        vrt        j                  «       t        | <   t        |    cd d d «       S # 1 sw Y   y xY w©N)Ú_locks_guardr   Ú	threadingÚLock©r	   s    ú*/var/www/html/lead-cleaner/backend/jobs.pyÚ	_job_lockr      s.   € Þ	ØœÑÜ&Ÿ^™^Ó-ŒF�6‰NÜ�f‰~÷ 
�Šús	   ‡,=½Ac                 ó   — t         | z  }|S r   )ÚDATA_DIR©r	   Úds     r   Újob_dirr   "   s   € ô 	�6Ñ€AØ€Hó    c                 ó   — t        | «      dz  S )NÚinputs©r   r   s    r   Ú
inputs_dirr   )   s   € Ü�6‹?˜XÑ%Ð%r   Úoriginal_filenamesÚ
created_byc           	      ó"  — t        j                  «       j                  }t        |«      }|j	                  dd¬«       |dz  j	                  «        t        |d| |t        j                  t        j                  «      j                  «       ¬«       |S )NTF)Úparentsr   r   Úpending)Ústatusr   r   Ú
created_at)ÚuuidÚuuid4Úhexr   ÚmkdirÚ
set_statusr   Únowr   ÚutcÚ	isoformat)r   r   r	   r   s       r   Ú
create_jobr,   -   sp   € Ü�Z‰Z‹\×Ñ€FÜ�‹€AØ‡G�G�D 5€GÔ)Øˆ�\×ÑÔÜØØØ-ØÜ—<‘<¤§¡Ó-×7Ñ7Ó9õð €Mr   c                 ó   — t        | «      dz  S )Nzstatus.jsonr   r   s    r   Ústatus_pathr.   <   s   € Ü�6‹?˜]Ñ*Ð*r   c                 ó¢  — t        | «      5  t        | «      }i }|j                  «       r#t        j                  |j                  «       «      }|j                  |«       t        j                  t        j                  «      j                  «       |d<   |j                  t        j                  |t        ¬«      «       d d d «       y # 1 sw Y   y xY w)NÚ
updated_at)Údefault)r   r.   ÚexistsÚjsonÚloadsÚ	read_textÚupdater   r)   r   r*   r+   Ú
write_textÚdumpsÚstr)r	   ÚfieldsÚpÚexistings       r   r(   r(   @   s…   € Ü	�6Õ	Ü˜ÓˆØˆØ�8‰8Œ:Ü—z‘z !§+¡+£-Ó0ˆHØ�‰˜ÔÜ!)§¡¬h¯l©lÓ!;×!EÑ!EÓ!Gˆ�ÑØ	�‰”T—Z‘Z ´#Ô6Ô7÷ 
×	Ñ	ús   ŒB0CÃCc                 ó€   — t        | «      }|j                  «       sy t        j                  |j	                  «       «      S r   )r.   r2   r3   r4   r5   )r	   r;   s     r   Ú
get_statusr>   K   s-   € Ü�FÓ€AØ�8‰8Œ:ØÜ�:‰:�a—k‘k“mÓ$Ð$r   c                 ó4   — t        | «      j                  «       S r   )r   r2   r   s    r   Ú
job_existsr@   R   s   € Ü�6‹?×!Ñ!Ó#Ð#r   c                 óÆ   — t        | «      }|j                  «       rt        j                  |«       t        5  t
        j                  | d «       d d d «       y # 1 sw Y   y xY wr   )r   r2   ÚshutilÚrmtreer   r   Úpopr   s     r   Ú
delete_jobrE   V   s;   € Ü�‹€AØ‡x�x„zÜ�‰�aÔÞ	Ü�
‰
�6˜4Ô ÷ 
�‰ús   ·AÁA c                  ó†   — t         j                  «       D � cg c]  } | j                  «       sŒ| j                  ‘Œ! c} S c c} w r   )r   ÚiterdirÚis_dirÚname)r;   s    r   Ú	list_jobsrJ   ^   s1   € Ü$×,Ñ,Ô.Ó=Ñ.�q°!·(±(µ*ˆA�F‹FÐ.Ñ=Ð=ùÒ=s   —>­>r   )Ú__doc__r3   rB   r$   r   r   r   Úpathlibr   Ú__file__Úparentr   r'   r   Údictr9   r   Ú__annotations__r   r   r   r   Úlistr,   r.   r(   r>   Úboolr@   rE   rJ   © r   r   Ú<module>rT      s+  ðò
ó Û Û Û ß 'Ý á�‹>× Ñ  6Ñ)€Ø ‡�˜€Ô à$&€ˆˆS�)—.‘.Ð Ñ!Ó &Øˆy�~‰~Ó€ð�cð ˜iŸn™nó ð�Cð ˜Dó ð&�sð &˜tó &ñ 4¨¡9ð ¸#À¹*ð ÐPSó ð+˜ð + ó +ð8�só 8ð%�sð %˜t d™{ó %ð$�sð $˜tó $ð!�só !ð>�4˜‘9ô >r   