[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
0

Configure Feed

Select the types of activity you want to include in your feed.

test(database): Implement db size stats

FoxxMD (May 6, 2026, 2:56 AM UTC) d772c8c8 48b6b555

+102 -3
+100 -1
src/backend/tests/database/drizzle.test.ts
··· 13 13 import { DatabaseSync } from 'node:sqlite'; 14 14 import { fixtureCreateComponent, fixtureCreateInput, fixtureCreatePlay } from '../utils/databaseFixtures.js'; 15 15 import { DrizzlePlayRepository, RepositoryCreatePlayOpts } from '../../common/database/drizzle/repositories/PlayRepository.js'; 16 - import { generateRandomObj } from '../../../core/tests/utils/fixtures.js'; 16 + import { generatePlayWithLifecycle, generateRandomObj } from '../../../core/tests/utils/fixtures.js'; 17 17 import { generateArray } from '../../../core/DataUtils.js'; 18 18 import { objectsEqual } from '../../utils/DataUtils.js'; 19 19 import { eq, sql } from 'drizzle-orm'; 20 20 import { PlaySelect } from '../../common/database/drizzle/drizzleTypes.js'; 21 + import { loggerDebug } from '@foxxmd/logging'; 21 22 22 23 // would be great to push migrations directly from schema but doesn't seem supported in newest beta 23 24 // https://github.com/drizzle-team/drizzle-orm/discussions/4373 ··· 551 552 552 553 }); 553 554 555 + describe('DB Size Stats', function () { 556 + 557 + 558 + before(function () { 559 + if (process.env.DB_SIZE_TEST !== 'true') { 560 + this.skip(); 561 + } 562 + }); 563 + 564 + it('get empty db size stats', async function () { 565 + 566 + await withLocalTmpDir(async () => { 567 + try { 568 + let db = getDb('ms', { workingDirectory: process.cwd() }); 569 + await migrateDb(db); 570 + const stats = await fs.stat(path.resolve('./ms.db')); 571 + loggerDebug.debug(`Empty => ${stats.size / 1024}kb`); 572 + } catch (e) { 573 + throw e; 574 + } 575 + }, { unsafeCleanup: true }); 576 + }); 577 + 578 + it('get db plays size stats', async function () { 579 + 580 + await withLocalTmpDir(async () => { 581 + try { 582 + let db = getDb('ms', { workingDirectory: process.cwd() }); 583 + await migrateDb(db); 584 + const component = await db.insert(components).values(fixtureCreateComponent()).returning(); 585 + 586 + const playRepo = new DrizzlePlayRepository(db); 587 + const playData = generateArray<RepositoryCreatePlayOpts>(100, () => ({ ...fixtureCreatePlay({ componentId: component[0].id, play: generatePlay() }), state: 'queued', input: { data: undefined } })); 588 + await playRepo.createPlays(playData); 589 + 590 + const Play100Component = await fs.stat(path.resolve('./ms.db')); 591 + loggerDebug.debug(`100 Plays => ${Play100Component.size / 1024}kb`); 592 + 593 + const morePlayData = generateArray<RepositoryCreatePlayOpts>(900, () => ({ ...fixtureCreatePlay({ componentId: component[0].id, play: generatePlay() }), state: 'queued', input: { data: undefined }})); 594 + await playRepo.createPlays(morePlayData); 595 + const Play1000Component = await fs.stat(path.resolve('./ms.db')); 596 + loggerDebug.debug(`1000 Plays => ${Play1000Component.size / 1024}kb`); 597 + } catch (e) { 598 + throw e; 599 + } 600 + }, { unsafeCleanup: true }); 601 + }); 602 + 603 + it('get db plays size stats with input', async function () { 604 + 605 + await withLocalTmpDir(async () => { 606 + try { 607 + let db = getDb('ms', { workingDirectory: process.cwd() }); 608 + await migrateDb(db); 609 + const component = await db.insert(components).values(fixtureCreateComponent()).returning(); 610 + 611 + const playRepo = new DrizzlePlayRepository(db); 612 + const playData = generateArray<RepositoryCreatePlayOpts>(100, () => ({ ...fixtureCreatePlay({ componentId: component[0].id, play: generatePlay() }), state: 'queued', input: { data: generateRandomObj(undefined, { allowUndefined: false }) } })); 613 + await playRepo.createPlays(playData); 614 + 615 + const Play100Component = await fs.stat(path.resolve('./ms.db')); 616 + loggerDebug.debug(`100 Plays => ${Play100Component.size / 1024}kb`); 617 + 618 + const morePlayData = generateArray<RepositoryCreatePlayOpts>(900, () => ({ ...fixtureCreatePlay({ componentId: component[0].id, play: generatePlay() }), state: 'queued', input: { data: generateRandomObj(undefined, { allowUndefined: false }) } })); 619 + await playRepo.createPlays(morePlayData); 620 + const Play1000Component = await fs.stat(path.resolve('./ms.db')); 621 + loggerDebug.debug(`1000 Plays => ${Play1000Component.size / 1024}kb`); 622 + } catch (e) { 623 + throw e; 624 + } 625 + }, { unsafeCleanup: true }); 626 + }); 627 + 628 + it('get db plays size stats with input and lifecycle', async function () { 629 + 630 + await withLocalTmpDir(async () => { 631 + try { 632 + let db = getDb('ms', { workingDirectory: process.cwd() }); 633 + await migrateDb(db); 634 + const component = await db.insert(components).values(fixtureCreateComponent()).returning(); 635 + 636 + const playRepo = new DrizzlePlayRepository(db); 637 + const playData = generateArray<RepositoryCreatePlayOpts>(100, () => ({ ...fixtureCreatePlay({ componentId: component[0].id, play: generatePlayWithLifecycle({lifecycleSteps: {preCompare: 1}}) }), state: 'queued', input: { data: generateRandomObj(undefined, { allowUndefined: false }) } })); 638 + await playRepo.createPlays(playData); 639 + 640 + const Play100Component = await fs.stat(path.resolve('./ms.db')); 641 + loggerDebug.debug(`100 Plays => ${Play100Component.size / 1024}kb`); 642 + 643 + const morePlayData = generateArray<RepositoryCreatePlayOpts>(900, () => ({ ...fixtureCreatePlay({ componentId: component[0].id, play: generatePlayWithLifecycle({lifecycleSteps: {preCompare: 1}}) }), state: 'queued', input: { data: generateRandomObj(undefined, { allowUndefined: false }) } })); 644 + await playRepo.createPlays(morePlayData); 645 + const Play1000Component = await fs.stat(path.resolve('./ms.db')); 646 + loggerDebug.debug(`1000 Plays => ${Play1000Component.size / 1024}kb`); 647 + } catch (e) { 648 + throw e; 649 + } 650 + }, { unsafeCleanup: true }); 651 + }); 652 + })
+2 -2
src/core/tests/utils/fixtures.ts
··· 46 46 ...original.meta 47 47 } 48 48 }; 49 - lplay.meta.lifecycle.original = lifecyclelessInvariantTransform(original); 50 - lplay.meta.lifecycle.input = generateRandomObj(); 49 + //lplay.meta.lifecycle.original = lifecyclelessInvariantTransform(original); 50 + //lplay.meta.lifecycle.input = generateRandomObj(); 51 51 52 52 let steps: LifecycleStep[] = []; 53 53 let transformedPlay = clone(original);