Schedule Kraken OHLC polls at HH:01 UTC instead of fixed 5-min interval

Hourly candles only finalize on the hour, so polling every 5 minutes
was wasteful. Now the poller sleeps until 1 minute past each hour,
fetches immediately on first run when no data exists, and logs time
to next fetch on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 17:40:36 +01:00
co-authored by Claude Opus 4.6
parent 553dac3069
commit 30aa52cdc7
2 changed files with 35 additions and 13 deletions
+1 -2
View File
@@ -59,5 +59,4 @@
:uri "wss://stream.binance.com:9443/ws/btcusdt@trade"}
:kraken/ohlc
{:query-fn #ig/ref :db.sql/query-fn
:interval-ms 300000}}
{:query-fn #ig/ref :db.sql/query-fn}}
+34 -11
View File
@@ -70,26 +70,49 @@
(log/info "Fetched" (count candles) "completed Kraken hourly candles"))
(count candles)))
(defn- ms-until-next-poll
"Milliseconds from now until next HH:01:00 UTC."
[]
(let [now (java.time.ZonedDateTime/now java.time.ZoneOffset/UTC)
next (-> now
(.truncatedTo java.time.temporal.ChronoUnit/HOURS)
(.plusMinutes 1))
target (if (.isAfter now next)
(.plusHours next 1)
next)]
(.toMillis (java.time.Duration/between now target))))
(defn- start-poll-loop!
"Start a background future that polls Kraken every `interval-ms`.
Returns the future."
[client query-fn since-atom running? interval-ms]
"Start a background future that polls Kraken aligned to HH:01:00 UTC.
When `has-data?` is false, fetches immediately to backfill."
[client query-fn since-atom running? has-data?]
(future
(while @running?
(when-not has-data?
(try
(poll! client query-fn since-atom)
(catch Exception e
(log/error e "Kraken OHLC poll failed")))
(Thread/sleep interval-ms))))
(log/error e "Kraken OHLC initial poll failed"))))
(while @running?
(let [wait (ms-until-next-poll)]
(log/info "Next Kraken OHLC poll in" (quot wait 60000) "minutes")
(Thread/sleep wait)
(when @running?
(try
(poll! client query-fn since-atom)
(catch Exception e
(log/error e "Kraken OHLC poll failed"))))))))
(defmethod ig/init-key :kraken/ohlc
[_ {:keys [query-fn interval-ms]}]
(log/info "Starting Kraken OHLC poller, interval:" interval-ms "ms")
[_ {:keys [query-fn]}]
(let [client (HttpClient/newHttpClient)
since (atom (seed-since-from-db query-fn))
db-since (seed-since-from-db query-fn)
since (atom db-since)
running? (atom true)
fut (start-poll-loop! client query-fn since running?
(or interval-ms 300000))]
has-data? (some? db-since)
fut (start-poll-loop! client query-fn since running? has-data?)]
(if has-data?
(log/info "Starting Kraken OHLC poller, next fetch in" (quot (ms-until-next-poll) 60000) "minutes")
(log/info "Starting Kraken OHLC poller, fetching immediately (no data)"))
{:running? running?
:future fut
:since since}))