
    UjD                       d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZmZ ddlmZ ddlmZmZmZmZmZ  ed      Z ed      Z ed	      Z ed
      ZdZdZ e	j<                          d ej>                          Z  ejB                  d      Z"d Z#d Z$d Z%d Z& G d de'      Z( G d de)      Z*d Z+d Z,d Z-d Z.d Z/d Z0d Z1d Z2d Z3d  Z4d! Z5e6d"k(  r e5        yy)#zLAutonomous YouTube Research E2E worker and independent completion validator.    )annotationsN)datetimetimezone	timedelta)Path)NativeTranscriptUnavailable	QuotaWaitTransientSupadataErroraccount_statusfetch_nativez+/opt/struktur/youtube-research/knowledge.dbz;/opt/struktur/content-extraction/data/content_extraction.dbz0/opt/obsidian-vault/YouTube-Research/Automatischz'/opt/struktur/youtube-research/.e2e-tmpze2e-extraction-v1zcontent-validator-v2:zyoutube-e2ec                 d    t        j                  t        j                        j	                         S N)r   nowr   utc	isoformat     /tmp/e2e_worker.pyr   r      s    (,,x||,6688r   c                f    t        j                  | j                  d            j                         S )Nutf-8)hashlibsha256encode	hexdigest)ss    r   shar      s"    7>>!((7"34>>@@r   c                     t        j                  t        dd       } t         j                  | _        | j                  d       | j                  d       | S )N   )timeoutisolation_levelPRAGMA busy_timeout=10000zPRAGMA foreign_keys=ON)sqlite3connectDBRowrow_factoryexecute)cs    r   connr*      s=    oob"d;A7;;Q]II)*AII6N,OXYQYr   c                     dd l } | j                          t               }dD ]  }|j                  d|z           |j                          y # t        j
                  $ r Y ?w xY w)Nr   )zclassification TEXTzrejection_reason TEXTzmetrics_json TEXTzvalidator_version TEXTz&ALTER TABLE e2e_rejections ADD COLUMN )dbinit_dbr*   r(   r#   OperationalErrorclose)r,   r)   cols      r   ensure_schemar1      sV    JJL
fAk .YY?CD. GGI ''--s   AA! A!c                       e Zd Z fdZ xZS )ContentRejectc                @    || _         || _        t        |   |       y r   )classificationmetricssuper__init__)selfr5   r6   	__class__s      r   r8   zContentReject.__init__"   s    *DL(r   )__name__
__module____qualname__r8   __classcell__)r:   s   @r   r3   r3   !   s    ) )r   r3   c                      e Zd Zy)TranscriptFetchErrorN)r;   r<   r=   r   r   r   r@   r@   &   s    r   r@   c           
     \   ddl | D cg c]L  }|d   j                         st        j                  dd|d   j	                               j                         N }}t        j
                  d|j	                               }t        t        |            }|t        t        t        |      d      d      z  }t        t        |            t        t        |      d      z  }t        |      t        t        |            z
  }t        fd	t        ||dd       D              t        t        |      dz
  d      z  }	t        j                  d
|      D 
cg c]/  }
t        |
j                               dk\  s |
j                         1 }}
t        d |D              t        t        |      d      z  }t        d |D              t        t        |      d      z  }|dkD  xr9 |dk  xr2 |	dkD  xs |dk  xr$ t        |      t        dt        |       dz        k  }t        d|z
  d      t        |d      t        |d      |t        |	d      t        |d      t        |       t        |      t        d	}|rd|fS |dk  s
