|
72 | 72 | PyInfo,
|
73 | 73 | ServerSettings,
|
74 | 74 | TaskStatusV0,
|
| 75 | + TaskStatusV1, |
75 | 76 | UserRecord,
|
76 | 77 | )
|
77 | 78 | from .timeouts import get_task_timeout, get_task_timeout_help_message
|
@@ -393,12 +394,26 @@ def system_caches_runtime_delete(self, target: DeleteInputDTO) -> DeleteOutputDT
|
393 | 394 | response = self._server.handle_bad_response(response)
|
394 | 395 | return response
|
395 | 396 |
|
396 |
| - def task_get(self, task_id: str, first_status: Optional[int] = None) -> TaskStatusV0: |
| 397 | + def task_get( |
| 398 | + self, |
| 399 | + task_id: str, |
| 400 | + first: Optional[int] = None, |
| 401 | + wait: Optional[int] = None, |
| 402 | + ) -> TaskStatusV1: |
397 | 403 | params = None
|
398 |
| - if first_status is not None: |
399 |
| - params = {"first_status": first_status} |
400 |
| - response = cast(Union[TaskStatusV0, HTTPResponse], self.get("tasks/%s" % task_id, query_params=params)) |
| 404 | + if first is not None or wait is not None: |
| 405 | + params = {} |
| 406 | + if first is not None: |
| 407 | + params["first"] = first |
| 408 | + if wait is not None: |
| 409 | + params["wait"] = wait |
| 410 | + response = cast(Union[TaskStatusV1, HTTPResponse], self.get("v1/tasks/%s" % task_id, query_params=params)) |
401 | 411 | response = self._server.handle_bad_response(response)
|
| 412 | + |
| 413 | + # compatibility with rsconnect-jupyter |
| 414 | + response["status"] = response["output"] |
| 415 | + response["last_status"] = response["last"] |
| 416 | + |
402 | 417 | return response
|
403 | 418 |
|
404 | 419 | def deploy(
|
@@ -467,76 +482,55 @@ def wait_for_task(
|
467 | 482 | log_callback: Optional[Callable[[str], None]],
|
468 | 483 | abort_func: Callable[[], bool] = lambda: False,
|
469 | 484 | timeout: int = get_task_timeout(),
|
470 |
| - poll_wait: float = 0.5, |
| 485 | + poll_wait: int = 1, |
471 | 486 | raise_on_error: bool = True,
|
472 |
| - ) -> tuple[list[str] | None, TaskStatusV0]: |
| 487 | + ) -> tuple[list[str] | None, TaskStatusV1]: |
473 | 488 | if log_callback is None:
|
474 | 489 | log_lines: list[str] | None = []
|
475 | 490 | log_callback = log_lines.append
|
476 | 491 | else:
|
477 | 492 | log_lines = None
|
478 | 493 |
|
479 |
| - last_status: int | None = None |
| 494 | + first: int | None = None |
480 | 495 | start_time = time.time()
|
481 |
| - sleep_duration = 0.5 |
482 |
| - time_slept = 0.0 |
483 | 496 | while True:
|
484 | 497 | if (time.time() - start_time) > timeout:
|
485 | 498 | raise RSConnectException(get_task_timeout_help_message(timeout))
|
486 | 499 | elif abort_func():
|
487 | 500 | raise RSConnectException("Task aborted.")
|
488 | 501 |
|
489 |
| - # we continue the loop so that we can re-check abort_func() in case there was an interrupt (^C), |
490 |
| - # otherwise the user would have to wait a full poll_wait cycle before the program would exit. |
491 |
| - if time_slept <= poll_wait: |
492 |
| - time_slept += sleep_duration |
493 |
| - time.sleep(sleep_duration) |
494 |
| - continue |
495 |
| - else: |
496 |
| - time_slept = 0 |
497 |
| - task_status = self.task_get(task_id, last_status) |
498 |
| - last_status = self.output_task_log(task_status, last_status, log_callback) |
499 |
| - if task_status["finished"]: |
500 |
| - result = task_status.get("result") |
501 |
| - if isinstance(result, dict): |
502 |
| - data = result.get("data", "") |
503 |
| - type = result.get("type", "") |
504 |
| - if data or type: |
505 |
| - log_callback("%s (%s)" % (data, type)) |
506 |
| - |
507 |
| - err = task_status.get("error") |
508 |
| - if err: |
509 |
| - log_callback("Error from Connect server: " + err) |
510 |
| - |
511 |
| - exit_code = task_status["code"] |
512 |
| - if exit_code != 0: |
513 |
| - exit_status = "Task exited with status %d." % exit_code |
514 |
| - if raise_on_error: |
515 |
| - raise RSConnectException(exit_status) |
516 |
| - else: |
517 |
| - log_callback("Task failed. %s" % exit_status) |
518 |
| - return log_lines, task_status |
| 502 | + task = self.task_get(task_id, first=first, wait=poll_wait) |
| 503 | + self.output_task_log(task, log_callback) |
| 504 | + first = task["last"] |
| 505 | + if task["finished"]: |
| 506 | + result = task.get("result") |
| 507 | + if isinstance(result, dict): |
| 508 | + data = result.get("data", "") |
| 509 | + type = result.get("type", "") |
| 510 | + if data or type: |
| 511 | + log_callback("%s (%s)" % (data, type)) |
| 512 | + |
| 513 | + err = task.get("error") |
| 514 | + if err: |
| 515 | + log_callback("Error from Connect server: " + err) |
| 516 | + |
| 517 | + exit_code = task["code"] |
| 518 | + if exit_code != 0: |
| 519 | + exit_status = "Task exited with status %d." % exit_code |
| 520 | + if raise_on_error: |
| 521 | + raise RSConnectException(exit_status) |
| 522 | + else: |
| 523 | + log_callback("Task failed. %s" % exit_status) |
| 524 | + return log_lines, task |
519 | 525 |
|
520 | 526 | @staticmethod
|
521 | 527 | def output_task_log(
|
522 |
| - task_status: TaskStatusV0, |
523 |
| - last_status: int | None, |
| 528 | + task: TaskStatusV1, |
524 | 529 | log_callback: Callable[[str], None],
|
525 | 530 | ):
|
526 |
| - """Pipe any new output through the log_callback. |
527 |
| -
|
528 |
| - Returns an updated last_status which should be passed into |
529 |
| - the next call to output_task_log. |
530 |
| -
|
531 |
| - Raises RSConnectException on task failure. |
532 |
| - """ |
533 |
| - new_last_status = last_status |
534 |
| - if task_status["last_status"] != last_status: |
535 |
| - for line in task_status["status"]: |
536 |
| - log_callback(line) |
537 |
| - new_last_status = task_status["last_status"] |
538 |
| - |
539 |
| - return new_last_status |
| 531 | + """Pipe any new output through the log_callback.""" |
| 532 | + for line in task["output"]: |
| 533 | + log_callback(line) |
540 | 534 |
|
541 | 535 |
|
542 | 536 | # for backwards compatibility with rsconnect-jupyter
|
@@ -601,8 +595,6 @@ def __init__(
|
601 | 595 |
|
602 | 596 | self.bundle: IO[bytes] | None = None
|
603 | 597 | self.deployed_info: RSConnectClientDeployResult | None = None
|
604 |
| - self.result: DeleteOutputDTO | None = None |
605 |
| - self.task_status: TaskStatusV0 | None = None |
606 | 598 |
|
607 | 599 | self.logger: logging.Logger | None = logger
|
608 | 600 | self.ctx = ctx
|
@@ -954,7 +946,7 @@ def emit_task_log(
|
954 | 946 | log_callback: logging.Logger = connect_logger,
|
955 | 947 | abort_func: Callable[[], bool] = lambda: False,
|
956 | 948 | timeout: int = get_task_timeout(),
|
957 |
| - poll_wait: float = 0.5, |
| 949 | + poll_wait: int = 1, |
958 | 950 | raise_on_error: bool = True,
|
959 | 951 | ):
|
960 | 952 | """
|
@@ -1207,10 +1199,10 @@ def delete_runtime_cache(self, language: Optional[str], version: Optional[str],
|
1207 | 1199 | self.result = result
|
1208 | 1200 | if result["task_id"] is None:
|
1209 | 1201 | print("Dry run finished")
|
| 1202 | + return result, None |
1210 | 1203 | else:
|
1211 |
| - (_, task_status) = self.client.wait_for_task(result["task_id"], connect_logger.info, raise_on_error=False) |
1212 |
| - self.task_status = task_status |
1213 |
| - return self |
| 1204 | + (_, task) = self.client.wait_for_task(result["task_id"], connect_logger.info, raise_on_error=False) |
| 1205 | + return result, task |
1214 | 1206 |
|
1215 | 1207 |
|
1216 | 1208 | class S3Client(HTTPServer):
|
@@ -1825,7 +1817,7 @@ def emit_task_log(
|
1825 | 1817 | log_callback: Optional[Callable[[str], None]],
|
1826 | 1818 | abort_func: Callable[[], bool] = lambda: False,
|
1827 | 1819 | timeout: int = get_task_timeout(),
|
1828 |
| - poll_wait: float = 0.5, |
| 1820 | + poll_wait: int = 1, |
1829 | 1821 | raise_on_error: bool = True,
|
1830 | 1822 | ):
|
1831 | 1823 | """
|
|
0 commit comments