From dcf30c6e71fb13e4bd3a654f48885e2825092e5c Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Thu, 27 May 2021 18:05:03 +0100 Subject: [PATCH] feat: Improve performance of OnShowStyleEnd infinites --- meteor/client/lib/rundown.ts | 4 +++- .../client/ui/ClockView/PresenterScreen.tsx | 8 ++++++++ meteor/client/ui/RundownView.tsx | 10 +++++++++- .../SegmentTimelineContainer.tsx | 4 +++- meteor/lib/Rundown.ts | 4 ++++ meteor/lib/rundown/infinites.ts | 19 ++++++++++++------- meteor/server/api/playout/cache.ts | 13 ++++++++++++- meteor/server/api/playout/infinites.ts | 13 ++++++++++++- 8 files changed, 63 insertions(+), 12 deletions(-) diff --git a/meteor/client/lib/rundown.ts b/meteor/client/lib/rundown.ts index a927a889e9..d7fd1206e6 100644 --- a/meteor/client/lib/rundown.ts +++ b/meteor/client/lib/rundown.ts @@ -21,7 +21,7 @@ import { } from '../../lib/Rundown' import { DBSegment, Segment, SegmentId, Segments } from '../../lib/collections/Segments' import { RundownPlaylist } from '../../lib/collections/RundownPlaylists' -import { ShowStyleBase } from '../../lib/collections/ShowStyleBases' +import { ShowStyleBase, ShowStyleBaseId } from '../../lib/collections/ShowStyleBases' import { literal, normalizeArray, getCurrentTime, applyToArray, unprotectString, protectString } from '../../lib/lib' import { PartInstance, wrapPartToTemporaryInstance } from '../../lib/collections/PartInstances' import { PieceId } from '../../lib/collections/Pieces' @@ -310,6 +310,7 @@ export namespace RundownUtils { segment: DBSegment, segmentsBeforeThisInRundownSet: Set, rundownsBeforeThisInPlaylistSet: Set, + rundownsToShowstyles: Map, orderedAllPartIds: PartId[], currentPartInstance: PartInstance | undefined, nextPartInstance: PartInstance | undefined, @@ -483,6 +484,7 @@ export namespace RundownUtils { new Set(partIds.slice(0, itIndex)), segmentsBeforeThisInRundownSet, rundownsBeforeThisInPlaylistSet, + rundownsToShowstyles, orderedAllPartIds, nextPartIsAfterCurrentPart, currentPartInstance, diff --git a/meteor/client/ui/ClockView/PresenterScreen.tsx b/meteor/client/ui/ClockView/PresenterScreen.tsx index 433feaeaf2..9c8aaaf1de 100644 --- a/meteor/client/ui/ClockView/PresenterScreen.tsx +++ b/meteor/client/ui/ClockView/PresenterScreen.tsx @@ -54,6 +54,7 @@ function getShowStyleBaseIdSegmentPartUi( segments: Segment[] parts: Part[] }, + rundownsToShowstyles: Map, currentPartInstance: PartInstance | undefined, nextPartInstance: PartInstance | undefined ): { @@ -94,6 +95,7 @@ function getShowStyleBaseIdSegmentPartUi( orderedSegmentsAndParts.segments[segmentIndex], new Set(orderedSegmentsAndParts.segments.map((s) => s._id).slice(0, segmentIndex)), new Set(rundownOrder.slice(0, rundownIndex)), + rundownsToShowstyles, orderedSegmentsAndParts.parts.map((part) => part._id), currentPartInstance, nextPartInstance, @@ -147,6 +149,10 @@ export const getPresenterScreenReactive = (props: RundownOverviewProps): Rundown rundowns = playlist.getRundowns() const orderedSegmentsAndParts = playlist.getSegmentsAndPartsSync() rundownIds = rundowns.map((rundown) => rundown._id) + const rundownsToShowstyles: Map = new Map() + for (let rundown of rundowns) { + rundownsToShowstyles.set(rundown._id, rundown.showStyleBaseId) + } showStyleBaseIds = rundowns.map((rundown) => rundown.showStyleBaseId) const { currentPartInstance, nextPartInstance } = playlist.getSelectedPartInstances() const partInstance = currentPartInstance || nextPartInstance @@ -173,6 +179,7 @@ export const getPresenterScreenReactive = (props: RundownOverviewProps): Rundown currentPartInstance, playlist, orderedSegmentsAndParts, + rundownsToShowstyles, currentPartInstance, nextPartInstance ) @@ -186,6 +193,7 @@ export const getPresenterScreenReactive = (props: RundownOverviewProps): Rundown nextPartInstance, playlist, orderedSegmentsAndParts, + rundownsToShowstyles, currentPartInstance, nextPartInstance ) diff --git a/meteor/client/ui/RundownView.tsx b/meteor/client/ui/RundownView.tsx index f6e07b9002..b1c447a7c0 100644 --- a/meteor/client/ui/RundownView.tsx +++ b/meteor/client/ui/RundownView.tsx @@ -53,7 +53,7 @@ import { AfterBroadcastForm } from './AfterBroadcastForm' import { Tracker } from 'meteor/tracker' import { RundownRightHandControls } from './RundownView/RundownRightHandControls' import { mousetrapHelper } from '../lib/mousetrapHelper' -import { ShowStyleBases, ShowStyleBase } from '../../lib/collections/ShowStyleBases' +import { ShowStyleBases, ShowStyleBase, ShowStyleBaseId } from '../../lib/collections/ShowStyleBases' import { PeripheralDevicesAPI, callPeripheralDeviceFunction } from '../lib/clientAPI' import { RONotificationEvent, @@ -1412,6 +1412,7 @@ interface ITrackedProps { rundowns: Rundown[] playlist?: RundownPlaylist matchedSegments: MatchedSegment[] + rundownsToShowstyles: Map studio?: Studio showStyleBase?: ShowStyleBase rundownLayouts?: Array @@ -1454,6 +1455,11 @@ export const RundownView = translateWithTracker(( ? undefined : (params['buckets'] as string).split(',').map((v) => parseInt(v)) + const rundownsToShowstyles: Map = new Map() + for (let rundown of rundowns) { + rundownsToShowstyles.set(rundown._id, rundown.showStyleBaseId) + } + // let rundownDurations = calculateDurations(rundown, parts) return { rundownPlaylistId: playlistId, @@ -1478,6 +1484,7 @@ export const RundownView = translateWithTracker(( ), })) : [], + rundownsToShowstyles, playlist, studio: studio, showStyleBase: rundowns.length > 0 ? ShowStyleBases.findOne(rundowns[0].showStyleBaseId) : undefined, @@ -2267,6 +2274,7 @@ export const RundownView = translateWithTracker(( onSegmentScroll={this.onSegmentScroll} segmentsIdsBefore={rundownAndSegments.segmentIdsBeforeEachSegment[segmentIndex]} rundownIdsBefore={new Set(rundownArray.slice(0, rundownIndex).map((r) => r.rundown._id))} + rundownsToShowstyles={this.props.rundownsToShowstyles} isLastSegment={ rundownIndex === rundownArray.length - 1 && segmentIndex === segmentArray.length - 1 } diff --git a/meteor/client/ui/SegmentTimeline/SegmentTimelineContainer.tsx b/meteor/client/ui/SegmentTimeline/SegmentTimelineContainer.tsx index e4ed7b5ac2..2ea1307c9c 100644 --- a/meteor/client/ui/SegmentTimeline/SegmentTimelineContainer.tsx +++ b/meteor/client/ui/SegmentTimeline/SegmentTimelineContainer.tsx @@ -18,7 +18,7 @@ import { SegmentExtended, } from '../../../lib/Rundown' import { IContextMenuContext, MAGIC_TIME_SCALE_FACTOR } from '../RundownView' -import { ShowStyleBase } from '../../../lib/collections/ShowStyleBases' +import { ShowStyleBase, ShowStyleBaseId } from '../../../lib/collections/ShowStyleBases' import { SpeechSynthesiser } from '../../lib/speechSynthesis' import { NoteType, SegmentNote } from '../../../lib/api/notes' import { getElementWidth } from '../../utils/dimensions' @@ -82,6 +82,7 @@ interface IProps { segmentId: SegmentId segmentsIdsBefore: Set rundownIdsBefore: Set + rundownsToShowstyles: Map studio: Studio showStyleBase: ShowStyleBase playlist: RundownPlaylist @@ -200,6 +201,7 @@ export const SegmentTimelineContainer = translateWithTracker, segmentsBeforeThisInRundownSet: Set, rundownsBeforeThisInPlaylistSet: Set, + rundownsToShowstyles: Map, orderedAllParts: PartId[], nextPartIsAfterCurrentPart: boolean, currentPartInstance: PartInstance | undefined, @@ -140,6 +142,7 @@ export function getPieceInstancesForPartInstance( partsBeforeThisInSegmentSet, segmentsBeforeThisInRundownSet, rundownsBeforeThisInPlaylistSet, + rundownsToShowstyles, fetchPiecesThatMayBeActiveForPart( partInstance.part, partsBeforeThisInSegmentSet, @@ -182,6 +185,7 @@ export function getPieceInstancesForPartInstance( partsBeforeThisInSegmentSet, segmentsBeforeThisInRundownSet, rundownsBeforeThisInPlaylistSet, + rundownsToShowstyles, fetchPiecesThatMayBeActiveForPart( partInstance.part, partsBeforeThisInSegmentSet, diff --git a/meteor/lib/rundown/infinites.ts b/meteor/lib/rundown/infinites.ts index 5a30343828..0e10ecf1a7 100644 --- a/meteor/lib/rundown/infinites.ts +++ b/meteor/lib/rundown/infinites.ts @@ -16,7 +16,7 @@ import { getRandomId, } from '../lib' import { Mongo } from 'meteor/mongo' -import { ShowStyleBase } from '../collections/ShowStyleBases' +import { ShowStyleBase, ShowStyleBaseId } from '../collections/ShowStyleBases' import { getPieceGroupId } from './timeline' import { RundownPlaylist, RundownPlaylistActivationId } from '../collections/RundownPlaylists' import { ReadonlyDeep } from 'type-fest' @@ -80,6 +80,7 @@ export function getPlayheadTrackingInfinitesForPart( partsBeforeThisInSegmentSet: Set, segmentsBeforeThisInRundownSet: Set, rundownsBeforeThisInPlaylistSet: Set, + rundownsToShowstyles: Map, currentPartInstance: PartInstance, currentPartPieceInstances: PieceInstance[], rundown: Rundown, @@ -195,14 +196,14 @@ export function getPlayheadTrackingInfinitesForPart( break } - const prevRundown = Rundowns.findOne(prevRundownId, { fields: { showStyleBaseId: 1 } }) + const prevRundownShowstyle = rundownsToShowstyles.get(prevRundownId) - if (!prevRundown) { + if (!prevRundownShowstyle) { isValid = false break } - isValid = prevRundown.showStyleBaseId === rundown.showStyleBaseId + isValid = prevRundownShowstyle === rundown.showStyleBaseId } if (isValid) { @@ -260,6 +261,7 @@ export function isPiecePotentiallyActiveInPart( partsBeforeThisInSegment: Set, segmentsBeforeThisInRundown: Set, rundownsBeforeThisInPlaylistSet: Set, + rundownsToShowstyles: Map, rundown: Rundown, part: DBPart, pieceToCheck: Piece @@ -323,13 +325,13 @@ export function isPiecePotentiallyActiveInPart( return false } - const prevRundown = Rundowns.findOne(prevRundownId, { fields: { showStyleBaseId: 1 } }) + const prevRundownShowstyle = rundownsToShowstyles.get(prevRundownId) - if (!prevRundown) { + if (!prevRundownShowstyle) { return false } - return prevRundown.showStyleBaseId === rundown.showStyleBaseId + return prevRundownShowstyle === rundown.showStyleBaseId default: assertNever(pieceToCheck.lifespan) return false @@ -345,6 +347,7 @@ export function getPieceInstancesForPart( partsBeforeThisInSegmentSet: Set, segmentsBeforeThisInRundownSet: Set, rundownsBeforeThisInPlaylistSet: Set, + rundownsToShowstyles: Map, possiblePieces: Piece[], orderedPartIds: PartId[], newInstanceId: PartInstanceId, @@ -390,6 +393,7 @@ export function getPieceInstancesForPart( partsBeforeThisInSegmentSet, segmentsBeforeThisInRundownSet, rundownsBeforeThisInPlaylistSet, + rundownsToShowstyles, rundown, part, candidatePiece @@ -413,6 +417,7 @@ export function getPieceInstancesForPart( partsBeforeThisInSegmentSet, segmentsBeforeThisInRundownSet, rundownsBeforeThisInPlaylistSet, + rundownsToShowstyles, playingPartInstance, playingPieceInstances || [], rundown, diff --git a/meteor/server/api/playout/cache.ts b/meteor/server/api/playout/cache.ts index 69edfdd392..57bc440efd 100644 --- a/meteor/server/api/playout/cache.ts +++ b/meteor/server/api/playout/cache.ts @@ -10,7 +10,7 @@ import { RundownPlaylistId, RundownPlaylists, } from '../../../lib/collections/RundownPlaylists' -import { Rundown, DBRundown, Rundowns } from '../../../lib/collections/Rundowns' +import { Rundown, DBRundown, Rundowns, RundownId } from '../../../lib/collections/Rundowns' import { Segment, DBSegment, Segments } from '../../../lib/collections/Segments' import { Studio, StudioId, Studios } from '../../../lib/collections/Studios' import { Timeline, TimelineComplete } from '../../../lib/collections/Timeline' @@ -24,6 +24,7 @@ import { CacheForStudioBase } from '../studio/cache' import { getRundownsSegmentsAndPartsFromCache } from './lib' import { CacheForIngest } from '../ingest/cache' import { Meteor } from 'meteor/meteor' +import { ShowStyleBaseId } from '../../../lib/collections/ShowStyleBases' /** * This is a cache used for playout operations. @@ -276,3 +277,13 @@ export function getSelectedPartInstancesFromCache( : undefined, } } +export function getShowStyleIdsRundownMappingFromCache(cache: CacheForPlayout): Map { + const rundowns = cache.Rundowns.findFetch({}) + const ret = new Map() + + for (let rundown of rundowns) { + ret.set(rundown._id, rundown.showStyleBaseId) + } + + return ret +} diff --git a/meteor/server/api/playout/infinites.ts b/meteor/server/api/playout/infinites.ts index c00cd7943f..70ebb956be 100644 --- a/meteor/server/api/playout/infinites.ts +++ b/meteor/server/api/playout/infinites.ts @@ -15,7 +15,12 @@ import { } from '../../../lib/rundown/infinites' import { profiler } from '../profiler' import { Meteor } from 'meteor/meteor' -import { CacheForPlayout, getOrderedSegmentsAndPartsFromPlayoutCache, getSelectedPartInstancesFromCache } from './cache' +import { + CacheForPlayout, + getOrderedSegmentsAndPartsFromPlayoutCache, + getSelectedPartInstancesFromCache, + getShowStyleIdsRundownMappingFromCache, +} from './cache' import { ReadonlyDeep } from 'type-fest' import { asyncCollectionFindFetch } from '../../lib/database' import { getCurrentTime } from '../../../lib/lib' @@ -193,11 +198,14 @@ export async function syncPlayheadInfinitesForNextPartInstance(cache: CacheForPl true ) + const rundownIdsToShowstyleIds = getShowStyleIdsRundownMappingFromCache(cache) + const infinites = libgetPlayheadTrackingInfinitesForPart( playlist.activationId, new Set(partsBeforeThisInSegment), new Set(segmentsBeforeThisInRundown), new Set(rundownsBeforeThisInPlaylist), + rundownIdsToShowstyleIds, currentPartInstance, prunedPieceInstances, rundown, @@ -250,6 +258,8 @@ export function getPieceInstancesForPart( part ) + const rundownIdsToShowstyleIds = getShowStyleIdsRundownMappingFromCache(cache) + const res = libgetPieceInstancesForPart( playlist.activationId, playingPartInstance, @@ -259,6 +269,7 @@ export function getPieceInstancesForPart( new Set(partsBeforeThisInSegment), new Set(segmentsBeforeThisInRundown), new Set(rundownsBeforeThisInPlaylist), + rundownIdsToShowstyleIds, possiblePieces, orderedPartsAndSegments.parts.map((p) => p._id), newInstanceId,