Avinashnalla7 commited on
Commit
d19344e
·
1 Parent(s): e0039b5

feat: process jobs; upload_pdf to sftp; status callbacks

Browse files
Files changed (2) hide show
  1. sftp_store.py +7 -0
  2. worker.py +50 -0
sftp_store.py CHANGED
@@ -80,3 +80,10 @@ def upload_bytes(remote_path: str, data: bytes) -> None:
80
  sftp.close()
81
  finally:
82
  transport.close()
 
 
 
 
 
 
 
 
80
  sftp.close()
81
  finally:
82
  transport.close()
83
+
84
+
85
+ def upload_pdf(pdf_id: str, data: bytes) -> str:
86
+ # Stores under: pdfs/{pdf_id}.pdf (relative to SFTP_ROOT)
87
+ remote_path = f"pdfs/{pdf_id}.pdf"
88
+ upload_bytes(remote_path, data)
89
+ return remote_path
worker.py CHANGED
@@ -1,8 +1,11 @@
1
  import os
2
  import time
 
3
  import threading
4
  import requests
5
  from http.server import BaseHTTPRequestHandler, HTTPServer
 
 
6
  from sftp_store import sftp_test
7
 
8
  import sftp_store
@@ -46,6 +49,53 @@ def serve_http():
46
  HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
47
 
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  def poll_loop():
50
  print("Worker polling started", flush=True)
51
 
 
1
  import os
2
  import time
3
+ import base64
4
  import threading
5
  import requests
6
  from http.server import BaseHTTPRequestHandler, HTTPServer
7
+
8
+ from sftp_store import upload_pdf
9
  from sftp_store import sftp_test
10
 
11
  import sftp_store
 
49
  HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
50
 
51
 
52
+ def _api_headers() -> dict:
53
+ # API expects X-Worker-Token (NOT Authorization Bearer)
54
+ return {"X-Worker-Token": WORKER_TOKEN}
55
+
56
+ def _job_status(job_id: str, status: str, message: str = "") -> None:
57
+ try:
58
+ requests.post(
59
+ f"{API_BASE}/api/jobs/{job_id}/status",
60
+ headers=_api_headers(),
61
+ json={"status": status, "message": message},
62
+ timeout=10,
63
+ )
64
+ except Exception as e:
65
+ print(f"status update failed: {e}", flush=True)
66
+
67
+ def process_job(job: dict) -> None:
68
+ # API returns job dict (asdict(Job)) => id field is the canonical one
69
+ jid = job.get("id") or job.get("job_id")
70
+ if not jid:
71
+ raise RuntimeError("job missing id/job_id")
72
+
73
+ payload = job.get("payload") or {}
74
+ action = payload.get("action")
75
+
76
+ if action == "upload_pdf":
77
+ pdf_id = payload.get("pdf_id")
78
+ pdf_b64 = payload.get("pdf_b64")
79
+ if not pdf_id or not pdf_b64:
80
+ raise RuntimeError("upload_pdf requires payload.pdf_id and payload.pdf_b64")
81
+
82
+ # decode
83
+ try:
84
+ pdf_bytes = base64.b64decode(pdf_b64)
85
+ except Exception as e:
86
+ raise RuntimeError(f"invalid base64 in pdf_b64: {e}")
87
+
88
+ # upload
89
+ remote_path = upload_pdf(pdf_id, pdf_bytes)
90
+ _job_status(jid, "done", f"uploaded:{remote_path}")
91
+ print(f"job {jid} done -> {remote_path}", flush=True)
92
+ return
93
+
94
+ # unknown action -> fail but don't crash loop
95
+ _job_status(jid, "failed", f"unknown action: {action}")
96
+ print(f"job {jid} failed: unknown action {action}", flush=True)
97
+
98
+
99
  def poll_loop():
100
  print("Worker polling started", flush=True)
101