homelab: runpod-lazy v5.1 background catalog prefetch
| @@ -107,6 +107,27 @@ def needed_files(values): | |||
| 107 | return files | 107 | return files |
| 108 | 108 | ||
| 109 | 109 | ||
| 110 | def all_catalog_files(): | ||
| 111 | files = [] | ||
| 112 | for entry in load_catalog().get('models', []): | ||
| 113 | files.extend(entry.get('files') or []) | ||
| 114 | return files | ||
| 115 | |||
| 116 | |||
| 117 | def prefetch_rest(pod_id): | ||
| 118 | """Queues every catalog file on the pod (background, non-priority) so later | ||
| 119 | model switches find the files already on disk.""" | ||
| 120 | files = all_catalog_files() | ||
| 121 | if not files: | ||
| 122 | return | ||
| 123 | try: | ||
| 124 | res = mm_request(pod_id, 'POST', '/ensure', {'files': files}, timeout=20) | ||
| 125 | if res.get('queued'): | ||
| 126 | log('background prefetch queued:', ', '.join(res['queued'])) | ||
| 127 | except Exception: | ||
| 128 | pass # old image without a model manager | ||
| 129 | |||
| 130 | |||
| 110 | def api(method, path, body=None): | 131 | def api(method, path, body=None): |
| 111 | req = urllib.request.Request( | 132 | req = urllib.request.Request( |
| 112 | f'https://rest.runpod.io/v1{path}', | 133 | f'https://rest.runpod.io/v1{path}', |
| @@ -251,7 +272,7 @@ def ensure_pod(values=None, wait=True): | |||
| 251 | state['last'] = time.monotonic() | 272 | state['last'] = time.monotonic() |
| 252 | if not ensured: | 273 | if not ensured: |
| 253 | try: | 274 | try: |
| 254 | mm_request(pod_id, 'POST', '/ensure', {'files': files}) | 275 | mm_request(pod_id, 'POST', '/ensure', {'files': files, 'priority': True}) |
| 255 | ensured = True | 276 | ensured = True |
| 256 | state['model'] = values_key(key_values(state['model']) | set(values)) | 277 | state['model'] = values_key(key_values(state['model']) | set(values)) |
| 257 | log(f'in-place ensure requested: {key}') | 278 | log(f'in-place ensure requested: {key}') |
| @@ -286,6 +307,11 @@ def ensure_pod(values=None, wait=True): | |||
| 286 | state['phase'] = 'green' | 307 | state['phase'] = 'green' |
| 287 | state['since'] = time.time() | 308 | state['since'] = time.time() |
| 288 | log('pod ready:', pod_id) | 309 | log('pod ready:', pod_id) |
| 310 | # Green on the needed set; everything else in the catalog | ||
| 311 | # downloads in the background for instant later switches. | ||
| 312 | if state.get('prefetch_pod') != pod_id: | ||
| 313 | state['prefetch_pod'] = pod_id | ||
| 314 | threading.Thread(target=prefetch_rest, args=(pod_id,), daemon=True).start() | ||
| 289 | return pod_id | 315 | return pod_id |
| 290 | if state['phase'] == 'green': | 316 | if state['phase'] == 'green': |
| 291 | state['phase'] = 'orange' # in-place download in progress | 317 | state['phase'] = 'orange' # in-place download in progress |