mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-14 10:39:37 +00:00
fix(rundown): preserve revision and runtime semantics
Advance swapped-entry revisions correctly and rename loaded rundowns without restarting playback, while documenting the shared revision invariant.
This commit is contained in:
@@ -1718,16 +1718,18 @@ describe('rundownMutation.swap()', () => {
|
|||||||
expect((testRundown.entries['1'] as OntimeEvent).id).toBe('1');
|
expect((testRundown.entries['1'] as OntimeEvent).id).toBe('1');
|
||||||
expect((testRundown.entries['1'] as OntimeEvent).cue).toBe('data2');
|
expect((testRundown.entries['1'] as OntimeEvent).cue).toBe('data2');
|
||||||
expect((testRundown.entries['1'] as OntimeEvent).timeStart).toBe(1);
|
expect((testRundown.entries['1'] as OntimeEvent).timeStart).toBe(1);
|
||||||
expect((testRundown.entries['1'] as OntimeEvent).revision).toBe(1);
|
// the swapped entries changed, their revision has to say so
|
||||||
|
expect((testRundown.entries['1'] as OntimeEvent).revision).toBe(2);
|
||||||
|
|
||||||
expect((testRundown.entries['2'] as OntimeEvent).id).toBe('2');
|
expect((testRundown.entries['2'] as OntimeEvent).id).toBe('2');
|
||||||
expect((testRundown.entries['2'] as OntimeEvent).cue).toBe('data1');
|
expect((testRundown.entries['2'] as OntimeEvent).cue).toBe('data1');
|
||||||
expect((testRundown.entries['2'] as OntimeEvent).timeStart).toBe(2);
|
expect((testRundown.entries['2'] as OntimeEvent).timeStart).toBe(2);
|
||||||
expect((testRundown.entries['2'] as OntimeEvent).revision).toBe(1);
|
expect((testRundown.entries['2'] as OntimeEvent).revision).toBe(2);
|
||||||
|
|
||||||
expect((testRundown.entries['3'] as OntimeEvent).id).toBe('3');
|
expect((testRundown.entries['3'] as OntimeEvent).id).toBe('3');
|
||||||
expect((testRundown.entries['3'] as OntimeEvent).cue).toBe('data3');
|
expect((testRundown.entries['3'] as OntimeEvent).cue).toBe('data3');
|
||||||
expect((testRundown.entries['3'] as OntimeEvent).timeStart).toBe(3);
|
expect((testRundown.entries['3'] as OntimeEvent).timeStart).toBe(3);
|
||||||
|
// untouched, so it keeps its revision
|
||||||
expect((testRundown.entries['3'] as OntimeEvent).revision).toBe(1);
|
expect((testRundown.entries['3'] as OntimeEvent).revision).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ function swap(rundown: Rundown, eventFrom: OntimeEvent, eventTo: OntimeEvent) {
|
|||||||
gap: eventFrom.gap,
|
gap: eventFrom.gap,
|
||||||
dayOffset: eventFrom.dayOffset,
|
dayOffset: eventFrom.dayOffset,
|
||||||
// keep revision number but increment it
|
// keep revision number but increment it
|
||||||
revision: eventFrom.revision++,
|
revision: eventFrom.revision + 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
rundown.entries[eventTo.id] = {
|
rundown.entries[eventTo.id] = {
|
||||||
@@ -440,7 +440,7 @@ function swap(rundown: Rundown, eventFrom: OntimeEvent, eventTo: OntimeEvent) {
|
|||||||
gap: eventTo.gap,
|
gap: eventTo.gap,
|
||||||
dayOffset: eventTo.dayOffset,
|
dayOffset: eventTo.dayOffset,
|
||||||
// keep revision number but increment it
|
// keep revision number but increment it
|
||||||
revision: eventTo.revision++,
|
revision: eventTo.revision + 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -816,27 +816,23 @@ export async function createNewRundown(title: string) {
|
|||||||
* @throws if the provided id does not exist
|
* @throws if the provided id does not exist
|
||||||
*/
|
*/
|
||||||
export async function renameRundown(id: string, title: string) {
|
export async function renameRundown(id: string, title: string) {
|
||||||
const dataProvider = getDataProvider();
|
const { rundown, commit } = createTransaction({ rundownId: id, mutableRundown: true });
|
||||||
const rundown = dataProvider.getRundown(id);
|
|
||||||
|
|
||||||
await dataProvider.setRundown(id, { ...rundown, title, revision: rundown.revision + 1 });
|
if (rundown.title === title) {
|
||||||
|
return getDataProvider().getProjectRundowns();
|
||||||
/**
|
|
||||||
* If we are modifying the loaded rundown we re-init it
|
|
||||||
* This is likely over-kill but the simplest way to ensure state consistency
|
|
||||||
*/
|
|
||||||
if (isCurrentRundown(id)) {
|
|
||||||
const rundown = dataProvider.getRundown(id);
|
|
||||||
const customField = dataProvider.getCustomFields();
|
|
||||||
// init rundown does its own refetch
|
|
||||||
await initRundown(rundown, customField);
|
|
||||||
} else {
|
|
||||||
setImmediate(() => {
|
|
||||||
sendRefetch(RefetchKey.ProjectRundowns);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataProvider.getProjectRundowns();
|
rundown.title = title;
|
||||||
|
|
||||||
|
// a title has no bearing on the schedule, there is nothing to process and no runtime to notify
|
||||||
|
const { rundownMetadata, revision } = await commit(false);
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
notifyChanges(id, rundownMetadata, revision, { external: true });
|
||||||
|
sendRefetch(RefetchKey.ProjectRundowns);
|
||||||
|
});
|
||||||
|
|
||||||
|
return getDataProvider().getProjectRundowns();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ Load only for touched domains. Add only stable, recurring invariants; not one-of
|
|||||||
- Preserve entry identity and supported types across patch, clone, group, ungroup, reorder.
|
- Preserve entry identity and supported types across patch, clone, group, ungroup, reorder.
|
||||||
- Distinguish loaded vs background rundown. Prefer explicit rundown ID over global current state.
|
- Distinguish loaded vs background rundown. Prefer explicit rundown ID over global current state.
|
||||||
- No caller-owned rundown mutation unless explicitly contracted.
|
- No caller-owned rundown mutation unless explicitly contracted.
|
||||||
|
- Revisions mark change: a rundown revision advances on every commit, an entry revision on every
|
||||||
|
change to that entry. Delays carry no revision. Optimistic client updates apply the same bump the
|
||||||
|
server does, so an unchanged entry keeps its identity and clients can compare revisions to tell
|
||||||
|
what moved on.
|
||||||
|
|
||||||
## Persistence, realtime, cache
|
## Persistence, realtime, cache
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user