Commit9e13d07fRecorded29 Jun 2026Repositorysigil-telegram
Thread request-timeout through the bot/client to bound API reads
Message
Bump the sigil-http dependency to ^0.16.0 to consume the new opt-in timeout: keyword, and thread an optional request-timeout (seconds) from make-tg-bot through tg-client into tg-api-call's http-post/json call. Because every API method (getUpdates poll and outbound sends alike) goes through tg-api-call, a single client-level request-timeout bounds the response read on all of them, so a half-open connection raises instead of hanging.
Default is #f (no timeout, blocking reads) so existing callers are unaffected. This is distinct from the getUpdates long-poll timeout:, which is the Telegram-side wait.
Changed
package.sgl | 2 +-
src/sigil/telegram/bot.sgl | 16 ++++++++++++----
src/sigil/telegram/client.sgl | 12 ++++++++++--
3 files changed, 23 insertions(+), 7 deletions(-)Diff
package.sglmodified
@@ -27,7 +27,7 @@
27
28
dependencies: (list 29
(from-git url: "codeberg:sigil/sigil-json" version: "^0.14.0")−30
(from-git url: "codeberg:sigil/sigil-http" version: "^0.14.0"))+30
(from-git url: "codeberg:sigil/sigil-http" version: "^0.16.0")) 31
32
dev-dependencies: (list 33
(from-git url: "codeberg:sigil/sigil" package: "sigil-test" version: "^0.17")src/sigil/telegram/bot.sglmodified
@@ -61,19 +61,27 @@
61
62
;;; Create a Telegram bot. 63
;;;+64
;;; The optional `request-timeout:` (seconds) bounds the HTTP read+65
;;; on every API call the bot makes — both the getUpdates poll and+66
;;; outbound sends — so a half-open connection raises instead of+67
;;; hanging. Omitted/#f keeps the original blocking behavior.+68
;;; 69
;;; ```scheme 70
;;; (define bot (make-tg-bot 71
;;; token: "123456:ABC-DEF..."−67
;;; allowed-chats: '(12345 67890)))+72
;;; allowed-chats: '(12345 67890)+73
;;; request-timeout: 25)) 74
;;; ``` 75
(define (make-tg-bot (keys: (token #f) 76
(allowed-chats #f)−71
(allowed-users #f)))+77
(allowed-users #f)+78
(request-timeout #f))) 79
(: (token: string?) (allowed-chats: (maybe list?))−73
(allowed-users: (maybe list?)) -> tg-bot?)+80
(allowed-users: (maybe list?))+81
(request-timeout: (maybe number?)) -> tg-bot?) 82
(unless token (error "make-tg-bot: token: is required")) 83
(tg-bot−76
client: (tg-client token: token)+84
client: (tg-client token: token request-timeout: request-timeout) 85
allowed-chats: allowed-chats 86
allowed-users: allowed-users)) 87
src/sigil/telegram/client.sglmodified
@@ -21,6 +21,7 @@
21
;; Client 22
tg-client tg-client? tg-client-token 23
tg-client-last-update-id set-tg-client-last-update-id!+24
tg-client-request-timeout 25
26
;; Core API 27
tg-api-call@@ -67,7 +68,13 @@
68
(define-struct tg-client 69
(token) 70
(api-url default: "https://api.telegram.org")−70
(last-update-id default: 0 mutable: #t))+71
(last-update-id default: 0 mutable: #t)+72
;; Optional per-request HTTP read timeout in seconds (#f = no+73
;; timeout, blocking reads — the default, unchanged behavior).+74
;; When set, every tg-api-call bounds its response read so a+75
;; half-open connection raises instead of hanging. Distinct from+76
;; the getUpdates long-poll `timeout:` (Telegram-side wait).+77
(request-timeout default: #f)) 78
79
;; ============================================================ 80
;; Core API Call@@ -91,7 +98,8 @@
98
;;; ``` 99
(define (tg-api-call client method (keys: (params #{}))) 100
(: tg-client? string? (params: dict?) -> any?)−94
(let ((response (http-post/json (api-url client method) params)))+101
(let ((response (http-post/json (api-url client method) params+102
timeout: (tg-client-request-timeout client)))) 103
(unless response 104
(error (string-append "tg-api-call: HTTP request failed for " method))) 105
(if (eq? (dict-ref response ok: #f) #t)