"""Independent Punchblog loopback readiness lab; no external services.""" import json import argparse from datetime import datetime, timezone import threading import urllib.request import urllib.error from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path worker_stop = threading.Event() worker = threading.Thread(target=lambda: worker_stop.wait(), daemon=True) worker.start() dependency = {'available': True} class Handler(BaseHTTPRequestHandler): def do_GET(self): live = worker.is_alive() ready = live and dependency['available'] status = 200 if self.path == '/healthz' or self.path == '/readyz' and ready else 503 body = json.dumps({'http_process_responding': True, 'worker_alive': live, 'dependency_available': dependency['available'], 'ready': ready}).encode() self.send_response(status); self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(body))); self.end_headers(); self.wfile.write(body) def log_message(self, *_): pass server = ThreadingHTTPServer(('127.0.0.1', 0), Handler) thread = threading.Thread(target=server.serve_forever, daemon=True); thread.start() lab = [] def sample(phase): for path in ['/healthz', '/readyz']: try: response = urllib.request.urlopen(f'http://127.0.0.1:{server.server_port}{path}', timeout=2) except urllib.error.HTTPError as e: response = e with response: lab.append({'phase': phase, 'path': path, 'status': response.code, 'body': json.load(response)}) try: sample('healthy') dependency['available'] = False; sample('dependency_unavailable') dependency['available'] = True; worker_stop.set(); worker.join(1); sample('worker_stopped') worker_stop = threading.Event() worker = threading.Thread(target=lambda: worker_stop.wait(), daemon=True); worker.start() sample('recovered') finally: worker_stop.set(); worker.join(1); server.shutdown(); server.server_close(); thread.join(1) assert [r['status'] for r in lab] == [200, 200, 200, 503, 200, 503, 200, 200] parser = argparse.ArgumentParser() parser.add_argument('--output', required=True) args = parser.parse_args() output = Path(args.output) if output.exists(): raise SystemExit('Output exists; choose a new path') record = {'observed_at': datetime.now(timezone.utc).isoformat(), 'observations': lab} output.write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') print('PASS: 8 loopback responses; own server and workers stopped')