|
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