fix: remove dataloader

more trouble than it's worth
This commit is contained in:
Christian Benincasa
2026-01-29 20:55:37 -05:00
parent ccf45886d9
commit 75ee6a3c43
7 changed files with 21 additions and 74 deletions

View File

@@ -50,6 +50,7 @@
"tsx": "^4.20.5",
"turbo": "^2.5.3",
"typescript": "catalog:",
"typescript-eslint": "^8.46.1",
"vitest": "^3.2.4"
},
"engines": {

11
pnpm-lock.yaml generated
View File

@@ -133,6 +133,9 @@ importers:
typescript:
specifier: 5.9.3
version: 5.9.3
typescript-eslint:
specifier: ^8.46.1
version: 8.46.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.10.7)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.2)
@@ -208,9 +211,6 @@ importers:
cron-parser:
specifier: ^4.9.0
version: 4.9.0
dataloader:
specifier: ^2.2.3
version: 2.2.3
dayjs:
specifier: ^1.11.14
version: 1.11.18
@@ -4708,9 +4708,6 @@ packages:
resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
engines: {node: '>= 0.4'}
dataloader@2.2.3:
resolution: {integrity: sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==}
date-fns@2.30.0:
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
engines: {node: '>=0.11'}
@@ -13656,8 +13653,6 @@ snapshots:
es-errors: 1.3.0
is-data-view: 1.0.2
dataloader@2.2.3: {}
date-fns@2.30.0:
dependencies:
'@babel/runtime': 7.28.4

View File

@@ -53,7 +53,6 @@
"blurhash": "^2.0.5",
"chalk": "^5.6.0",
"cron-parser": "^4.9.0",
"dataloader": "^2.2.3",
"dayjs": "^1.11.14",
"drizzle-orm": "^0.39.3",
"fast-xml-parser": "^4.5.3",

View File

