Fix local price fetching
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_day_ahead_prices_time_dk_area
|
||||||
|
ON day_ahead_prices (time_dk, price_area);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS idx_day_ahead_prices_time_dk_area;
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
-- :name insert-price! :! :n
|
-- :name insert-price! :! :n
|
||||||
-- :doc Insert a day-ahead price record, update DKK if it was null
|
-- :doc Insert/update a day-ahead price record
|
||||||
INSERT INTO day_ahead_prices (time_utc, time_dk, price_area, price_dkk, price_eur)
|
INSERT INTO day_ahead_prices (time_utc, time_dk, price_area, price_dkk, price_eur)
|
||||||
VALUES (:time-utc, :time-dk, :price-area, :price-dkk, :price-eur)
|
VALUES (:time-utc, :time-dk, :price-area, :price-dkk, :price-eur)
|
||||||
ON CONFLICT (time_dk, price_area) DO UPDATE SET
|
ON CONFLICT (time_utc, price_area) DO UPDATE SET
|
||||||
price_dkk = COALESCE(day_ahead_prices.price_dkk, EXCLUDED.price_dkk),
|
time_dk = EXCLUDED.time_dk,
|
||||||
price_eur = COALESCE(day_ahead_prices.price_eur, EXCLUDED.price_eur);
|
price_dkk = EXCLUDED.price_dkk,
|
||||||
|
price_eur = EXCLUDED.price_eur;
|
||||||
|
|
||||||
-- :name get-prices-for-date :? :*
|
-- :name get-prices-for-date :? :*
|
||||||
-- :doc Get all prices for a given date (time_dk local date) and price area
|
-- :doc Get all prices for a given date (time_dk local date) and price area
|
||||||
|
|||||||
Executable
+68
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Run the app locally without Docker.
|
||||||
|
# Loads environment variables from .env and the Eloverblik refresh token from .token.
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
load_env_file() {
|
||||||
|
local file="$1"
|
||||||
|
|
||||||
|
[[ -f "$file" ]] || return 0
|
||||||
|
|
||||||
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||||
|
# Trim CR from CRLF files.
|
||||||
|
line="${line%$'\r'}"
|
||||||
|
|
||||||
|
# Skip blank lines and full-line comments.
|
||||||
|
[[ -z "${line//[[:space:]]/}" || "$line" =~ ^[[:space:]]*# ]] && continue
|
||||||
|
|
||||||
|
# Allow lines prefixed with "export ".
|
||||||
|
line="${line#export }"
|
||||||
|
|
||||||
|
local key="${line%%=*}"
|
||||||
|
local value="${line#*=}"
|
||||||
|
|
||||||
|
# Trim whitespace around the key only; preserve value contents (e.g. JDBC_URL query strings).
|
||||||
|
key="$(printf '%s' "$key" | xargs)"
|
||||||
|
|
||||||
|
if [[ ! "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ || "$line" != *=* ]]; then
|
||||||
|
echo "Skipping invalid env line in $file: $line" >&2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove one matching pair of surrounding quotes, if present.
|
||||||
|
if [[ "$value" =~ ^\".*\"$ || "$value" =~ ^\'.*\'$ ]]; then
|
||||||
|
value="${value:1:${#value}-2}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export "$key=$value"
|
||||||
|
done < "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_env_file ".env"
|
||||||
|
|
||||||
|
if [[ -f ".token" && -z "${ELOVERBLIK_TOKEN:-}" ]]; then
|
||||||
|
ELOVERBLIK_TOKEN="$(tr -d '\r\n' < .token)"
|
||||||
|
export ELOVERBLIK_TOKEN
|
||||||
|
fi
|
||||||
|
|
||||||
|
: "${PORT:=3000}"
|
||||||
|
export PORT
|
||||||
|
|
||||||
|
# Energi Data Service currently serves only the leaf certificate. Allow the JVM
|
||||||
|
# to fetch missing intermediate CA certificates from the certificate AIA URL.
|
||||||
|
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-} -Dcom.sun.security.enableAIAcaIssuers=true"
|
||||||
|
|
||||||
|
echo "Starting elprice locally on port $PORT (no Docker)..."
|
||||||
|
|
||||||
|
# `clj` requires rlwrap for REPL command editing. Fall back to `clojure`
|
||||||
|
# when rlwrap is not installed so the app can still start.
|
||||||
|
if command -v rlwrap >/dev/null 2>&1; then
|
||||||
|
exec clj -M:dev -e "(dev-prep!) (go)" -r
|
||||||
|
else
|
||||||
|
echo "rlwrap not found; using clojure instead of clj (REPL editing disabled)." >&2
|
||||||
|
exec clojure -M:dev -e "(dev-prep!) (go)" -r
|
||||||
|
fi
|
||||||
@@ -123,3 +123,13 @@
|
|||||||
(defn get-tomorrow-prices
|
(defn get-tomorrow-prices
|
||||||
[query-fn]
|
[query-fn]
|
||||||
(get-prices-for-date query-fn (.plusDays (LocalDate/now dk-zone) 1) "DK1"))
|
(get-prices-for-date query-fn (.plusDays (LocalDate/now dk-zone) 1) "DK1"))
|
||||||
|
|
||||||
|
|
||||||
|
(defn ensure-current-prices!
|
||||||
|
"Fetch prices only when today's DK1 prices are missing from the database."
|
||||||
|
[query-fn]
|
||||||
|
(if (seq (get-today-prices query-fn))
|
||||||
|
(do
|
||||||
|
(log/info "Day-ahead prices already exist; skipping API fetch")
|
||||||
|
nil)
|
||||||
|
(fetch-and-save! query-fn)))
|
||||||
|
|||||||
@@ -184,7 +184,7 @@
|
|||||||
|
|
||||||
(defn home
|
(defn home
|
||||||
[query-fn request]
|
[query-fn request]
|
||||||
(prices/fetch-and-save! query-fn)
|
(prices/ensure-current-prices! query-fn)
|
||||||
(page {:lang "en"}
|
(page {:lang "en"}
|
||||||
[:h1 {:class "text-2xl font-bold text-gray-900 cursor-pointer hover:text-blue-600 transition-colors"
|
[:h1 {:class "text-2xl font-bold text-gray-900 cursor-pointer hover:text-blue-600 transition-colors"
|
||||||
:hx-post "/prices/fetch"
|
:hx-post "/prices/fetch"
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
|
|
||||||
(defn fetch-prices
|
(defn fetch-prices
|
||||||
[query-fn request]
|
[query-fn request]
|
||||||
(prices/fetch-and-save! query-fn)
|
(prices/ensure-current-prices! query-fn)
|
||||||
(fragment
|
(fragment
|
||||||
(price-content :today (prices/get-today-prices query-fn) (has-tomorrow? query-fn))))
|
(price-content :today (prices/get-today-prices query-fn) (has-tomorrow? query-fn))))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user