非同期APIのリトライ

非同期APIをラップして、リトライ処理を入れる。やってることは、エラーハンドラの関数オブジェクトをラップしてリトライ状態を持たせ、再帰的に非同期APIを呼んでいる。

#include <iostream>
#include <string>
#include <functional>

void asyncApi(std::function<void(const std::string& data)> callback,
              std::function<void(const std::string& error)> errorF)
{
    std::cout << "async api" << std::endl;
    errorF("error");
//  callback("data");
}

struct AsyncRetryFunctor {
    std::size_t retry_;
    std::function<void(const std::string& data)> callback_;
    std::function<void(const std::string& error)> errorF_;

    template <class Callback, class ErrorF>
    AsyncRetryFunctor(std::size_t retry, Callback callback, ErrorF errorF)
        : retry_(retry), callback_(callback), errorF_(errorF) {}

    void operator()(const std::string& error)
    {
        if (retry_ <= 0) {
            errorF_(error);
        }
        else {
            --retry_;
            asyncApi(callback_, *this);
        }
    }
};

void asyncRetry(std::size_t retry,
                std::function<void(const std::string& data)> callback,
                std::function<void(const std::string& error)> errorF)
{
    asyncApi(callback, AsyncRetryFunctor(retry, callback, errorF));
}

int main()
{
    asyncRetry(
        3,
        [](const std::string& data) {
            std::cout << data << std::endl;
        },
        [](const std::string& error) {
            std::cout << error << std::endl;
        }
    );
}

出力:

async api
async api
async api
async api
error