Skip to content

Conversation

@jvstme
Copy link

@jvstme jvstme commented Feb 9, 2026

Add wait_for_status parameter to InstancesService.create, similar to ClustersService.create. Setting wait_for_status=None allows to return from the method immediately.

Resolves #79

Add `InstancesService.create_nowait` method that
returns immediately after sending a create request
to the API.
@huksley
Copy link
Contributor

huksley commented Feb 9, 2026

Good idea!

Can this be rewritten to support the same syntax as for clusters, i.e.

...instance.create(
            # Set to None to not wait for provisioning but return immediately
            wait_for_status=verda_client.constants.cluster_status.PROVISIONING
)

@jvstme
Copy link
Author

jvstme commented Feb 9, 2026

@huksley, even with wait_for_status=None, ClustersService.create still issues two API calls: POST /clusters followed by GET /clusters/<id>. We could implement the same behavior for instances, but ideally we’d like to avoid the second request so we never end up in the following situation:

  • POST /instances — success
  • GET /instances/<id> — error (API error, network issue, etc.)
  • Result: the instance is created and starts accumulating charges, but its ID is never returned by InstancesService.create, leaving the application unaware of its existence.

Here are a few possible ways to address this:

  1. Introduce a separate InstancesService.create_nowait method that does not call GET /instances/<id> (as proposed in this PR).

  2. Make the return type of InstancesService.create depend on the wait_for_status parameter:

    • If wait_for_status is set, return an Instance.
    • If wait_for_status is None, return the instance ID as str (since POST /instances only returns the ID).

    Or introduce a separate parameter to control the return type.

  3. Update the REST API so POST /instances returns a full Instance object. Since this is not backward-compatible, this would require either a new API version (/v2) or an opt-in mechanism via a request parameter.

Please let me know if any of these options seem reasonable, or if you have alternative suggestions.

@huksley
Copy link
Contributor

huksley commented Feb 10, 2026

Would it be ok if instance.create() with with wait_for_status=None would return instance populated with ID and values passed as request payload? that way, no get instance method will be needed

@jvstme
Copy link
Author

jvstme commented Feb 10, 2026

@huksley, InstancesService.create doesn't have enough details to populate all instance fields, including price_per_hour, status, created_at, cpu, gpu, memory, etc.

@jvstme
Copy link
Author

jvstme commented Feb 10, 2026

@huksley, I’ve added the wait_for_status parameter as you initially suggested. For now, I think we can live with the extra GET /instances/<id> call. This still isn’t ideal, since instance loss remains possible, but it’s less likely than before. We’d appreciate it if this could be improved further in the future, possibly by returning the full instance object from POST /instances.

I also had to add support for callables in wait_for_status; otherwise, it wouldn’t be backward compatible with the existing behavior, which checks for status != ordered instead of waiting for a specific status.

payload['pricing'] = pricing
id = self._http_client.post(INSTANCES_ENDPOINT, json=payload).text

if not wait_for_status:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this completely change logic because it will not wait for status but immediately return instance without wait_for_status set?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, wait_for_status is set to lambda s: s != InstanceStatus.ORDERED, which means the method doesn't return here and nothing changes for existing users that are not setting wait_for_status.

For those users that will decide to set wait_for_status=None, the method will return here immediately, which is the expected behavior.

The implementation is consistent with ClustersService.create.

@huksley huksley requested a review from Copilot February 11, 2026 13:42
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates instance creation to optionally skip polling/waiting for a status transition after the create request.

Changes:

  • Added a wait_for_status kw-only parameter to InstancesService.create to control whether/how to wait for a desired status.
  • Updated polling logic to support either a specific status or a predicate callable.
  • Added unit tests covering different wait_for_status behaviors.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
verda/instances/_instances.py Adds wait_for_status parameter and adjusts create polling/early-return logic.
tests/unit_tests/instances/test_instances.py Adds parameterized tests validating new waiting behavior for create.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pricing: Pricing | None = None,
coupon: str | None = None,
*,
wait_for_status: str | Callable[[str], bool] | None = lambda s: s != InstanceStatus.ORDERED,
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title/description says it adds InstancesService.create_nowait, but the diff only changes create() by introducing wait_for_status. Either add the described create_nowait method (e.g., a small wrapper calling create(..., wait_for_status=None)), or update the PR metadata to reflect the actual API change.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the description

pricing: Pricing | None = None,
coupon: str | None = None,
*,
wait_for_status: str | Callable[[str], bool] | None = lambda s: s != InstanceStatus.ORDERED,
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait_for_status is typed as str | Callable[[str], bool], but the code/tests appear to use InstanceStatus values (and instance.status is compared to InstanceStatus). This should be typed consistently (e.g., InstanceStatus | Callable[[InstanceStatus], bool] | None) to avoid misleading API contracts and type-checking issues.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InstanceStatus is a namespace for str constants. The actual type passed to wait_for_status is str and not InstanceStatus

Comment on lines +217 to 221
if callable(wait_for_status):
if wait_for_status(instance.status):
return instance
elif instance.status == wait_for_status:
return instance
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait_for_status is typed as str | Callable[[str], bool], but the code/tests appear to use InstanceStatus values (and instance.status is compared to InstanceStatus). This should be typed consistently (e.g., InstanceStatus | Callable[[InstanceStatus], bool] | None) to avoid misleading API contracts and type-checking issues.

Suggested change
if callable(wait_for_status):
if wait_for_status(instance.status):
return instance
elif instance.status == wait_for_status:
return instance
status_value = getattr(instance.status, 'value', instance.status)
if callable(wait_for_status):
if wait_for_status(status_value):
return instance
else:
target_status = getattr(wait_for_status, 'value', wait_for_status)
if status_value == target_status:
return instance

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InstanceStatus is a namespace for str constants. The actual type passed to wait_for_status is str and not InstanceStatus

contract: Optional contract type for the instance.
pricing: Optional pricing model for the instance.
coupon: Optional coupon code for discounts.
wait_for_status: Status to wait for the instance to reach, or callable that returns True when the desired status is reached. Default to any status other than ORDERED. If None, no wait is performed.
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: change 'Default to' to 'Defaults to' for readability.

Suggested change
wait_for_status: Status to wait for the instance to reach, or callable that returns True when the desired status is reached. Default to any status other than ORDERED. If None, no wait is performed.
wait_for_status: Status to wait for the instance to reach, or callable that returns True when the desired status is reached. Defaults to any status other than ORDERED. If None, no wait is performed.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current docstring is based on and consistent with ClustersService.create

@jvstme jvstme requested a review from huksley February 11, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow creating instances without waiting

2 participants