|	dkD  s|dk  rd|fS |dk  st        |      dk  rd|fS d|fS c c}w c c}
w )zBGeneral content-value check; no single keyword decides the result.r   N   z\s+ u   [a-zA-ZÀ-ÿÄÖÜäöüß]{3,}i     c              3  l   K   | ]+  \  }}j                  d ||      j                         dk\   - y w)Ng=
ףp=?)SequenceMatcherratio).0abdifflibs      r   	<genexpr>z#content_classify.<locals>.<genexpr>1   s2     aSQq((a288:D@as   14(?<=[.!?])\s+-   c              3  v   K   | ]1  }t        t        j                  d |j                                      3 yw)u   \b(weil|daher|deshalb|schritt|zuerst|dann|how|because|therefore|first|then|install|config|api|system|methode|prozess|funktion|problem|lösung|is|are|will|can)\bN)boolresearchlowerrH   xs     r   rL   z#content_classify.<locals>.<genexpr>3   sO       i  Z[d299  &I  JK  JQ  JQ  JS  T  U  is   79c              3  *   K   | ]  }|d v sd  yw)u   ♪♫🎵🎶rD   Nr   rT   s     r   rL   z#content_classify.<locals>.<genexpr>4   s     >1-=(=Q>s   	gMb`?g)\(?gQ?g
ףp=
?      )	repeat_ratiounique_segment_ratiolexical_diversityduplicate_segment_countadjacent_similarity_ratioinformational_sentence_ratiosegment_countsentence_countvalidator_versionnon_informational_musicg?gffffff?g
ףp=
?repetitive_low_informationg333333?uncertain_contentinformational)rK   striprQ   subrS   findalllensetmaxminsumzipsplitroundVALIDATOR_VERSION)segstextr   cleanwordsunique_wordslexicalunique_segmentsduplicate_countadjacentrU   	sentencesre   symbol_ratiomusic_shaper6   rK   s                   @r   content_classifyr~   )   s   <@
QqAaDJJL266&QqTZZ\*002
QE
Q
**7


EESZL,s3s5z$;OPQ7R*R'E
OCE
1$55OJs3u:.OaCPUV[\]\^V_L`aabefijofpqrfrstbuuH"$((+;D"AXQS^UWEWqwwyXIX  i  _h  i  i  jm  nq  r{  n|  }~  j  M>>>s3t9Q?OOLe#  I  I(4-:_?[_K_  Iehirestwxyz}  C  {D  FH  {H  uI  fIK!!O"3A6eTcdeNf  |A  BI  JK  |L  gv  SX  Ya  bc  Sd  DI  JW  XY  DZ  kn  os  kt  FI  JS  FT  iz  {G4W<<tx}EabiEi>iTS^A-6I'6Q/Q7"" R Ys   J$8J$!J)5J)c                6   | j                  dt               f      j                         }|syt               }|j	                  d      dk7  s|j	                  d      Mt
        j                  d       |d   dk7  r/| j                  d	t               |d
   f       | j                          y|d   dk  r8|d   dk7  r/| j                  dt               |d
   f       | j                          y| j                  d       | j                  dt               t               t               |d
   f      }|j                  dk7  r| j                          y| j                  d       | j                  d|d
   f      j                         }t
        j                  d|d
   |d          |S # t        j                  $ rf}dt        |      j                         vrdt        |      j                         vr | j                          t
        j                  d       Y d}~yd}~ww xY w)zBReserve one queued Supadata job, with a one-credit safety reserve.zSELECT * FROM e2e_jobs WHERE status IN ('queued','supadata_retry','supadata_quota_wait') AND (local_retry_after IS NULL OR local_retry_after<=?) ORDER BY priority,job_id LIMIT 1Nhttp   	availablez8Supadata account status unavailable; job remains waitingstatussupadata_quota_waitzUPDATE e2e_jobs SET status='supadata_quota_wait',step='quota_wait',updated_at=?,error_code='account_status_unavailable',error_message='Supadata account status unavailable' WHERE job_id=? AND status IN ('queued','supadata_retry')job_idrD   zUPDATE e2e_jobs SET status='supadata_quota_wait',step='quota_wait',updated_at=?,error_code='quota_reserve',error_message='Supadata quota reserve active' WHERE job_id=? AND status IN ('queued','supadata_retry')zBEGIN IMMEDIATElockedbusyz3database busy during reserve; retrying on next polla  UPDATE e2e_jobs SET status='supadata_processing',step='supadata_fetch',attempts=attempts+1,started_at=COALESCE(started_at,?),reserved_at=?,updated_at=?,lease_until=NULL,error_code=NULL,error_message=NULL WHERE job_id=? AND status IN ('queued','supadata_retry','supadata_quota_wait')COMMITz%SELECT * FROM e2e_jobs WHERE job_id=?z2job %s reserved for Supadata Native (available=%s))r(   r   fetchoner   getLOGerrorcommitr#   r.   strrS   rollbackwarningrowcountinfo)r)   rowacctexchangeds        r   reserver   <   s}   			  F  HK  HM  GO  	P  	Y  	Y  	[Ct		Dxx3$((;"7"?		LMx=11II  }  B  D  EH  IQ  ER  ~S  T  VW  V^  V^  V`KAx=11II  j  lo  lq  ru  v~  r  k@  A  CD  CK  CK  CM	
