Skip to content

Commit 2b6fb64

Browse files
steve-chavezsoedirgo
authored andcommitted
feat: add timeout_milliseconds
1 parent dea845f commit 2b6fb64

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

src/worker.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ pg_text_array_to_slist(ArrayType *array, struct curl_slist *headers)
138138
return headers;
139139
}
140140

141-
static int init(CURLM *cm, char *method, char *url, struct curl_slist *reqHeaders, char *reqBody, int64 id, HTAB *curlDataMap)
141+
static int init(CURLM *cm, char *method, char *url, int timeout_milliseconds, struct curl_slist *reqHeaders, char *reqBody, int64 id, HTAB *curlDataMap)
142142
{
143143
CURL *eh = curl_easy_init();
144144

@@ -178,6 +178,7 @@ static int init(CURLM *cm, char *method, char *url, struct curl_slist *reqHeader
178178
curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
179179
curl_easy_setopt(eh, CURLOPT_URL, url);
180180
curl_easy_setopt(eh, CURLOPT_HTTPHEADER, reqHeaders);
181+
curl_easy_setopt(eh, CURLOPT_TIMEOUT_MS, timeout_milliseconds);
181182
curl_easy_setopt(eh, CURLOPT_PRIVATE, id);
182183
if (log_min_messages <= DEBUG1)
183184
curl_easy_setopt(eh, CURLOPT_VERBOSE, 1L);
@@ -286,6 +287,7 @@ worker_main(Datum main_arg)
286287
q.id,\
287288
q.method,\
288289
q.url,\
290+
q.timeout_milliseconds,\
289291
array(\
290292
select key || ': ' || value from jsonb_each_text(q.headers)\
291293
),\
@@ -325,21 +327,22 @@ worker_main(Datum main_arg)
325327
int64 id = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 1, &tupIsNull));
326328
char *method = TextDatumGetCString(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 2, &tupIsNull));
327329
char *url = TextDatumGetCString(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 3, &tupIsNull));
330+
int32 timeout_milliseconds = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 4, &tupIsNull));
328331

329332
Datum headersBin;
330333
Datum bodyBin;
331334
ArrayType *pgHeaders;
332335
char *body = NULL;
333336

334-
headersBin = SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 4, &tupIsNull);
337+
headersBin = SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 5, &tupIsNull);
335338
if (!tupIsNull) {
336339
pgHeaders = DatumGetArrayTypeP(headersBin);
337340
headers = pg_text_array_to_slist(pgHeaders, headers);
338341
}
339-
bodyBin = SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 5, &tupIsNull);
342+
bodyBin = SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 6, &tupIsNull);
340343
if (!tupIsNull) body = TextDatumGetCString(bodyBin);
341344

342-
res = init(cm, method, url, headers, body, id, curlDataMap);
345+
res = init(cm, method, url, timeout_milliseconds, headers, body, id, curlDataMap);
343346

344347
if(res) {
345348
elog(ERROR, "error: init() returned %d\n", res);

test/test_http_timeout.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import time
2+
3+
import pytest
4+
from sqlalchemy import text
5+
6+
def test_http_get_err_on_default_timeout(sess):
7+
"""net.http_get with default timeout errs on a slow reply"""
8+
9+
(request_id,) = sess.execute(
10+
"""
11+
select net.http_get(url := 'http://localhost:8080/slow-reply');
12+
"""
13+
).fetchone()
14+
15+
sess.commit()
16+
17+
time.sleep(2)
18+
19+
(response,) = sess.execute(
20+
text(
21+
"""
22+
select error_msg from net._http_response where id = :request_id;
23+
"""
24+
),
25+
{"request_id": request_id},
26+
).fetchone()
27+
28+
assert response == u'Timeout was reached'
29+
30+
def test_http_get_succeed_with_gt_timeout(sess):
31+
"""net.http_get with a timeout greater than the default one succeeds on a slow reply"""
32+
33+
(request_id,) = sess.execute(
34+
"""
35+
select net.http_get(url := 'http://localhost:8080/slow-reply', timeout_milliseconds := 2500);
36+
"""
37+
).fetchone()
38+
39+
sess.commit()
40+
41+
time.sleep(2.5)
42+
43+
(response,) = sess.execute(
44+
text(
45+
"""
46+
select content from net._http_response where id = :request_id;
47+
"""
48+
),
49+
{"request_id": request_id},
50+
).fetchone()
51+
52+
assert 'after 2 seconds' in str(response)

0 commit comments

Comments
 (0)