diff --git a/app/models/station.server.ts b/app/models/station.server.ts index aef8c15..9ac5080 100644 --- a/app/models/station.server.ts +++ b/app/models/station.server.ts @@ -17,6 +17,9 @@ export type StationInput = { export type PrismaTxClient = Omit; +/** + * Fetch stations with a reliability score GTE to the `reliability` parameter. + */ export function getStations(reliability: number = 80) { return prisma.station.findMany({ where: { reliability: { gte: reliability } }, @@ -34,7 +37,9 @@ export function getStations(reliability: number = 80) { }); } - +/** + * Fetch stations tagged with `tags` and a reliability score GTE to the `reliability` parameter. + */ export function findStationsByTags(tags: string[], reliability: number = 80) { return prisma.station.findMany({ where: { @@ -78,14 +83,22 @@ export function getStationById(id: string) { } +/** + * Performs upsert at the DB level with `ON CONFLICT`. This is much faster than application level checks, which would require + * several queries. + * Note: certain criteria must be met to perform at the DB level. + * For details, see https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#database-upsert-query-criteria + */ export function upsertStationOnStreamUrl(input: StationInput, p: PrismaTxClient = prisma) { return p.station.upsert({ + // only one unique field in the upsert's where option where: { streamUrl: input.streamUrl }, create: { name: input.name, slug: slugify(input.name), description: input.description, imgUrl: input.imgUrl, + // unique field in the where option and the unique field in the create option have the same value streamUrl: input.streamUrl, reliability: input.reliability, popularity: input.popularity @@ -114,6 +127,15 @@ export function createStationTag(station: Station, tag: Tag, p: PrismaTxClient = }); } +/** + * Import the stations in `stationsInput` by either inserting or updating the records. + * - stations are upserted with uniqueness constraint on `streamUrl` + * - tags are upserted with uniqueness constraint on `name` + * - station tags are set by removing and then adding tags from each `stationInput`. + * - we may need to revisit this approach on station tags for performance and functional + * requirements + * - all writes are performed in a single transaction for performance and correctness. + */ export async function importStations(stationsInput: StationInput[]) { return prisma.$transaction(async (tx) => { const stations: Station[] = []; diff --git a/app/models/tag.server.ts b/app/models/tag.server.ts index 361c66d..9fe7771 100644 --- a/app/models/tag.server.ts +++ b/app/models/tag.server.ts @@ -50,6 +50,12 @@ export function getTags(reliability = 80) { }); } +/** + * Performs upsert at the DB level with `ON CONFLICT`. This is much faster than application level checks, which would require + * several queries. + * Note: certain criteria must be met to perform at the DB level. + * For details, see https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#database-upsert-query-criteria + */ export function upsertTagOnName(tag: string, p: PrismaTxClient = prisma) { const slug = slugify(tag); return p.tag.upsert({