$	% II  s  ux  uz  {~  {@  AD  AF  GJ  KS  GT  tU  VG1ajjl4IIh			93x=:JKTTVCHHA3x=RVWbRcdJ ## f3r7==?*vSW]]_/Le	

ckk"WXaefs   )F H2AHHc                4    t        |       }|j                  |fS r   )r   segments)yidresults     r   fetch_segmentsr   V   s    F??F""r   c                l   dj                  d |D              }t        j                  d|      D cg c]/  }t        |j	                               dkD  s |j	                         1 }}dj                  |d d       |d d g g g g g g g g g |D cg c]  }|d   |d   |d	   |d
   d c}d}|S c c}w c c}w )NrC   c              3  &   K   | ]	  }|d      ywrB   Nr   rT   s     r   rL   zextract.<locals>.<genexpr>\   s     %1!A$%   rM            r   rD      rB   )
segment_idstartendrs   )summary
key_pointsfactstechnical_details
proceduresreasonswarningsexamplesopen_questionstopicskeywordssource_spans)joinrQ   ro   ri   rf   )r   rr   rs   rU   r{   r   payloads          r   extractr   [   s2   	%%	%DRXXN^_cEd1zhklmlslsluhvwyhy!'')1zy1zxx	"1.IcrNSUkm|~  KM  Z\  ik  ~@  KM  Z\  os  mt  jk  |}  ~  |@  IJ  KL  IM  TU  VW  TX  `a  bc  `d  ne  mt  uGN 2{ mts   !B,B,B1c                   t         j                  dd       t        j                  dd       g }t         j                  d      D ]T  }	 t	        j
                  dt	        j                  | d          d|j                  d            r|j                  |       V t        |      d	kD  rt        d
      |rt        |d         S t	        j                  dd| d   xs | d         d d j                  d      }t         | d    d| dz  }t        j                   ddt              \  }}	t#        j$                  |       dd| d    dt'        j(                  | d   xs dd       dt'        j(                  | d   xs dd       d| d    d| d   xs d dt+                d| d | d!t,         d"| d   xs | d    d#|d$    d%z   d&j/                  d' |d(   D              z   d)z   d&j/                  d* |d+   D              z   d&z   }
t1        |	      j3                  |
d,-       t#        j4                  |	|       t        |      S # t        $ r Y w xY w).NT)parentsexist_okz*.md(?im)^youtube_id:\s*
youtube_id\s*$ignoreerrorsrD   duplicate_obsidianr   z[^a-zA-Z0-9_-]+-titleP   z.mdz.e2e-)prefixsuffixdirz---
zyoutube_id: z
title:  F)ensure_asciiz

channel: channelz-
source_url: https://www.youtube.com/watch?v=z
published_at: published_atz
processed_at: z
transcript_hash: z
content_hash: z
extraction_version: z$
processing_status: complete
---

