Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/quickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
client.create_sprite(os.environ["SPRITE_NAME"])

# step: Run Python
output = client.sprite(os.environ["SPRITE_NAME"]).command("python", "-c", "print(2+2)").output()
output = client.sprite(os.environ["SPRITE_NAME"]).command("python", "-c", "print(2+2)", timeout=30).output()
print(output.decode(), end="")

# step: Clean up
Expand Down
8 changes: 4 additions & 4 deletions src/sprites/checkpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,9 @@ def create_checkpoint(sprite: Sprite, comment: str = "") -> CheckpointStream:
if comment:
payload["comment"] = comment

# Use a separate client for streaming with no timeout
# Use a separate client for streaming with a generous timeout
with httpx.Client(
timeout=None,
timeout=300.0,
headers={"Authorization": f"Bearer {sprite.client.token}"},
) as client:
try:
Expand Down Expand Up @@ -269,9 +269,9 @@ def restore_checkpoint(sprite: Sprite, checkpoint_id: str) -> RestoreStream:
"""
url = f"{sprite.client.base_url}/v1/sprites/{sprite.name}/checkpoints/{checkpoint_id}/restore"

# Use a separate client for streaming with no timeout
# Use a separate client for streaming with a generous timeout
with httpx.Client(
timeout=None,
timeout=300.0,
headers={"Authorization": f"Bearer {sprite.client.token}"},
) as client:
try:
Expand Down
7 changes: 6 additions & 1 deletion src/sprites/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,12 @@ def _cleanup_on_exit() -> None:
return

try:
from sprites.loop import get_loop, stop_loop
from sprites.loop import get_loop, stop_loop, _loop

# Don't create a new loop just for cleanup — if the loop was already
# stopped by loop.py's atexit handler, just skip cleanup
if _loop is None:
return

loop = get_loop()
future = asyncio.run_coroutine_threadsafe(_close_all_pools(), loop)
Expand Down