@@ -1,14 +1,13 @@
import { type IChannelDB } from '@/db/interfaces/IChannelDB.js';
import { KEYS } from '@/types/inject.js';
import { Maybe, Nullable } from '@/types/util.js';
import { groupByUniq, isNonEmptyString } from '@/util/index.js';
import { Maybe } from '@/types/util.js';
import { isNonEmptyString } from '@/util/index.js';
import { booleanToNumber } from '@/util/sqliteUtil.js';
import { tag } from '@tunarr/types';
import type {
InsertMediaSourceRequest,
UpdateMediaSourceRequest,
} from '@tunarr/types/api';
import DataLoader from 'dataloader';
import dayjs from 'dayjs';
import { and, eq } from 'drizzle-orm';
import { inject, injectable, interfaces } from 'inversify';
@@ -59,22 +58,6 @@ type MediaSourceUserInfo = {
@injectable()
export class MediaSourceDB {
private mediaSourceByIdLoader = new DataLoader<
MediaSourceId,
MediaSourceWithRelations | null
>(
async (batch) => {
const results = await this.getByIds([...batch]);
const byId = groupByUniq(results, (result) => result.uuid);
const resultList: Nullable<MediaSourceWithRelations>[] = [];
for (const id of batch) {
resultList.push(byId[id] ?? null);
}
return resultList;
},
{ maxBatchSize: 100, cache: false },
);
constructor(
@inject(KEYS.ChannelDB) private channelDb: IChannelDB,
@inject(KEYS.MediaSourceApiFactory)
@@ -98,14 +81,8 @@ export class MediaSourceDB {
});
}
async getById(
id: MediaSourceId,
useLoader: boolean = true,
): Promise<Maybe<MediaSourceWithRelations>> {
if (!useLoader) {
return head(await this.getByIds([id]));
}
return (await this.mediaSourceByIdLoader.load(id)) ?? undefined;
async getById(id: MediaSourceId): Promise<Maybe<MediaSourceWithRelations>> {
return head(await this.getByIds([id]));
}
private async getByIds(
@@ -179,7 +156,7 @@ export class MediaSourceDB {
}
async deleteMediaSource(id: MediaSourceId) {
const deletedServer = await this.getById(id, false);
const deletedServer = await this.getById(id);
if (isNil(deletedServer)) {
throw new Error(`MediaSource not found: ${id}`);
}

View File

@@ -78,7 +78,6 @@ export abstract class MediaSourceScanner<
const mediaSource = await this.mediaSourceDB.getById(
library.mediaSourceId,
false,
);
if (!mediaSource) {

View File

@@ -68,10 +68,7 @@ export class PlexCollectionScanner extends ExternalCollectionScanner<PlexApiClie
}
async scan(req: ExternalCollectionScanRequest): Promise<void> {
const mediaSource = await this.mediaSourceDB.getById(
req.mediaSourceId,
false,
);
const mediaSource = await this.mediaSourceDB.getById(req.mediaSourceId);
if (!mediaSource) {
throw new Error(
`Could not find media source with ID ${req.mediaSourceId}`,

View File

@@ -1,6 +1,5 @@
import { isNonEmptyString, seq } from '@tunarr/shared/util';
import { BaseSlot } from '@tunarr/types/api';
import DataLoader from 'dataloader';
import { inject, injectable } from 'inversify';
import {
flatten,
@@ -16,7 +15,6 @@ import { FillerDB } from '../../db/FillerListDB.ts';
import { IChannelDB } from '../../db/interfaces/IChannelDB.ts';
import { ProgramDB } from '../../db/ProgramDB.ts';
import { ProgramWithRelationsOrm } from '../../db/schema/derivedTypes.ts';
import { ProgramGroupingType } from '../../db/schema/ProgramGrouping.ts';
import { SmartCollectionsDB } from '../../db/SmartCollectionsDB.ts';
import { KEYS } from '../../types/inject.ts';
import { zipWithIndex } from '../../util/index.ts';
@@ -35,12 +33,6 @@ import { TimeSlotScheduleServiceRequest } from './TimeSlotSchedulerService.ts';
@injectable()
export class SlotSchedulerHelper {
private programLoader!: DataLoader<string, ProgramWithRelationsOrm>;
private descendantsLoader!: DataLoader<
[string, ProgramGroupingType],
readonly [string, ProgramWithRelationsOrm[]]
>;
constructor(
@inject(KEYS.Logger) private logger: Logger,
@inject(CustomShowDB) private customShowDB: CustomShowDB,
@@ -48,27 +40,7 @@ export class SlotSchedulerHelper {
@inject(KEYS.ProgramDB) private programDB: ProgramDB,
@inject(SmartCollectionsDB) private smartCollectionsDB: SmartCollectionsDB,
@inject(KEYS.ChannelDB) private channelDB: IChannelDB,
) {
this.programLoader = new DataLoader<string, ProgramWithRelationsOrm>(
(keys) => this.programDB.getProgramsByIds(keys),
{ cache: false, maxBatchSize: 100 },
);
this.descendantsLoader = new DataLoader(
(keys) => {
return Promise.all(
keys.map(([groupId, type]) =>
this.programDB
.getProgramGroupingDescendants(groupId, type)
.then((result) => [groupId, result] as const),
),
);
},
{
maxBatchSize: 100,
cache: false,
},
);
}
) {}
async collectSlotProgramming(
request: TimeSlotScheduleServiceRequest | SlotScheduleServiceRequest,
@@ -221,8 +193,15 @@ export class SlotSchedulerHelper {
);
const allDescendants: ProgramWithRelationsOrm[] = [];
const batchResult = await this.descendantsLoader.loadMany(
showIds.map((id) => [id, 'show'] as const),
const batchResult = await Promise.all(
showIds
.map((id) => [id, 'show'] as const)
.map(([groupId, type]) =>
this.programDB
.getProgramGroupingDescendants(groupId, type)
.then((result) => [groupId, result] as const),
),
);
for (const result of batchResult) {
if (isError(result)) {
@@ -299,7 +278,7 @@ export class SlotSchedulerHelper {
);
const dbPrograms = seq.collect(
await this.programLoader.loadMany(
await this.programDB.getProgramsByIds(
needsMaterialization.map((program) => program.id),
),
(programOrError) => {