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

Retry / Poll behaviour for asynchronous systems #525

Closed
Goffen opened this issue Mar 29, 2022 · 11 comments · Fixed by #871
Closed

Retry / Poll behaviour for asynchronous systems #525

Goffen opened this issue Mar 29, 2022 · 11 comments · Fixed by #871
Labels
enhancement New feature or request
Milestone

Comments

@Goffen
Copy link

Goffen commented Mar 29, 2022

Hi there! I really like this project, but I cannot use it currently on my work because of a missing feature: to be able to retry a request.

My scenario is this:

We post in something that will eventually create something. Then I would like to poll for it to be present. After a certain amount of time I would declare it failed.

Is this something that would fit within Hurl?

@fabricereix
Copy link
Collaborator

This is a very good use case. We can't do it right now, but it would be interesting to support it.

@Goffen
Copy link
Author

Goffen commented Mar 30, 2022

I thought it would have been pretty easy to just include a flag to curl::easy. But there is no --retry option there while its present in the cli tool.

So quit a bit more work, it needs to be reimplemented somewhere.

When reading the docs for the curl cli it also only retries on 5xx. I would have needed it to retry on 404.

@jcamiel
Copy link
Collaborator

jcamiel commented Apr 1, 2022

Hi @Goffen, I think we could address your use case with Hurl syntax (and also other asynchronous use case). We have asserts and captures on response, we could introduce a "retry" section on request that will retry the request if there is any failed asserts or fails captures.

For instance: you create a resource, it give you an id and you want to pull this new created resource until a certain condition is met:

# First, create a resource
POST https://foo.net/api/jobs

HTTP/* 201
[Captures]
id: jsonpath "$.id"

# Pull the newly created resource until its over
GET https://foo.net/api/jobs/{{id}}
[Retry]
delay: 5s
max: 60s

HTTP/* 200
[Asserts]
jsonpath "$.status" == "DONE"

=> we create a resource (POST ...), we capture the id of the new resource, we pull the new resource until the status is DONE.

Another user case:

GET https://foo.com
[Retry]

HTTP/* 200

=> Retry indefinitely until the status code is 200

Also:

GET https://foo.com
[Retry]
delay: 10s

HTTP/* *
[Captures]
some_var: xpath "//*[@id='bar']

=> Retry indefinitely with a 10s delay until the response contains an HTML element with id "bar".

It's not exactly the curl "retry", we reuse the existing asserts and captures on headers, body, status etccc to define a criteria for the retry.

Given this syntax/behaviour, do you think you can address your needs?

@Goffen
Copy link
Author

Goffen commented Apr 1, 2022

Yes! That would have been awesome!
With that syntax you could both satisfy 404-behavior of polling for the job to be present and wait for custom assert to be ok.

Async-behaviour of fetching a collection as the result of a POST. Not exactly failing each fetch with 404 but instead not contained in the list.

POST https://foo.net/api/jobs

HTTP/* 201
[Captures]
id: jsonpath "$.id"

GET  https://foo.net/api/jobs
[Retry]
delay: 1s

HTTP/* 200
[Asserts]
jsonpath "..id" == "{{id}}"

(maybe not correct HURL syntax above, but..)

Somewhere in the response of jobs we wait for the id to show up.

@Jiehong
Copy link

Jiehong commented Apr 13, 2022

Hi,

1 thing to keep in mind, is to be able to define a retry globally, for all cases, instead of having to set it for each request.

For example, in Karate you can say that if you retry, it uses the global retry settings (https://github.com/karatelabs/karate#retry-until)

This allows not having to give a delay and a count.

@jcamiel
Copy link
Collaborator

jcamiel commented Apr 13, 2022

Hi @Jiehong very good idea.

We already have a per request model and a global option, for basic authentification:

GET https:/foo.net/1
GET https://foo.net/1

Authentification can be added to every request of a file:

$ hurl --user alice:secret

Or per request:

GET https:/foo.net/1
[BasicAuth]
alice: secret

GET https://foo.net/1
[BasicAuth]
bob:something

We could use the same model with this [Retry] section.

Thanks for the idea!

@fabricereix
Copy link
Collaborator

We also plan to provide most of the curl options to Hurl.
--retry is definitely one of them.

@jcamiel jcamiel added this to the 1.7.0 milestone Apr 25, 2022
@jcamiel jcamiel removed this from the 1.7.0 milestone Aug 8, 2022
@jcamiel jcamiel added the enhancement New feature or request label Aug 27, 2022
@jcamiel jcamiel added this to the 1.8.0 milestone Oct 2, 2022
@jcamiel
Copy link
Collaborator

jcamiel commented Oct 2, 2022

Update on this issue: a draft PR is in progress that should be landing for Hurl 1.8.0 (next version).

The retry syntax is going to benefit form the [Options] section introduced with Hurl 1.7.0

We're going to have two new features:

This will allow this kind of Hurl file:

# Create a new job
POST http://localhost:8000/jobs

HTTP/* 201
[Captures]
job_id: jsonpath "$.id"


# Pull job status until it is completed
GET http://localhost:8000/jobs/{{job_id}}
[Options]
retry: true

HTTP/* 200
[Asserts]
jsonpath "$.state" == "COMPLETED"

Or simply:

# Pull a ressource until it's 200 OK
GET http://localhost:8000/resources/foo
[Options]
retry: true

HTTP/* 200

@Goffen
Copy link
Author

Goffen commented Oct 3, 2022

That's awesome!

@Jiehong
Copy link

Jiehong commented Oct 17, 2022

@jcamiel : thanks a lot, maybe just a word in the README for documentation purposes, and it'll be close to perfect <3

@jcamiel
Copy link
Collaborator

jcamiel commented Oct 17, 2022

@Jiehong Thanks, I need to make a few things to complete the feature:

  • add retry-max-count=> in this release
  • expose the retry-* options for a particular request (with [Options] section) => in this release
  • update docs (README and all the docs in this release) => in this release
  • add a new option to back off between retry (maybe a flag retry-back-off) => in a next release

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
4 participants