BlackHoleGalaxy
BlackHoleGalaxy

Reputation: 9662

Awaited async method keep previous retry payload

In our program, we try to implement a task retry pattern with await.

Our main problem is our method keeps the first retry payload in subsequent ones.

Here is the retry method:

async retryTaskUntilExpectedValue({
    task,
    expectedValue,
    messageOnError = 'Max retry number reached without expected result',
    maxRetries = 10,
    timeout = 10,
    spinner = null
  }) {
    let printFn = console.log;
    if (spinner !== null) {
      printFn = spinner.text;
    }

    // Proceed retries
    for (let i = 1; i <= maxRetries; i++) {
      try {
        let result = await task;

        console.log(result); // Always display same result: {"state": "upgrading"} even if curling returns {"state": "upgraded"} after about 2 retries

        result = JSON.parse(result).state;

        if (result === expectedValue) {
          return Promise.resolve(result);
        } else if (i <= maxRetries) {
          printFn(`Result "${result}" differs from expected value "${expectedValue}"`);
          await wait(1000);

          printFn(`Waiting ${timeout}s before retry`);
          await wait(timeout * 1000);

          printFn(`Retrying (${i})`);
          continue;
        } else {
          return Promise.reject(`ERROR: ${messageOnError}`);
        }
      } catch (err) {
        return Promise.reject(`ERROR: Unexpected error while running task`);
      }
    }
};

And the use in our CLI:

checkUpgrade(url) {
    return retryTaskUntilExpectedValue({
      task: this.makeHttpRequest('GET', url),
      expectedValue: 'upgraded'
    });
}

In our case, the task is an http request returning a state from our backend database.

The model is simple: { "state": "upgrading" } then when the backend job is done, it returns { "state": "upgraded"}.

The job takes some time to process (around 20 sec). In our tests, this behavior occured:

So in the CLI we build, we have 10 times the result: Result "upgrading" differs from expected value "upgraded"

It seems the let response = await task; in the subsequent retries does not call the task method at each retry. Indeed if actual call was made, it would for sure retrieve the proper upgraded state since we get it through curl.

How to make the await task; to actually trigger the call task method and not to keep the result from first call?

Upvotes: 0

Views: 265

Answers (1)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276306

A promise is the result for an already started operation. By passing in task as a promise inside - it will always await the same result and return the same value.

Instead, retryTaskUntilExpectedValue should take a function for a promise and await an invocation of that:

let result = await functionReturningTask();

Where functionReturningTask is whatever you used to obtain task in the first place.

Upvotes: 2

Related Questions