# z

## Kurzfassung
r   z

## Zentrale Aussagen

c              3  &   K   | ]	  }d |   yw)z- Nr   rT   s     r   rL   z!write_obsidian.<locals>.<genexpr>k   s7       W@	  ef  Z\  ]^  \_  X`  W@	r   r   z

## Quellenstellen
c           
   3  T   K   | ]   }d |d    d|d   dd|d   dd|d     " y	w)
z
- Segment r   z (r   z.2fu   s–r   zs): rs   Nr   rT   s     r   rL   z!write_obsidian.<locals>.<genexpr>k   s       d	X  {
|
  g	q	  r	s	  t	@
  r	A
  q	B
  B
D
  E
F
  G
N
  E
O
  P
S
  D
T
  T
X
  Y
Z
  [
`
  Y
a
  b
e
  X
f
  f
j
  k
l
  m
s
  k
t
  j
u
  e	v
  d	Xs   &(r   r   )encoding)VAULTmkdirTMPrglobrQ   rR   escape	read_textappendOSErrorri   RuntimeErrorr   rg   rf   tempfilemkstemposr/   jsondumpsr   VERSIONr   r   
write_textreplace)r   r   thchmatchespslugtargetfdtmpcontents              r   write_obsidianr   `   s   	KKdK+SYYtTY-RG[[  	yy03|;L1M0NdSTUT_T_goT_Tpqsz  tB  tB  CD  tE 7|A~\*>??s71:&	"3G(IL8I	KCR	P	V	VWZ	[DC%&avS11F(:J:JRYafkn:o62cqsqyqyz|q}l3|#4"5Ytzz#g,J\Z\jo?p>qq|  ~B  ~H  ~H  IL  MV  IW  I]  []  kp  ~q  }r  r`  ad  eq  ar  `s  sC  DG  HV  DW  D]  []  C^  ^n  or  ot  nu  uH  IK  HL  L\  ]_  \`  `v  w~  v  g  hk  ls  ht  hI  x{  |H  xI  gJ  J^  _f  gp  _q  ^r  rL  M  M  NR  NW  NW  W@	  jq  r~  j  W@	  N@	  @	  A	Z	  Z	  [	_	  [	d	  [	d	  d	X  @G  HV  @W  d	X  [	X  X  Y]  ]GI'2BJJs64JSVW]S^L^ s   
AH??	IIc                    	 ddl }|j                  j                  dd       ddlm}  ||        y# t
        $ r t        j                  d       Y yw xY w)zJBest-effort local enqueue; Graphiti is deliberately never on the hot path.r   Nz/opt/struktur/graphiti)enqueuez7graphiti enqueue failed; reconciliation will recover it)syspathinsertyoutube_graphiti_queuer   	Exceptionr   	exception)r   video_idr   r   s       r   register_graphitir   n   sF    Q342 QOPQs   .1 AAc                   t        j                  t        d      }|j                  d       dD ]  }|j                  d|z           |j                  d| d   | d   | d	   | d
   | d   d| d    d|t               || d   xs d| d   xs d| d   xs d||t        t               f       |j                          |j                          y # t         j                  $ r Y w xY w)Nr   r    r"   )zdescription TEXTztranscript TEXTztranscript_hash TEXTzcontent_hash TEXTzextraction_version TEXTzprocessed_at TEXTz"ALTER TABLE ce_sources ADD COLUMN aE  INSERT INTO ce_sources(source_system,source_video_id,youtube_id,title,channel,published_at,youtube_url,transcript_status,obsidian_artifact_path,imported_at,source_snapshot_hash,summary,description,transcript,transcript_hash,content_hash,extraction_version,processed_at) VALUES('youtube-research',?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(source_system,source_video_id) DO UPDATE SET youtube_id=excluded.youtube_id,title=excluded.title,description=excluded.description,transcript=excluded.transcript,obsidian_artifact_path=excluded.obsidian_artifact_path,transcript_status=excluded.transcript_status,source_snapshot_hash=excluded.source_snapshot_hash,summary=excluded.summary,transcript_hash=excluded.transcript_hash,content_hash=excluded.content_hash,extraction_version=excluded.extraction_version,processed_at=excluded.processed_atidr   r   r   r    https://www.youtube.com/watch?v=completer   r   description
