Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retry http requests in k6

Tags:

request

k6

I have a python requests-based suite of API tests that automatically retry every request with a 408 or 5xx response. I'm looking at re-implementing some of them in k6 for load testing. Does k6 have support for retrying http requests?

like image 288
alpinweis Avatar asked Oct 17 '25 19:10

alpinweis


2 Answers

There is no such functionality in k6, but you can add it fairly simply by wrapping the k6/http functions like:

function httpGet(url, params) {
    var res; 
    for (var retries = 3; retries > 0; retries--) {
        res = http.get(url, params)
        if (res.status != 408 && res.status < 500) {
            return res;
        }
    }
    return res;

}

And then just use httpGet instead of http.get ;)

like image 156
Михаил Стойков Avatar answered Oct 19 '25 12:10

Михаил Стойков


You can create a reusable retry function and put it in a module to be imported by your test scripts.

The function can be general purpose:

  • Expect a function to retry
  • Expect a predicate to discern successful from failed calls
  • An upper retry limit
function retry(limit, fn, pred) {
  while (limit--) {
    let result = fn();
    if (pred(result)) return result;
  }
  return undefined;
}

then provide the correct arguments when invoking:

retry(
  3,
  () => http.get('http://example.com'),
  r => !(r.status == 408 || r.status >= 500));

Of course, feel free to wrap it in one or more, more specific, functions:

function get3(url) {
  return request3(() => http.get(url));
}

function request3(req) {
  return retry(
    3,
    req,
    r => !(r.status == 408 || r.status >= 500));
}

let getResponse = get3('http://example.com');
let postResponse = request3(() => http.post(
  'https://httpbin.org/post',
  'body',
  { headers: { 'content-type': 'text/plain' } });

Bonus: you can make the calling code more expressive by implementing a cleverly named function, which inverts its result, instead of using the negation operator:

function when(pred) {
  return x => !pred(x);
}

then

retry(
  3,
  () => http.get('http://example.com'),
  when(r => r.status == 408 || r.status >= 500));

or turn around the behavior of the predicate altogether and test for failed requests instead for successful ones:

function retry(fn, pred, limit) {
  while (limit--) {
    let result = fn();
    if (!pred(result)) return result;
  }
  return undefined;
}

function unless(pred) {
  return x => !pred(x);
}

retry(
  3,
  () => http.get('http://example.com'),
  r => r.status == 408 || r.status >= 500);
retry(
  3,
  () => http.get('http://example.com'),
  unless(r => r.status != 408 && r.status < 500));
like image 36
knittl Avatar answered Oct 19 '25 13:10

knittl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!