cortexgrid 0.3.3__tar.gz → 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cortexgrid
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: Connect your ML code to the RoboLab compute cluster — Ray, MLflow, and S3
5
5
  Project-URL: Homepage, https://github.com/robodatalab/cortexgrid
6
6
  Project-URL: Repository, https://github.com/robodatalab/cortexgrid
@@ -485,6 +485,25 @@ def _clear_failed_application(
485
485
  time.sleep(_SERVING_POLL_INTERVAL_S)
486
486
 
487
487
 
488
+ def _spec_already_deployed(spec: dict[str, Any]) -> bool:
489
+ """True when this exact spec is already the app's target, so PUTting it
490
+ again would only disturb the controller.
491
+
492
+ Re-PUTting is not a no-op. While an app's build task is in flight its target
493
+ code version is unset, so Ray cancels that build and starts a new one no
494
+ matter what the config says - and since every PUT re-sends the whole
495
+ applications list, it restarts the in-flight builds of the other apps too.
496
+ Our build task downloads the model bundle and may create a pip virtualenv,
497
+ so a caller redeploying faster than that could keep it from ever finishing.
498
+
499
+ A DEPLOY_FAILED or DELETING app never reaches here: `_clear_failed_application`
500
+ has already removed it, and an identical PUT over a failed app is exactly the
501
+ no-op that leaves it failed.
502
+ """
503
+ app = get_serve_details().get("applications", {}).get(spec["name"])
504
+ return app is not None and app.get("deployed_app_config") == spec
505
+
506
+
488
507
  def deploy_model(
489
508
  family: str,
490
509
  suffix: str,
@@ -507,6 +526,11 @@ def deploy_model(
507
526
  or an app still DELETING, is waited out before the new spec is PUT, so the
508
527
  deploy starts afresh instead of Ray reusing the failed deployment.
509
528
 
529
+ Re-deploying a model that is already live with exactly this spec skips the
530
+ PUT rather than restating it: see `_spec_already_deployed` for what a
531
+ redundant PUT costs. The call still reports the app's phase, and with
532
+ `wait=True` still blocks until it is RUNNING.
533
+
510
534
  With `wait=True`, blocks as `wait_for_model_serving` does until the Serve
511
535
  controller reports the app RUNNING. `timeout` (default 300) caps the whole
512
536
  call, clearing a failed app included; exceeding it raises TimeoutError, and
@@ -520,11 +544,14 @@ def deploy_model(
520
544
  family, suffix, run_name, meta, requirements, num_replicas
521
545
  )
522
546
  _clear_failed_application(family, suffix, run_name, timeout, deadline)
523
- existing = [a for a in _current_application_specs() if a["name"] != spec["name"]]
524
- # The controller registers the app, sets it DEPLOYING and stamps
525
- # last_deployed_time_s before the PUT returns, so the wait below neither
526
- # misses the app nor reads a status left by an earlier deploy.
527
- put_serve_applications([*existing, spec])
547
+ if not _spec_already_deployed(spec):
548
+ existing = [
549
+ a for a in _current_application_specs() if a["name"] != spec["name"]
550
+ ]
551
+ # The controller registers the app, sets it DEPLOYING and stamps
552
+ # last_deployed_time_s before the PUT returns, so the wait below neither
553
+ # misses the app nor reads a status left by an earlier deploy.
554
+ put_serve_applications([*existing, spec])
528
555
  if wait:
529
556
  _wait_for_application_running(spec["name"], timeout, deadline)
530
557
  app = get_serve_details().get("applications", {}).get(spec["name"], {})
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cortexgrid"
3
- version = "0.3.3"
3
+ version = "0.3.4"
4
4
  description = "Connect your ML code to the RoboLab compute cluster — Ray, MLflow, and S3"
5
5
  readme = "docs/cortexgrid/README.md"
6
6
  license = "Apache-2.0"
File without changes
File without changes