transcript)	r#   r$   CE_DBr(   r.   r   r   r   r/   )r   r   r   r   r)   r0   s         r   sync_cer   x   s   ooeB'A3N)O O .YY;C?@. II  V  X[  \`  Xa  be  fr  bs  tw  x  t@  AD  EN  AO  PS  Tb  Pc  fF  GJ  KW  GX  FY  dZ  [e  fj  kn  kp  qs  tw  xA  tB  tH  FH  IL  MZ  I[  Ia  _a  be  fr  bs  by  wy  z|  }  @G  HK  HM  WN  OHHJ	 ''--s   C

C C c                *   t        |      }|j                         xr t        ||d         }t        j                  t
              }|j                  dd|d   f      j                         }	|j                          |xr |	xr |	d   |k(  xr |	d   dk(  S )Nr   zkSELECT obsidian_artifact_path,transcript_status FROM ce_sources WHERE source_system=? AND source_video_id=?zyoutube-researchr   r   rD   r   )	r   existsrow_idr#   r$   r   r(   r   r/   )
r)   jobr   r   r   r   r   okcerU   s
             r   validater     s    
4jAQXXZ?F1S->$?"uB  -Z  \n  or  s}  o~  [  "@  "I  "I  "Kq  MO  MU  MU  MW7!7!d
7qtZ'77r   c                    t        t        j                  dt        j                  |       d| j	                  d                  S )Nr   r   r   r   )rP   rQ   rR   r   r   )r   ys     r   r   r      s9    RYY*>ryy|nD'QRSR]R]emR]Rnoppr   c                   t               }|j                  d| d   f      j                         }	 t        |d         \  }}dj	                  d |D              }t        |      dk  st        |      dk  rt        d      t        ||      \  }}|d	k7  rt        ||      t        |      }t        ||      }	t        j                  |	d
d      }
t        |
      }|j                  d       |j                  d|d   f       |j                  d|D cg c]  }|d   t        |d         |d   f c}       |j                  d||t               |d   f       ddlm} ddlm}  ||d         rD ||d   xs |d   |d   xs d|      }|r'|j                  d||d   f       t)        |      }||d<   |j                  d       t+        ||	||      }t-        ||||       t/        ||d          |j                  d|d   |d   t0        |||
