runpod-lazy: no churn on unknown pod model; adopt existing pod on proxy restart
| @@ -163,7 +163,9 @@ def ensure_pod(value=None, wait=True): | ||
| 163 | 163 | pod_id, have, gpu = (state['pod_id'], state['model'], state['gpu']) |
| 164 | 164 | if not pod_id: |
| 165 | 165 | pod_id, have, gpu = find_pod() |
| 166 | - if pod_id and value and have != value: | |
| 166 | + # Only recreate when the pod's model is KNOWN and different. An unknown | |
| 167 | + # model (e.g. env not reported yet) must not churn pods. | |
| 168 | + if pod_id and value and have and have != value: | |
| 167 | 169 | log(f'pod has model={have}, need {value} - recreating') |
| 168 | 170 | terminate(pod_id) |
| 169 | 171 | pod_id, have, gpu = None, None, None |
| @@ -305,8 +307,9 @@ class Proxy(BaseHTTPRequestHandler): | ||
| 305 | 307 | catalog = {'models': payload.get('models', []), 'active': payload.get('active')} |
| 306 | 308 | save_catalog(catalog) |
| 307 | 309 | log(f"catalog updated: {len(catalog['models'])} models, active={catalog['active']}") |
| 308 | 310 | # Re-provision proactively when the active model changed under a live pod. |
| 309 | - if state['pod_id'] and catalog['active'] and state['model'] != catalog['active']: | |
| 311 | + # (known-model pods only - never churn a pod of unknown provenance). | |
| 312 | + if state['pod_id'] and catalog['active'] and state['model'] and state['model'] != catalog['active']: | |
| 310 | 313 | log('active model changed - re-provisioning pod') |
| 311 | 314 | threading.Thread(target=self._safe_ensure, args=(catalog['active'],), daemon=True).start() |
| 312 | 315 | return self._reply(200, status_body()) |
| @@ -357,6 +360,19 @@ class Proxy(BaseHTTPRequestHandler): | ||
| 357 | 360 | |
| 358 | 361 | def main(): |
| 359 | 362 | threading.Thread(target=idle_reaper, daemon=True).start() |
| 363 | + # Adopt a pre-existing pod (e.g. after a proxy restart mid-provisioning) so | |
| 364 | + # its readiness wait - which also feeds the idle timer - keeps running. | |
| 365 | + pod_id, have, gpu = find_pod() | |
| 366 | + if pod_id: | |
| 367 | + state.update({'pod_id': pod_id, 'model': have, 'gpu': gpu, 'phase': 'orange', 'last': time.monotonic()}) | |
| 368 | + log(f'adopting existing pod {pod_id} (model={have})') | |
| 369 | + | |
| 370 | + def _adopt(): | |
| 371 | + try: | |
| 372 | + ensure_pod(have) | |
| 373 | + except Exception as err: | |
| 374 | + log('adoption wait failed:', err) | |
| 375 | + threading.Thread(target=_adopt, daemon=True).start() | |
| 360 | 376 | server = ThreadingHTTPServer(('0.0.0.0', LISTEN_PORT), Proxy) |
| 361 | 377 | log(f'runpod-lazy v3 (catalog) on :{LISTEN_PORT} (pod "{POD_NAME}", DCs {DATACENTERS or "any"}, idle {IDLE_SECONDS}s)') |
| 362 | 378 | server.serve_forever() |