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:
@@ -59,5 +59,4 @@
|
|||||||
:uri "wss://stream.binance.com:9443/ws/btcusdt@trade"}
|
:uri "wss://stream.binance.com:9443/ws/btcusdt@trade"}
|
||||||
|
|
||||||
:kraken/ohlc
|
:kraken/ohlc
|
||||||
{:query-fn #ig/ref :db.sql/query-fn
|
{:query-fn #ig/ref :db.sql/query-fn}}
|
||||||
:interval-ms 300000}}
|
|
||||||
|
|||||||
@@ -70,26 +70,49 @@
|
|||||||
(log/info "Fetched" (count candles) "completed Kraken hourly candles"))
|
(log/info "Fetched" (count candles) "completed Kraken hourly candles"))
|
||||||
(count 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!
|
(defn- start-poll-loop!
|
||||||
"Start a background future that polls Kraken every `interval-ms`.
|
"Start a background future that polls Kraken aligned to HH:01:00 UTC.
|
||||||
Returns the future."
|
When `has-data?` is false, fetches immediately to backfill."
|
||||||
[client query-fn since-atom running? interval-ms]
|
[client query-fn since-atom running? has-data?]
|
||||||
(future
|
(future
|
||||||
(while @running?
|
(when-not has-data?
|
||||||
(try
|
(try
|
||||||
(poll! client query-fn since-atom)
|
(poll! client query-fn since-atom)
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(log/error e "Kraken OHLC poll failed")))
|
(log/error e "Kraken OHLC initial poll failed"))))
|
||||||
(Thread/sleep interval-ms))))
|
(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
|
(defmethod ig/init-key :kraken/ohlc
|
||||||
[_ {:keys [query-fn interval-ms]}]
|
[_ {:keys [query-fn]}]
|
||||||
(log/info "Starting Kraken OHLC poller, interval:" interval-ms "ms")
|
|
||||||
(let [client (HttpClient/newHttpClient)
|
(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)
|
running? (atom true)
|
||||||
fut (start-poll-loop! client query-fn since running?
|
has-data? (some? db-since)
|
||||||
(or interval-ms 300000))]
|
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?
|
{:running? running?
|
||||||
:future fut
|
:future fut
|
||||||
:since since}))
|
:since since}))
|
||||||
|
|||||||
Reference in New Issue
Block a user