|t               f       |j                  dt               | d   f       dd l}|j5                  d d!t7        | d         gd"#      j8                  dk7  rt;        d$      |j                  d%t               t               | d   f       |j[                          y c c}w # t        $ r}|j=                          |j>                  }|j                  d&|d   d'|d    |||t        j                  |j@                  d(      tB        f       |j                  d)t               t               |t        j                  |j@                  d(      | d   f       Y d }~d }~wtD        $ r}|j=                          |j                  d*t               |d   f       |j                  d+t               t               t7        |      d d | d   f       |jG                          Y d }~Td }~wtH        $ r}|j=                          tK        j                  tL        jN                        tQ        d,-      z   jS                         }|j                  d.t               |t7        |      d d/ | d   f       |jG                          Y d }~d }~wtT        $ r}|j=                          tK        j                  tL        jN                        tQ        d0-      z   jS                         }|j                  d1t               ||jV                  rd2|jV                   nd3t7        |      d d | d   f       |jG                          Y d }~d }~wtX        $ rG}|j=                          |j                  d4t               t7        |      d d5 | d   f       Y d }~d }~wt        $ rt}|j=                          t7        |      }|j                  d6|d   d'|d    ||tB        f       |j                  d)t               t               ||| d   f       Y d }~sd }~wt:        $ rV}|j=                          |j                  d7t               t7        |      d d5 | d   f       Y d }~|j[                          y d }~wt\        $ r\}|j=                          |j                  d7t               t7        |      d d5 | d   f       t^        ja                  d8       Y d }~3d }~ww xY w# |j[                          w xY w)9NzSELECT * FROM videos WHERE id=?r   r   rC   c              3  &   K   | ]	  }|d      ywr   r   )rH   r   s     r   rL   zprocess.<locals>.<genexpr>   s     I]ST!A$I]r   i  r   technically_unusablere   FT)r   	sort_keysBEGINz0DELETE FROM transcript_segments WHERE video_id=?r   zJINSERT INTO transcript_segments(video_id,start_seconds,text) VALUES(?,?,?)rD   rB   zUPDATE videos SET transcript=?,transcript_hash=?,transcript_status='done',transcript_source='supadata_native',transcript_updated_at=? WHERE id=?r   )generate_summary)is_stale_fallbackr   r   r   r   zCUPDATE videos SET summary=?,updated_at=CURRENT_TIMESTAMP WHERE id=?r   zINSERT OR REPLACE INTO e2e_extractions(video_id,youtube_id,extraction_version,transcript_hash,content_hash,payload_json,obsidian_path,processed_at) VALUES(?,?,?,?,?,?,?,?)z]UPDATE e2e_jobs SET status='validation_pending',step='validation',updated_at=? WHERE job_id=?r   z./opt/struktur/youtube-research/venv/bin/pythonz//opt/struktur/youtube-research/e2e_validator.pyr   r   validation_failedzqUPDATE e2e_jobs SET status='complete',step='complete',completed_at=?,updated_at=?,lease_until=NULL WHERE job_id=?zINSERT OR REPLACE INTO e2e_rejections(youtube_id,url,reason,classification,rejection_reason,metrics_json,validator_version) VALUES(?,?,?,?,?,?,?)r   )r	  zUPDATE e2e_jobs SET status='rejected_no_usable_transcript',step='rejected',completed_at=?,updated_at=?,lease_until=NULL,error_code=?,error_message=? WHERE job_id=?zUPDATE videos SET transcript_status='unavailable',transcript_source=NULL,transcript_updated_at=? WHERE id=? AND (transcript IS NULL OR trim(transcript)='')zUPDATE e2e_jobs SET status='supadata_native_unavailable',step='supadata_terminal',completed_at=?,updated_at=?,lease_until=NULL,error_code='native_unavailable',error_message=? WHERE job_id=?r   )minuteszUPDATE e2e_jobs SET status='supadata_quota_wait',step='quota_wait',updated_at=?,local_retry_after=?,lease_until=NULL,error_code='quota_wait',error_message=? WHERE job_id=?r   r   zUPDATE e2e_jobs SET status='supadata_retry',step='supadata_retry',updated_at=?,local_retry_after=?,lease_until=NULL,error_code=?,error_message=? WHERE job_id=?supadata_http_supadata_transient_errorzUPDATE e2e_jobs SET status=CASE WHEN attempts>=3 THEN 'blocked_transcript_fetch' ELSE 'queued' END,step='transcript_error',updated_at=?,lease_until=NULL,error_code='transcript_fetch_error',error_message=? WHERE job_id=?i  zqINSERT OR REPLACE INTO e2e_rejections(youtube_id,url,reason,rejection_reason,validator_version) VALUES(?,?,?,?,?)zUPDATE e2e_jobs SET status=CASE WHEN attempts>=3 THEN 'discarded_after_processing_error' ELSE 'queued' END,step='error',updated_at=?,lease_until=NULL,error_code='processing_error',error_message=? WHERE job_id=?z
job failed)1r*   r(   r   r   r   ri   
ValueErrorr~   r3   r   r   r   r   executemanyrp   r   summary_generatorr  summary_lifecycler  dictr   r   r   r   
subprocessrunr   
returncoder   r   r5   r6   rq   r   r   r	   r   r   r   r   r   r
   r   r@   r/   r   r   r   )r   r)   r   rr   native_metars   r5   r6   r   r   rawr   r   r  r  freshr   r  r   reasonretrys                        r   processr     s   
