Skip to content
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

Mocking retries? #96

Open
jamesperez2005 opened this issue Jan 7, 2024 · 3 comments
Open

Mocking retries? #96

jamesperez2005 opened this issue Jan 7, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@jamesperez2005
Copy link

I'm trying to mock a service that is supposed to be called multiple times and fail, and then succeed at the Nth time. Since these are retries the requests should be the same, so there's no way to distinguish them by parameters or by path/body.

Is that something that can be done with httpmock?

@alexliesenfeld
Copy link
Owner

alexliesenfeld commented Jan 7, 2024

Hi @jamesperez2005 , thanks for reaching out!

Do you think delete will help you here?

#[test]
fn delete_mock_test() {
    let server = MockServer::start();

    let mut m1 = server.mock(|when, then| {
        when.method(GET).path("/test");
        then.status(500);
    });

    let mut m2 = server.mock(|when, then| {
        when.method(GET).path("/test");
        then.status(200);
    });

    let response = get(&format!(
        "http://{}:{}/test",
        server.host(),
        server.port()
    ))
    .unwrap();

    assert_eq!(response.status(), 500);

    // As long as both m1 and m2 exist, m1 will take precedence over m2. 
    // Let's delete m1 so we can respond with a successful response.
    m1.delete();

    let response = get(&format!("http://{}/test", server.address())).unwrap();
    
    assert_eq!(response.status(), 200);
}

@jamesperez2005
Copy link
Author

Not quite. I want to test a utility function that does the retries by itself, so I don't get a chance to intervene after the first N retries... It would be great to have a "match_at_most(N)" helper on the when clause, or even provide a callback to control what happens based on a variable

@alexliesenfeld
Copy link
Owner

Interesting idea ... OK, let's keep this issue open and I'll try to get a PR for it after the next release (it's a big change, so it makes sense to wait a bit).

@alexliesenfeld alexliesenfeld added the enhancement New feature or request label Jun 2, 2024
wfchandler added a commit to oxidecomputer/oxide.rs that referenced this issue Jul 25, 2024
If a `disk import` request is interrupted then the disk is likely to be
left in a `ImportReady` or `ImportingFromBulkWrites` state, which
prevents the user from deleting it. The commonly occurs when users
interrupt the request using ^C, and is a frustrating experience.

Add a new `GracefulShutdown` struct to listen for SIGINTs. This will
cancel the executing `Future` on interrupt and run a cleanup task which
will return an error, even if cleanup succeeds. A second SIGINT causes
the process to exit immediately.

Hook calls make in the critical section of the import into the new
system to ensure we delete the partially imported disk.

This introduces a race where the user may cancel the import operation
while the disk creation saga is still executing and the disk is in
`Creating` state. Attempting to finalize or delete the disk in this
state will fail, so we are forced to wait until it has transitioned to
`ImportReady` before proceeding. To avoid spamming the API too heavily,
we poll the disk state every 500ms for no more than ten tries.

The new polling creates a problem for our testing, though. We need the
initial disk API query to return a 404, but subsequent ones to find the
disk. `httpmock` does not provide a way to remove a mock after N hits,
and we have no graceful way of replacing the mock while running the
`oxide` binary. There is an open issue[0] to add an option like this to
`httpmock`, but for right now we have no option but to delete the tests
that check for failure.

Closes #651

[0] alexliesenfeld/httpmock#96
wfchandler added a commit to wfchandler/httpmock that referenced this issue Jul 25, 2024
In situations where a component is expected to automatically retry an
endpoint manually calling `delete` on a `Mock` may not be an option.

To support this scenario, add a new `delete_after_n` method to `When`
that will remove the `Mock` from the server after it has matched the
specified number of calls.

Related to alexliesenfeld#76
Related to alexliesenfeld#96
wfchandler added a commit to oxidecomputer/oxide.rs that referenced this issue Jul 25, 2024
If a `disk import` request is interrupted then the disk is likely to be
left in a `ImportReady` or `ImportingFromBulkWrites` state, which
prevents the user from deleting it. The commonly occurs when users
interrupt the request using ^C, and is a frustrating experience.

Add a new `GracefulShutdown` struct to listen for SIGINTs. This will
cancel the executing `Future` on interrupt and run a cleanup task which
will return an error, even if cleanup succeeds. A second SIGINT causes
the process to exit immediately.

Hook calls make in the critical section of the import into the new
system to ensure we delete the partially imported disk.

This introduces a race where the user may cancel the import operation
while the disk creation saga is still executing and the disk is in
`Creating` state. Attempting to finalize or delete the disk in this
state will fail, so we are forced to wait until it has transitioned to
`ImportReady` before proceeding. To avoid spamming the API too heavily,
we poll the disk state every 500ms for no more than ten tries.

The new polling creates a problem for our testing, though. We need the
initial disk API query to return a 404, but subsequent ones to find the
disk. `httpmock` does not provide a way to remove a mock after N hits,
and we have no graceful way of replacing the mock while running the
`oxide` binary. There is an open issue[0] to add an option like this to
`httpmock`, but for right now we have no option but to delete the tests
that check for failure.

Closes #651

[0] alexliesenfeld/httpmock#96
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants