commit 52db1afe988e9d230603fe5f8bc4b28c48a089ce
parent 5650456a2446e68023eef7cef50aace64c4f4df3
Author: mtmn <miro@haravara.org>
Date: Sat, 18 Apr 2026 20:57:02 +0200
fix: add build step, leaky queries
Diffstat:
5 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/flake.nix b/flake.nix
@@ -167,7 +167,7 @@
chmod -R u+w $HOME/.elm
dhall-to-json --file users.dhall > users.json
- npm run build
+ npm run release
'';
installPhase = ''
diff --git a/justfile b/justfile
@@ -8,15 +8,20 @@ setup:
# Build the project locally
build:
- dhall-to-json --file users.dhall > users.json
npm run build
-dev: build run
+# Build a release
+release:
+ dhall-to-json --file users.dhall > users.json
+ npm run release
# Run the project locally
run:
npx spago run
+# Build and run locally
+dev: build run
+
# Run tests
test:
npm test
diff --git a/package.json b/package.json
@@ -1,11 +1,12 @@
{
"name": "corpus",
"version": "1.2.0",
- "description": "ListenBrainz scrobble viewer",
+ "description": "ListenBrainz and Last.fm frontend",
"main": "index.js",
"type": "module",
"scripts": {
- "build": "npx spago build && npx purs-backend-es build && npx esbuild output-es/Main/index.js --bundle --platform=node --format=esm --footer:js='main();' --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3 --external:prom-client --external:@opentelemetry/* && elm make src/Client.elm --optimize --output=client.js && npx uglifyjs client.js --compress \"pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe\" | npx uglifyjs --mangle --output client.js",
+ "build": "npx spago build && npx esbuild output/Main/index.js --bundle --platform=node --format=esm --footer:js='main();' --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3 --external:prom-client --external:@opentelemetry/* && elm make src/Client.elm --output=client.js",
+ "release": "npx spago build && npx purs-backend-es build && npx esbuild output-es/Main/index.js --bundle --platform=node --format=esm --footer:js='main();' --outfile=server.js --external:http --external:https --external:dotenv --external:url --external:duckdb --external:@aws-sdk/client-s3 --external:prom-client --external:@opentelemetry/* && elm make src/Client.elm --optimize --output=client.js && npx uglifyjs client.js --compress \"pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe\" | npx uglifyjs --mangle --output client.js",
"test": "npx spago test",
"tidy": "purs-tidy format-in-place src/**/*.purs"
},
diff --git a/src/Db.purs b/src/Db.purs
@@ -18,7 +18,6 @@ import Data.Formatter.DateTime (formatDateTime)
import Foreign (Foreign)
import Unsafe.Coerce (unsafeCoerce)
import Types (Listen(..), TrackMetadata(..), MbidMapping(..), Stats(..), StatsEntry(..))
-import Data.Traversable (traverse)
import Foreign.Object as Object
import Data.Nullable (Nullable, toMaybe, toNullable)
import Data.Array (mapMaybe, uncons, (!!), last, length, replicate)
@@ -173,10 +172,10 @@ getScrobbles conn limit offset Nothing = do
rows <- queryAll conn
"SELECT s.listened_at, s.track_name, s.artist_name, s.release_name, s.release_mbid, s.caa_release_mbid, rm.genre FROM scrobbles s LEFT JOIN release_metadata rm ON s.release_mbid = rm.release_mbid ORDER BY s.listened_at DESC LIMIT ? OFFSET ?"
[ unsafeCoerce limit, unsafeCoerce offset ]
- pure $ fromMaybe [] $ traverse rowToListen rows
+ pure $ mapMaybe rowToListen rows
getScrobbles conn limit offset (Just { field, value }) = do
rows <- queryAll conn query [ unsafeCoerce value, unsafeCoerce limit, unsafeCoerce offset ]
- pure $ fromMaybe [] $ traverse rowToListen rows
+ pure $ mapMaybe rowToListen rows
where
query = case field of
"artist" ->
diff --git a/src/Main.purs b/src/Main.purs
@@ -77,13 +77,14 @@ fetchListenBrainzUrl url = withRetry "ListenBrainz fetch" $ makeAff \callback ->
req # on_ Client.responseH \res -> do
launchAff_ do
- body <- readableToStringUtf8 (IM.toReadable res)
- let statusCode = IM.statusCode res
- liftEffect $
- if statusCode == 200 then
- callback (Right body)
- else
- callback (Left $ Exception.error $ "ListenBrainz API returned status " <> show statusCode)
+ result <- try $ readableToStringUtf8 (IM.toReadable res)
+ liftEffect $ case result of
+ Left err -> callback (Left err)
+ Right body ->
+ if IM.statusCode res == 200 then
+ callback (Right body)
+ else
+ callback (Left $ Exception.error $ "ListenBrainz API returned status " <> show (IM.statusCode res))
let errorH = EventHandle "error" mkEffectFn1
on_ errorH (\err -> callback (Left err)) (unsafeCoerce req)
@@ -782,7 +783,8 @@ enrichMetadata conn cfg slug = forever do
liftEffect $ Metrics.incEnrichmentFetch slug "musicbrainz" "error"
Right Nothing -> do
liftEffect $ Metrics.incEnrichmentFetch slug "musicbrainz" "retry"
- pure unit
+ upsertReleaseMetadata conn mbid Nothing Nothing Nothing
+ touchGenreCheckedAt conn mbid
Right (Just mbdata) -> do
liftEffect $ Metrics.incEnrichmentFetch slug "musicbrainz" "success"
if mbdata.genre == Nothing then do