Something went wrong. Try again.
A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071import sqliteKv from "sqliteKv";import { createClient } from "auth/client";import axios from "axios";import { consola } from "consola";import { createDb, migrateToLatest } from "db";import drizzle, { ensureWritable } from "drizzle";import authVerifier from "lib/authVerifier";import { env } from "lib/env";import { createBidirectionalResolver, createIdResolver } from "lib/idResolver";import { installPdsProxyFetch } from "lib/pdsProxy";import { connect } from "nats";import redis from "redis";import { typesense } from "typesense/client";import { createStorage } from "unstorage";
// Must run before anything builds an agent or an OAuth client: it swaps the// host of outbound requests to PDSes this server cannot reach directly.installPdsProxyFetch();
const { DB_PATH } = env;export const db = createDb(DB_PATH);await migrateToLatest(db);
// Unlike the write-only Rust services, this one is mostly a read API, so a// read-only primary is logged as loudly as possible rather than made fatal —// taking the whole API down would be the larger outage.await ensureWritable().catch((err: Error) => { consola.error( `[db] PRIMARY IS NOT WRITABLE — every write will fail. ${err.message}`, );});
const kv = createStorage({ driver: sqliteKv({ location: env.KV_DB_PATH, table: "kv" }),});
const baseIdResolver = createIdResolver(kv);
export const ctx = { oauthClient: await createClient(db), resolver: createBidirectionalResolver(baseIdResolver), baseIdResolver, kv: new Map<string, string>(), // Primary: writes, and reads that must be fresh. db: drizzle.db, // Read replica (the primary itself when unconfigured): lag-tolerant reads. readDb: drizzle.readDb, nc: await connect({ servers: env.NATS_URL }), analytics: axios.create({ baseURL: env.ANALYTICS }), tracklist: axios.create({ baseURL: env.TRACKLIST }), matching: axios.create({ baseURL: env.MATCHING_URL, timeout: 10_000 }), musicbrainz: axios.create({ baseURL: env.MUSICBRAINZ_URL }), deezer: axios.create({ baseURL: env.DEEZER_URL }), // The service queues for a rate limiter slot before answering, so the // timeout has to outlast its own queue budget (DISCOGS_MAX_WAIT). discogs: axios.create({ baseURL: env.DISCOGS_URL, timeout: 45_000 }), redis: await redis .createClient({ url: env.REDIS_URL }) .on("error", (err) => { consola.error("Uncaught Redis Client Error", err); process.exit(1); }) .connect(), typesense, authVerifier, sqliteDb: db, sqliteKv: kv,};
export type Context = typeof ctx;