Forráskód Böngészése

retry HttpClientTask

ithewei 4 éve
szülő
commit
ce8b0be613

+ 1 - 5
examples/http_client_test.cpp

@@ -10,7 +10,7 @@ static void test_http_async_client(int* finished) {
     req->headers["Connection"] = "keep-alive";
     req->body = "this is an async request.";
     req->timeout = 10;
-    int ret = http_client_send_async(req, [finished](const HttpResponsePtr& resp) {
+    http_client_send_async(req, [finished](const HttpResponsePtr& resp) {
         printf("test_http_async_client response thread tid=%ld\n", hv_gettid());
         if (resp == NULL) {
             printf("request failed!\n");
@@ -20,10 +20,6 @@ static void test_http_async_client(int* finished) {
         }
         *finished = 1;
     });
-    if (ret != 0) {
-        printf("http_client_send_async error: %s:%d\n", http_client_strerror(ret), ret);
-        *finished = 1;
-    }
 }
 
 static void test_http_sync_client() {

+ 12 - 6
http/client/AsyncHttpClient.cpp

@@ -2,10 +2,11 @@
 
 namespace hv {
 
-int AsyncHttpClient::sendInLoopImpl(const HttpRequestPtr& req, HttpResponseCallback resp_cb, uint64_t start_hrtime) {
+int AsyncHttpClient::doTask(const HttpClientTaskPtr& task) {
+    const HttpRequestPtr& req = task->req;
     // queueInLoop timeout?
     uint64_t now_hrtime = hloop_now_hrtime(loop_thread.hloop());
-    int elapsed_ms = (now_hrtime - start_hrtime) / 1000;
+    int elapsed_ms = (now_hrtime - task->start_time) / 1000;
     int timeout_ms = req->timeout * 1000;
     if (timeout_ms > 0 && elapsed_ms >= timeout_ms) {
         hlogw("%s queueInLoop timeout!", req->url.c_str());
@@ -34,7 +35,7 @@ int AsyncHttpClient::sendInLoopImpl(const HttpRequestPtr& req, HttpResponseCallb
             // hlogd("get from conn_pools");
             ctx = getContext(connfd);
             ctx->req = req;
-            ctx->cb = resp_cb;
+            ctx->cb = task->cb;
         }
     }
 
@@ -58,7 +59,7 @@ int AsyncHttpClient::sendInLoopImpl(const HttpRequestPtr& req, HttpResponseCallb
         // new HttpClientContext
         ctx.reset(new HttpClientContext);
         ctx->req = req;
-        ctx->cb = resp_cb;
+        ctx->cb = task->cb;
         ctx->channel.reset(new SocketChannel(connio));
         ctx->channel->onread = [this, ctx](Buffer* buf) {
             const char* data = (const char*)buf->data();
@@ -83,10 +84,15 @@ int AsyncHttpClient::sendInLoopImpl(const HttpRequestPtr& req, HttpResponseCallb
                 }
             }
         };
-        ctx->channel->onclose = [this, ctx]() {
+        ctx->channel->onclose = [this, ctx, task]() {
             ctx->channel->status = SocketChannel::CLOSED;
             removeContext(ctx);
-            ctx->errorCallback();
+            if (task->retry_cnt-- > 0) {
+                // try again
+                send(task);
+            } else {
+                ctx->errorCallback();
+            }
         };
         addContext(ctx);
     }

+ 25 - 7
http/client/AsyncHttpClient.h

@@ -49,6 +49,15 @@ private:
     std::list<Conn>  conns_;
 };
 
+struct HttpClientTask {
+    HttpRequestPtr          req;
+    HttpResponseCallback    cb;
+
+    uint64_t  start_time;
+    int       retry_cnt;
+};
+typedef std::shared_ptr<HttpClientTask> HttpClientTaskPtr;
+
 struct HttpClientContext {
     HttpRequestPtr          req;
     HttpResponseCallback    cb;
@@ -98,21 +107,30 @@ public:
 
     // thread-safe
     int send(const HttpRequestPtr& req, HttpResponseCallback resp_cb) {
-        uint64_t start_hrtime = hloop_now_hrtime(loop_thread.hloop());
-        loop_thread.loop()->queueInLoop(std::bind(&AsyncHttpClient::sendInLoop, this, req, resp_cb, start_hrtime));
+        HttpClientTaskPtr task(new HttpClientTask);
+        task->req = req;
+        task->cb = resp_cb;
+        task->start_time = hloop_now_hrtime(loop_thread.hloop());
+        task->retry_cnt = 3;
+        return send(task);
+    }
+
+    int send(const HttpClientTaskPtr& task) {
+        loop_thread.loop()->queueInLoop(std::bind(&AsyncHttpClient::sendInLoop, this, task));
+        return 0;
     }
 
 protected:
-    void sendInLoop(const HttpRequestPtr& req, HttpResponseCallback resp_cb, uint64_t start_hrtime) {
-        int err = sendInLoopImpl(req, resp_cb, start_hrtime);
-        if (err != 0 && resp_cb) {
-            resp_cb(NULL);
+    void sendInLoop(const HttpClientTaskPtr& task) {
+        int err = doTask(task);
+        if (err != 0 && task->cb) {
+            task->cb(NULL);
         }
     }
     // createsocket => startConnect =>
     // onconnect => sendRequest => startRead =>
     // onread => HttpParser => resp_cb
-    int sendInLoopImpl(const HttpRequestPtr& req, HttpResponseCallback resp_cb, uint64_t start_hrtime);
+    int doTask(const HttpClientTaskPtr& task);
 
     // InitResponse => SubmitRequest => while(GetSendData) write => startRead
     static void onconnect(hio_t* io);