corpus

Log | Files | Refs | README | LICENSE

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:
Mflake.nix | 2+-
Mjustfile | 9+++++++--
Mpackage.json | 5+++--
Msrc/Db.purs | 5++---
Msrc/Main.purs | 18++++++++++--------
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