mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-04 22:09:10 +00:00
refactor: improve project loading
This commit is contained in:
committed by
Carlos Valente
parent
876d111c61
commit
fd8f757851
@@ -282,8 +282,8 @@ function notifyChanges(options: NotifyChangesOptions) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the rundown with the given
|
||||
* @param rundown
|
||||
* Sets a new rundown in the cache
|
||||
* and marks it as the currently loaded one
|
||||
*/
|
||||
export async function initRundown(rundown: Readonly<Rundown>, customFields: Readonly<CustomFields>) {
|
||||
await cache.init(rundown, customFields);
|
||||
|
||||
@@ -34,11 +34,10 @@ beforeAll(() => {
|
||||
|
||||
describe('generate()', () => {
|
||||
test('benchmark function execution time', () => {
|
||||
const rundown = demoDb.rundowns.default;
|
||||
const t1 = performance.now();
|
||||
let result: ProcessedRundownMetadata | null = null;
|
||||
for (let i = 0; i < 100; i++) {
|
||||
result = generate(rundown);
|
||||
result = generate(demoDb.rundowns.default, demoDb.customFields);
|
||||
}
|
||||
const t2 = performance.now();
|
||||
console.warn(
|
||||
@@ -60,7 +59,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(3);
|
||||
expect(initResult.order).toStrictEqual(['1', '2', '3']);
|
||||
expect(initResult.entries['1'].type).toBe(SupportedEvent.Event);
|
||||
@@ -77,7 +76,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(2);
|
||||
expect((initResult.entries['2'] as OntimeEvent).delay).toBe(100);
|
||||
expect(initResult.totalDelay).toBe(100);
|
||||
@@ -97,7 +96,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(7);
|
||||
expect((initResult.entries['1'] as OntimeEvent).delay).toBe(0);
|
||||
expect((initResult.entries['2'] as OntimeEvent).delay).toBe(200);
|
||||
@@ -117,7 +116,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.totalDuration).toBe(10500 - 9000); // last end - first start
|
||||
});
|
||||
|
||||
@@ -132,7 +131,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.totalDuration).toBe(20000 - 9000); // last end - first start
|
||||
});
|
||||
|
||||
@@ -167,7 +166,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.totalDuration).toBe(dayInMs + MILLIS_PER_HOUR); // day + last end - first start
|
||||
});
|
||||
|
||||
@@ -185,7 +184,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(7);
|
||||
expect((initResult.entries['1'] as OntimeEvent).delay).toBe(0);
|
||||
expect((initResult.entries['2'] as OntimeEvent).delay).toBe(-200);
|
||||
@@ -227,7 +226,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(5);
|
||||
expect((initResult.entries['2'] as OntimeEvent).timeStart).toBe(2);
|
||||
expect((initResult.entries['2'] as OntimeEvent).timeEnd).toBe(12);
|
||||
@@ -248,7 +247,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(3);
|
||||
expect((initResult.entries['3'] as OntimeEvent).timeStart).toBe(2);
|
||||
});
|
||||
@@ -264,7 +263,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(4);
|
||||
expect(initResult.totalDuration).toBe(500 - 100);
|
||||
});
|
||||
@@ -280,7 +279,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.order.length).toBe(4);
|
||||
expect(initResult.totalDuration).toBe(500 - 100);
|
||||
});
|
||||
@@ -310,7 +309,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.totalDuration).toBe((23 - 9 + 48) * MILLIS_PER_HOUR);
|
||||
});
|
||||
|
||||
@@ -333,7 +332,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
const expectedDuration = 8 * MILLIS_PER_HOUR + (dayInMs - 12 * MILLIS_PER_HOUR);
|
||||
expect(initResult.totalDuration).toBe(expectedDuration);
|
||||
});
|
||||
@@ -369,7 +368,7 @@ describe('generate()', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
const initResult = generate(rundown, {});
|
||||
expect(initResult.entries).toMatchObject({
|
||||
'1': {
|
||||
timeStart: 0,
|
||||
@@ -455,7 +454,7 @@ describe('generate() v4', () => {
|
||||
'300': makeOntimeEvent({ id: '300', timeStart: 300, timeEnd: 400, duration: 100 }),
|
||||
},
|
||||
});
|
||||
const generatedRundown = generate(rundown);
|
||||
const generatedRundown = generate(rundown, {});
|
||||
|
||||
expect(generatedRundown.order).toMatchObject(['1']);
|
||||
expect(generatedRundown.totalDuration).toBe(300);
|
||||
@@ -495,7 +494,7 @@ describe('generate() v4', () => {
|
||||
'303': makeOntimeEvent({ id: '303', timeStart: 1100, timeEnd: 1200, duration: 100, linkStart: true }),
|
||||
},
|
||||
});
|
||||
const generatedRundown = generate(rundown);
|
||||
const generatedRundown = generate(rundown, {});
|
||||
|
||||
expect(generatedRundown.order).toMatchObject(['0', '1', '2', '3']);
|
||||
expect(generatedRundown.totalDuration).toBe(1200);
|
||||
|
||||
@@ -21,7 +21,6 @@ import type { RundownMetadata } from './rundown.types.js';
|
||||
import { apply } from './delayUtils.js';
|
||||
import { hasChanges, isDataStale, makeRundownMetadata, type ProcessedRundownMetadata } from './rundownCache.utils.js';
|
||||
|
||||
/** We hold the currently selected rundown and its metadata in memory */
|
||||
let currentRundownId: EntryId = '';
|
||||
let currentRundown: Rundown = {
|
||||
id: '',
|
||||
@@ -78,16 +77,14 @@ export let customFieldChangelog: Record<string, string> = {};
|
||||
* Receives a rundown which will be processed and used as the new current rundown
|
||||
*/
|
||||
export async function init(initialRundown: Readonly<Rundown>, customFields: Readonly<CustomFields>) {
|
||||
// TODO: do we need to clone?
|
||||
// we clone this objects since we use mutating logic in the cache
|
||||
currentRundown = structuredClone(initialRundown);
|
||||
currentRundownId = initialRundown.id;
|
||||
projectCustomFields = structuredClone(customFields);
|
||||
generate();
|
||||
|
||||
// TODO: we may not need to persist this data since it should come from the database
|
||||
// update the persisted data
|
||||
await getDataProvider().setRundown(currentRundownId, currentRundown);
|
||||
await getDataProvider().setCustomFields(customFields);
|
||||
updateCache();
|
||||
|
||||
currentRundownId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,14 +92,9 @@ export async function init(initialRundown: Readonly<Rundown>, customFields: Read
|
||||
* @private should not be called outside of `rundownCache.ts`, exported for testing
|
||||
*/
|
||||
export function generate(
|
||||
initialRundown: Readonly<Rundown> = currentRundown,
|
||||
customFields: Readonly<CustomFields> = projectCustomFields,
|
||||
initialRundown: Readonly<Rundown>,
|
||||
customFields: Readonly<CustomFields>,
|
||||
): ProcessedRundownMetadata {
|
||||
// The stale state can only be cleared inside generate()
|
||||
function clearIsStale() {
|
||||
isStale = false;
|
||||
}
|
||||
|
||||
const { process, getMetadata } = makeRundownMetadata(customFields, customFieldChangelog);
|
||||
|
||||
for (let i = 0; i < initialRundown.order.length; i++) {
|
||||
@@ -154,9 +146,18 @@ export function generate(
|
||||
}
|
||||
}
|
||||
|
||||
const processedData = getMetadata();
|
||||
clearIsStale();
|
||||
customFieldChangelog = {};
|
||||
return getMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the generate function in the currently loaded rundown and updates caches
|
||||
*/
|
||||
export function updateCache() {
|
||||
// The stale state can only be cleared inside updateCache()
|
||||
function clearIsStale() {
|
||||
isStale = false;
|
||||
}
|
||||
const processedData = generate(currentRundown, projectCustomFields);
|
||||
|
||||
// update the cache values
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- we are not interested in the iteration data
|
||||
@@ -164,15 +165,14 @@ export function generate(
|
||||
currentRundown.entries = entries;
|
||||
currentRundown.order = order;
|
||||
rundownMetadata = metadata;
|
||||
|
||||
// The return value is used for testing
|
||||
return processedData;
|
||||
clearIsStale();
|
||||
customFieldChangelog = {};
|
||||
}
|
||||
|
||||
/** Returns an ID guaranteed to be unique */
|
||||
export function getUniqueId(): string {
|
||||
if (isStale) {
|
||||
generate();
|
||||
updateCache();
|
||||
}
|
||||
let id = '';
|
||||
do {
|
||||
@@ -184,7 +184,7 @@ export function getUniqueId(): string {
|
||||
/** Returns index of an event with a given id */
|
||||
export function getIndexOf(eventId: EntryId) {
|
||||
if (isStale) {
|
||||
generate();
|
||||
updateCache();
|
||||
}
|
||||
return currentRundown.order.indexOf(eventId);
|
||||
}
|
||||
@@ -192,7 +192,7 @@ export function getIndexOf(eventId: EntryId) {
|
||||
/** Returns id of an event at a given index */
|
||||
export function getIdOf(index: number) {
|
||||
if (isStale) {
|
||||
generate();
|
||||
updateCache();
|
||||
}
|
||||
return currentRundown.order.at(index);
|
||||
}
|
||||
@@ -213,7 +213,7 @@ type RundownCache = {
|
||||
*/
|
||||
export function get(): Readonly<RundownCache> {
|
||||
if (isStale) {
|
||||
generate();
|
||||
updateCache();
|
||||
}
|
||||
return {
|
||||
id: currentRundown.id,
|
||||
@@ -232,7 +232,7 @@ export function get(): Readonly<RundownCache> {
|
||||
*/
|
||||
export function getMetadata(): Readonly<RundownMetadata & { revision: number }> {
|
||||
if (isStale) {
|
||||
generate();
|
||||
updateCache();
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -252,7 +252,7 @@ export type RundownOrder = {
|
||||
*/
|
||||
export function getEventOrder(): Readonly<RundownOrder> {
|
||||
if (isStale) {
|
||||
generate();
|
||||
updateCache();
|
||||
}
|
||||
return {
|
||||
order: currentRundown.order,
|
||||
@@ -482,7 +482,7 @@ function invalidateIfUsed(label: CustomFieldLabel) {
|
||||
// ... and schedule a cache update
|
||||
// schedule a non priority cache update
|
||||
setImmediate(async () => {
|
||||
generate();
|
||||
updateCache();
|
||||
await getDataProvider().setRundown(currentRundownId, currentRundown);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -149,10 +149,18 @@ export function filterTimedEvents(rundown: Rundown, timedEventOrder: EntryId[]):
|
||||
|
||||
/**
|
||||
* Gets the first rundown in the project
|
||||
* We ensure that the projects always have a rundown
|
||||
* We know that the project has at least one rundown
|
||||
*/
|
||||
export function getFirstRundown(rundowns: ProjectRundowns): Rundown {
|
||||
const firstKey = Object.keys(rundowns)[0];
|
||||
|
||||
// eslint-disable-next-line no-unused-labels -- dev code path
|
||||
DEV: {
|
||||
if (!firstKey) {
|
||||
throw new Error('rundownUtils.getFirstRundown() No rundowns found');
|
||||
}
|
||||
}
|
||||
|
||||
return rundowns[firstKey];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user