-
Notifications
You must be signed in to change notification settings - Fork 53
Add Lightwheel fetching asset retry handling #731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+174
−14
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Copyright (c) 2025-2026, The Isaac Lab Arena Project Developers (https://github.com/isaac-sim/IsaacLab-Arena/blob/main/CONTRIBUTORS.md). | ||
| # All rights reserved. | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| import time | ||
| from collections.abc import Callable | ||
| from typing import Any | ||
|
|
||
| _MISSING = object() | ||
|
|
||
|
|
||
| def acquire_lightwheel_asset( | ||
| loader: Any, | ||
| acquire_fn: Callable, | ||
| description: str, | ||
| attempts: int = 3, | ||
| timeout_sec: int | None = 60, | ||
| delay_sec: float = 2.0, | ||
| **kwargs, | ||
| ): | ||
| """Acquire a Lightwheel asset with scoped timeout and retry handling.""" | ||
|
|
||
| assert attempts > 0, "attempts must be positive" | ||
| assert delay_sec >= 0, "delay_sec must be non-negative" | ||
|
|
||
| client = getattr(loader, "client", None) | ||
| old_timeout = getattr(client, "base_timeout", _MISSING) | ||
| for attempt in range(1, attempts + 1): | ||
| try: | ||
| if timeout_sec is not None and old_timeout is not _MISSING: | ||
| client.base_timeout = timeout_sec | ||
| return acquire_fn(**kwargs) | ||
| except Exception as exc: | ||
| if not _looks_like_timeout(exc) or attempt == attempts: | ||
| raise | ||
| print(f"[isaaclab-arena] {description} timed out; retrying {attempt + 1}/{attempts} in {delay_sec:g}s.") | ||
| if delay_sec > 0: | ||
| time.sleep(delay_sec) | ||
| finally: | ||
| if old_timeout is not _MISSING: | ||
| client.base_timeout = old_timeout | ||
|
|
||
| raise AssertionError("unreachable") | ||
|
|
||
|
|
||
| def _looks_like_timeout(exc: BaseException) -> bool: | ||
| """Return whether an exception is a timeout.""" | ||
| current: BaseException | None = exc | ||
| while current is not None: | ||
| text = f"{type(current).__name__}: {current}".lower() | ||
| if "timeout" in text or "timed out" in text: | ||
| return True | ||
| current = current.__cause__ or current.__context__ | ||
|
xyao-nv marked this conversation as resolved.
|
||
| return False | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # Copyright (c) 2025-2026, The Isaac Lab Arena Project Developers (https://github.com/isaac-sim/IsaacLab-Arena/blob/main/CONTRIBUTORS.md). | ||
| # All rights reserved. | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
|
|
||
| from isaaclab_arena.assets.lightwheel_utils import acquire_lightwheel_asset | ||
|
|
||
|
|
||
| def test_acquire_lightwheel_asset_fetches_object(): | ||
| loader_module = pytest.importorskip("lightwheel_sdk.loader") | ||
| object_loader = loader_module.object_loader | ||
| old_timeout = object_loader.client.base_timeout | ||
|
|
||
| file_path, object_name, metadata = acquire_lightwheel_asset( | ||
| object_loader, | ||
| object_loader.acquire_by_registry, | ||
| "microwave asset", | ||
| attempts=2, | ||
| delay_sec=0, | ||
| registry_type="fixtures", | ||
| file_name="Microwave039", | ||
| file_type="USD", | ||
| ) | ||
|
|
||
| assert Path(file_path).exists() | ||
| assert object_name == "Microwave039" | ||
| assert metadata["fileName"].startswith("Microwave039") | ||
| assert object_loader.client.base_timeout == old_timeout | ||
|
|
||
|
|
||
| def test_acquire_lightwheel_asset_retries_timeout_failure(): | ||
| class Client: | ||
| base_timeout = 10 | ||
|
|
||
| class Loader: | ||
| def __init__(self): | ||
| self.client = Client() | ||
| self.calls = 0 | ||
| self.timeouts_seen = [] | ||
|
|
||
| def acquire(self, **kwargs): | ||
| self.calls += 1 | ||
| self.timeouts_seen.append(self.client.base_timeout) | ||
| if self.calls == 1: | ||
| raise TimeoutError("read timed out") | ||
| return kwargs["asset_name"] | ||
|
|
||
| loader = Loader() | ||
|
|
||
| result = acquire_lightwheel_asset( | ||
| loader, | ||
| loader.acquire, | ||
| "test asset", | ||
| attempts=2, | ||
| timeout_sec=45, | ||
| delay_sec=0, | ||
| asset_name="foo", | ||
| ) | ||
|
|
||
| assert result == "foo" | ||
| assert loader.calls == 2 | ||
| assert loader.timeouts_seen == [45, 45] | ||
| assert loader.client.base_timeout == 10 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.