fA!))=s:>PQZZ\cp'L(9:[I]X\I]A]Dt9S=CIaKz:P/Q)Q/T:w_,M.QX4Y.Yt9gc$/gTZZUZei5jorsvowln			'AII&XZ]^bZcYef	b  KO  dP  FGehimenotuvwxuyoz{|}~{  eA  dP  	Q  ST  S\  S\  ]o  qu  vx  y|  y~  B  CG  H  pI  SJ67S^,"3w<#D3|3Dc-FXF^\^`deEaii eglmpqumvfwx  C  DG  Hz}  Y^  JM  NW  JX			(C2.DB0GIZ[_`cdp`qIr			  @  BE  FJ  BK  LO  P\  L]  ^e  fh  ik  lo  pt  ux  uz  A{  	|			qsvsxy|  ~F  zG  sH  	I>>KL}  B  CF  GO  CP  Q  R  []>  ^  i  i  mn  n  vB  CV  vW  pW			  F  HK  HM  NQ  NS  TW  X`  Ta  Gb  	cz WWYS dP  
	

  			$ L!23|3D2EFvf

2::5!		
 	
		: U35

2:: Ec(mT	
 	
 ' 	

			  p  ru  rw  x{  |@  xA  qB  	C			  R  TW  TY  Z]  Z_  `c  df  `g  hl  il  `m  nq  rz  n{  S|  	}	

 	

||HLL))B*??JJL			  @  BE  BG  HM  NQ  RT  NU  VZ  WZ  N[  \_  `h  \i  Aj  	k	

! 	

||HLL))A*>>IIK			  t  vy  v{  |A  bd  bk  bk  DR  SU  S\  S\  R]  B^  qK  LO  PR  LS  TX  UX  LY  Z]  ^f  Zg  uh  	i	

 
	

 	
		
 U3r75D>#h-0	
 	
  
	

2w 	
		  L!23|3D2EFv/			
 	
		: U35s8}5	
 	
  		

			K U3r75D>#h-0	
 	 WWY  x	

aii  !u  wz  w|  }@  AC  }D  EJ  FJ  }K  LO  PX  LY  vZ  [  ]`  ]j  ]j  kw  ]x  ]xxWWYs   C!J5 J0
/E0J5 0J5 5	[>B*M-([ -[9A4O3-[ 3[?BR
[ [B'U	[ 	[<V[ [#A)X[ [<Y/[ /[;A[[ [[ [,c                 H   t        j                  t         j                         t                t        j                  d       	 t               } 	 t        |       }| j                          |rt        |       nt        j                  d       J# | j                          w xY w)N)levelzworker startedr   )loggingbasicConfigINFOr1   r   r   r*   r   r/   r  timesleep)r)   js     r   mainr'     sk    gll+]_chhGW>X
F	
AGGIgajjjm 
 GGIs   B B!__main__)7__doc__
__future__r   r   r   r!  r   rQ   shutilsocketr#   r   r$  r   r   r   pathlibr   supadata_nativer   r	   r
   r   r   r%   r   r   r   r   rq   gethostnamegetpidWORKER	getLoggerr   r   r   r*   r1   r  r3   r   r@   r~   r   r   r   r   r   r   r  r   r  r'  r;   r   r   r   <module>r3     s   R " N N N N N 2 2  x x	
78JK?@
45
* F !9299;-	0g& 8 @Z)J )
	< 	#&4#

_Q8 qrh	 Zr   