From 874e85ccbf6d9438c17d550c98ebb8e81df44e48 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Mon, 4 Nov 2024 11:12:32 +0100 Subject: [PATCH 1/8] fix: RundownView shows spinner when unMOSing a Rundown from a Playlist --- .../lib/ReactMeteorData/ReactMeteorData.tsx | 121 ++++++++++++++++-- meteor/client/ui/RundownView.tsx | 15 ++- 2 files changed, 123 insertions(+), 13 deletions(-) diff --git a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx index df3ddd7d30..efe17b7371 100644 --- a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx +++ b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/prefer-stateless-function */ -import React, { useState, useEffect, useRef } from 'react' +import React, { useState, useEffect, useRef, useCallback } from 'react' import { Meteor } from 'meteor/meteor' import { Mongo } from 'meteor/mongo' import { Tracker } from 'meteor/tracker' @@ -13,6 +13,8 @@ const globalTrackerQueue: Array = [] let globalTrackerTimestamp: number | undefined = undefined let globalTrackerTimeout: number | undefined = undefined +const SUBSCRIPTION_TIMEOUT = 1000 + /** * Delay an update to be batched with the global tracker invalidation queue */ @@ -370,6 +372,46 @@ export function useTracker( return meteorData } +function useReadyState(): { + ready: boolean + setReady: (value: boolean) => void + cancelPreviousReady: (timeout: number) => void +} { + const [ready, setReady] = useState(false) + const [prevReady, setPrevReady] = useState(false) + const prevReadyTimeoutRef = useRef(null) + + const setIsReady = useCallback( + (value: boolean) => { + setReady(value) + + if (value) { + setPrevReady(true) + if (prevReadyTimeoutRef.current !== null) { + window.clearTimeout(prevReadyTimeoutRef.current) + prevReadyTimeoutRef.current = null + } + } + }, + [setReady, setPrevReady] + ) + + const cancelPrevReady = useCallback( + (timeout: number) => { + prevReadyTimeoutRef.current = window.setTimeout(() => { + setPrevReady(false) + }, timeout) + }, + [prevReadyTimeoutRef] + ) + + return { + ready: ready || prevReady, + setReady: setIsReady, + cancelPreviousReady: cancelPrevReady, + } +} + /** * A Meteor Subscription hook that allows using React Functional Components and the Hooks API with Meteor subscriptions. * Subscriptions will be torn down 1000ms after unmounting the component. @@ -383,20 +425,28 @@ export function useSubscription( sub: K, ...args: Parameters ): boolean { - const [ready, setReady] = useState(false) + const { ready, setReady, cancelPreviousReady } = useReadyState() useEffect(() => { const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) - const isReadyComp = Tracker.nonreactive(() => Tracker.autorun(() => setReady(subscription.ready()))) + const isReadyComp = Tracker.nonreactive(() => + Tracker.autorun(() => { + const isNowReady = subscription.ready() + setReady(isNowReady) + }) + ) return () => { isReadyComp.stop() setTimeout(() => { subscription.stop() - }, 1000) + }, SUBSCRIPTION_TIMEOUT) + cancelPreviousReady(SUBSCRIPTION_TIMEOUT) } }, [sub, stringifyObjects(args)]) - return ready + const isReady = ready + + return isReady } /** @@ -415,7 +465,7 @@ export function useSubscriptionIfEnabled( enable: boolean, ...args: Parameters ): boolean { - const [ready, setReady] = useState(false) + const { ready, setReady, cancelPreviousReady } = useReadyState() useEffect(() => { if (!enable) { @@ -424,16 +474,69 @@ export function useSubscriptionIfEnabled( } const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) - const isReadyComp = Tracker.nonreactive(() => Tracker.autorun(() => setReady(subscription.ready()))) + const isReadyComp = Tracker.nonreactive(() => + Tracker.autorun(() => { + const isNowReady = subscription.ready() + setReady(isNowReady) + }) + ) return () => { isReadyComp.stop() setTimeout(() => { subscription.stop() - }, 1000) + }, SUBSCRIPTION_TIMEOUT) + cancelPreviousReady(SUBSCRIPTION_TIMEOUT) } }, [sub, enable, stringifyObjects(args)]) - return !enable || ready + const isReady = !enable || ready + + return isReady +} + +/** + * A Meteor Subscription hook that allows using React Functional Components and the Hooks API with Meteor subscriptions. + * Subscriptions will be torn down 1000ms after unmounting the component. + * If the subscription is not enabled, the subscription will not be created, and the ready state will always be true. + * + * @export + * @param {PubSub} sub The subscription to be subscribed to + * @param {boolean} enable Whether the subscription is enabled + * @param {...any[]} args A list of arugments for the subscription. This is used for optimizing the subscription across + * renders so that it isn't torn down and created for every render. + */ +export function useSubscriptionIfEnabledReadyOnce( + sub: K, + enable: boolean, + ...args: Parameters +): boolean { + const { ready, setReady, cancelPreviousReady } = useReadyState() + + useEffect(() => { + if (!enable) { + setReady(false) + return + } + + const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) + const isReadyComp = Tracker.nonreactive(() => + Tracker.autorun(() => { + const isNowReady = subscription.ready() + if (isNowReady) setReady(true) + }) + ) + return () => { + isReadyComp.stop() + setTimeout(() => { + subscription.stop() + }, SUBSCRIPTION_TIMEOUT) + cancelPreviousReady(SUBSCRIPTION_TIMEOUT) + } + }, [sub, enable, stringifyObjects(args)]) + + const isReady = !enable || ready + + return isReady } /** diff --git a/meteor/client/ui/RundownView.tsx b/meteor/client/ui/RundownView.tsx index a6ce8517e3..6b949b0c69 100644 --- a/meteor/client/ui/RundownView.tsx +++ b/meteor/client/ui/RundownView.tsx @@ -7,6 +7,7 @@ import { Translated, translateWithTracker, useSubscriptionIfEnabled, + useSubscriptionIfEnabledReadyOnce, useSubscriptions, useTracker, } from '../lib/ReactMeteorData/react-meteor-data' @@ -1227,9 +1228,6 @@ export function RundownView(props: Readonly): JSX.Element { return playlist?.studioId }, [playlistId]) - // Load once the playlist is confirmed to exist - auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiSegmentPartNotes, !!playlistStudioId, playlistId)) - auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiPieceContentStatuses, !!playlistStudioId, playlistId)) // Load only when the studio is known requiredSubsReady.push( useSubscriptionIfEnabled(MeteorPubSub.uiStudio, !!playlistStudioId, playlistStudioId ?? protectString('')) @@ -1258,7 +1256,12 @@ export function RundownView(props: Readonly): JSX.Element { ) ) requiredSubsReady.push( - useSubscriptionIfEnabled(CorelibPubSub.showStyleVariants, showStyleVariantIds.length > 0, null, showStyleVariantIds) + useSubscriptionIfEnabledReadyOnce( + CorelibPubSub.showStyleVariants, + showStyleVariantIds.length > 0, + null, + showStyleVariantIds + ) ) auxSubsReady.push( useSubscriptionIfEnabled(MeteorPubSub.rundownLayouts, showStyleBaseIds.length > 0, showStyleBaseIds) @@ -1283,6 +1286,10 @@ export function RundownView(props: Readonly): JSX.Element { ) ) + // Load once the playlist is confirmed to exist + auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiSegmentPartNotes, !!playlistStudioId, playlistId)) + auxSubsReady.push(useSubscriptionIfEnabled(MeteorPubSub.uiPieceContentStatuses, !!playlistStudioId, playlistId)) + useTracker(() => { const playlist = RundownPlaylists.findOne(playlistId, { fields: { From 5d72c14f79aba87398d222c27e004e9a096375be Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 15 Nov 2024 14:04:48 +0100 Subject: [PATCH 2/8] chore: move checkForMultipleVersions into a yarn script --- .github/workflows/node.yaml | 2 +- package.json | 3 ++- scripts/checkForMultipleVersions.mjs | 17 ++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index fb50334747..ae6d82fd6f 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -748,6 +748,6 @@ jobs: CI: true - name: Run check run: | - node scripts/checkForMultipleVersions.mjs + yarn validate:versions env: CI: true diff --git a/package.json b/package.json index e232a83b9f..ac8dc02608 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,10 @@ "meteor:run": "cd meteor && meteor yarn start", "lint": "run lint:meteor && run lint:packages", "unit": "run unit:meteor && run unit:packages", - "validate:release": "yarn install && run install-and-build && run validate:release:packages && run validate:release:meteor", + "validate:release": "yarn install && run install-and-build && run validate:versions && run validate:release:packages && run validate:release:meteor", "validate:release:meteor": "cd meteor && meteor yarn validate:prod-dependencies && meteor yarn license-validate && meteor yarn lint && meteor yarn test", "validate:release:packages": "cd packages && run validate:dependencies && run test", + "validate:versions": "node scripts/checkForMultipleVersions.mjs", "meteor": "cd meteor && meteor", "docs:serve": "cd packages && run docs:serve", "reset": "node scripts/reset.mjs", diff --git a/scripts/checkForMultipleVersions.mjs b/scripts/checkForMultipleVersions.mjs index b633852235..792aee1f79 100644 --- a/scripts/checkForMultipleVersions.mjs +++ b/scripts/checkForMultipleVersions.mjs @@ -1,5 +1,12 @@ import { buildDepTreeFromFiles } from "snyk-nodejs-lockfile-parser"; +function hr() { + // write regular dashes if this is a "simple" output stream () + if (!process.stdout.hasColors || !process.stdout.hasColors()) + return "-".repeat(process.stdout.columns ?? 40); + return '─'.repeat(process.stdout.columns ?? 40) +} + /** * These are the libs we want to consider. * Its an array of arrays, to allow for multiple names to be treated as one package @@ -58,6 +65,10 @@ await addDepsForRoot("./packages", "live-status-gateway"); let hasFailure = false; +console.log(hr()) +console.log(" 🔢 Checking dependency version consistency...") +console.log(hr()) + // check each library for (const libName of libsToConsider) { const allVersions = new Set(); @@ -73,11 +84,11 @@ for (const libName of libsToConsider) { // output some info const str = Array.from(allVersions).join(", "); if (allVersions.size === 0) { - console.log(`No versions of "${nameStr}" installed`); + console.log(`❔ No versions of "${nameStr}" installed`); } else if (allVersions.size === 1) { - console.log(`Single version of "${nameStr}" installed: ${str}`); + console.log(`✅ Single version of "${nameStr}" installed: ${str}`); } else { - console.error(`Multiple versions of "${nameStr}" installed: ${str}`); + console.error(`⚠️ Multiple versions of "${nameStr}" installed: ${str}`); hasFailure = true; } } From 96360510d78fcc9dbfd31a125d363aab272f8158 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 15 Nov 2024 15:01:36 +0100 Subject: [PATCH 3/8] fix: release scripts broken on Windows --- packages/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/package.json b/packages/package.json index c379c53211..b38fcdc147 100644 --- a/packages/package.json +++ b/packages/package.json @@ -17,7 +17,7 @@ "build": "lerna run build --ignore @sofie-automation/openapi", "build:try": "lerna run --no-bail build --ignore @sofie-automation/openapi", "watch": "lerna run --parallel build:main --ignore @sofie-automation/openapi -- --watch --preserveWatchOutput", - "stage-versions": "git add -u */package.json */CHANGELOG.md lerna.json yarn.lock", + "stage-versions": "git add -u \"*/package.json\" \"*/CHANGELOG.md\" lerna.json yarn.lock", "set-version": "lerna version --exact --no-changelog --no-git-tag-version --no-push --yes", "set-version-and-commit": "lerna version --exact --no-changelog --no-changelog --no-commit-hooks --force-publish='*' --no-push --yes", "set-version-and-changelog": "lerna version --exact --force-publish --conventional-commits --no-git-tag-version --no-push --yes", @@ -65,4 +65,4 @@ }, "name": "packages", "packageManager": "yarn@3.5.0" -} +} \ No newline at end of file From 193815dccd92f1d86acff5b316bc0956b9e8f0e4 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 16:43:15 +0100 Subject: [PATCH 4/8] fix: Device Action Studio Context gets lost, Adlib previews are unstable --- .../deviceTriggers/RundownContentObserver.ts | 8 +- .../StudioDeviceTriggerManager.ts | 280 +++++++++--------- meteor/server/api/deviceTriggers/observer.ts | 43 +-- .../lib/ReactiveCacheCollection.ts | 49 +++ 4 files changed, 225 insertions(+), 155 deletions(-) diff --git a/meteor/server/api/deviceTriggers/RundownContentObserver.ts b/meteor/server/api/deviceTriggers/RundownContentObserver.ts index 3758160320..e0d7dddcef 100644 --- a/meteor/server/api/deviceTriggers/RundownContentObserver.ts +++ b/meteor/server/api/deviceTriggers/RundownContentObserver.ts @@ -32,7 +32,7 @@ export class RundownContentObserver { #observers: Meteor.LiveQueryHandle[] = [] #cache: ContentCache #cancelCache: () => void - #cleanup: () => void = () => { + #cleanup: (() => void) | undefined = () => { throw new Error('RundownContentObserver.#cleanup has not been set!') } #disposed = false @@ -45,8 +45,11 @@ export class RundownContentObserver { ) { logger.silly(`Creating RundownContentObserver for playlist "${rundownPlaylistId}"`) const { cache, cancel: cancelCache } = createReactiveContentCache(() => { + if (this.#disposed) { + this.#cleanup?.() + return + } this.#cleanup = onChanged(cache) - if (this.#disposed) this.#cleanup() }, REACTIVITY_DEBOUNCE) this.#cache = cache @@ -157,5 +160,6 @@ export class RundownContentObserver { this.#cancelCache() this.#observers.forEach((observer) => observer.stop()) this.#cleanup?.() + this.#cleanup = undefined } } diff --git a/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts b/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts index fc1b6ac0c2..bc3f205a82 100644 --- a/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts +++ b/meteor/server/api/deviceTriggers/StudioDeviceTriggerManager.ts @@ -38,20 +38,23 @@ export class StudioDeviceTriggerManager { StudioActionManagers.set(studioId, new StudioActionManager()) } - updateTriggers(cache: ContentCache, showStyleBaseId: ShowStyleBaseId): void { + async updateTriggers(cache: ContentCache, showStyleBaseId: ShowStyleBaseId): Promise { const studioId = this.studioId this.#lastShowStyleBaseId = showStyleBaseId - const rundownPlaylist = cache.RundownPlaylists.findOne({ - activationId: { - $exists: true, - }, - }) - if (!rundownPlaylist) { + const [showStyleBase, rundownPlaylist] = await Promise.all([ + cache.ShowStyleBases.findOneAsync(showStyleBaseId), + cache.RundownPlaylists.findOneAsync({ + activationId: { + $exists: true, + }, + }), + ]) + if (!showStyleBase || !rundownPlaylist) { return } - const context = createCurrentContextFromCache(cache) + const context = await createCurrentContextFromCache(cache) const actionManager = StudioActionManagers.get(studioId) if (!actionManager) throw new Meteor.Error( @@ -60,18 +63,13 @@ export class StudioDeviceTriggerManager { ) actionManager.setContext(context) - const showStyleBase = cache.ShowStyleBases.findOne(showStyleBaseId) - if (!showStyleBase) { - return - } - const { obj: sourceLayers } = applyAndValidateOverrides(showStyleBase.sourceLayersWithOverrides) - const allTriggeredActions = cache.TriggeredActions.find({ + const allTriggeredActions = await cache.TriggeredActions.find({ showStyleBaseId: { $in: [showStyleBaseId, null], }, - }) + }).fetchAsync() const upsertedDeviceTriggerMountedActionIds: DeviceTriggerMountedActionId[] = [] const touchedActionIds: DeviceActionId[] = [] @@ -83,116 +81,126 @@ export class StudioDeviceTriggerManager { const addedPreviewIds: PreviewWrappedAdLibId[] = [] - Object.entries(triggeredAction.actions).forEach(([key, action]) => { - // Since the compiled action is cached using this actionId as a key, having the action - // and the filterChain allows for a quicker invalidation without doing a deepEquals - const actionId = protectString( - `${studioId}_${triggeredAction._id}_${key}_${JSON.stringify(action)}` - ) - const existingAction = actionManager.getAction(actionId) - let thisAction: ExecutableAction - // Use the cached action or put a new one in the cache - if (existingAction) { - thisAction = existingAction - } else { - const compiledAction = createAction(action, sourceLayers) - actionManager.setAction(actionId, compiledAction) - thisAction = compiledAction - } - touchedActionIds.push(actionId) - - Object.entries(triggeredAction.triggers).forEach(([key, trigger]) => { - if (!isDeviceTrigger(trigger)) { - return + const updateActionsPromises = Object.entries(triggeredAction.actions).map( + async ([key, action]) => { + // Since the compiled action is cached using this actionId as a key, having the action + // and the filterChain allows for a quicker invalidation without doing a deepEquals + const actionId = protectString( + `${studioId}_${triggeredAction._id}_${key}_${JSON.stringify(action)}` + ) + const existingAction = actionManager.getAction(actionId) + let thisAction: ExecutableAction + // Use the cached action or put a new one in the cache + if (existingAction) { + thisAction = existingAction + } else { + const compiledAction = createAction(action, sourceLayers) + actionManager.setAction(actionId, compiledAction) + thisAction = compiledAction } + touchedActionIds.push(actionId) - let deviceActionArguments: ShiftRegisterActionArguments | undefined = undefined + const updateMountedActionsPromises = Object.entries( + triggeredAction.triggers + ).map(async ([key, trigger]) => { + if (!isDeviceTrigger(trigger)) { + return + } - if (action.action === DeviceActions.modifyShiftRegister) { - deviceActionArguments = { - type: 'modifyRegister', - register: action.register, - operation: action.operation, - value: action.value, - limitMin: action.limitMin, - limitMax: action.limitMax, + let deviceActionArguments: ShiftRegisterActionArguments | undefined = undefined + + if (action.action === DeviceActions.modifyShiftRegister) { + deviceActionArguments = { + type: 'modifyRegister', + register: action.register, + operation: action.operation, + value: action.value, + limitMin: action.limitMin, + limitMax: action.limitMax, + } } - } - const deviceTriggerMountedActionId = protectString( - `${actionId}_${key}` - ) - DeviceTriggerMountedActions.upsert(deviceTriggerMountedActionId, { - $set: { - studioId, - showStyleBaseId, - actionType: thisAction.action, - actionId, - deviceId: trigger.deviceId, - deviceTriggerId: trigger.triggerId, - values: trigger.values, - deviceActionArguments, - name: triggeredAction.name, - }, - }) - upsertedDeviceTriggerMountedActionIds.push(deviceTriggerMountedActionId) - }) - - if (!isPreviewableAction(thisAction)) { - const adLibPreviewId = protectString(`${actionId}_preview`) - DeviceTriggerMountedActionAdlibsPreview.upsert(adLibPreviewId, { - $set: literal({ - _id: adLibPreviewId, - _rank: 0, - partId: null, - type: undefined, - label: thisAction.action, - item: null, - triggeredActionId: triggeredAction._id, - actionId, - studioId, - showStyleBaseId, - sourceLayerType: undefined, - sourceLayerName: undefined, - styleClassNames: triggeredAction.styleClassNames, - }), + const deviceTriggerMountedActionId = protectString( + `${actionId}_${key}` + ) + upsertedDeviceTriggerMountedActionIds.push(deviceTriggerMountedActionId) + return DeviceTriggerMountedActions.upsertAsync(deviceTriggerMountedActionId, { + $set: { + studioId, + showStyleBaseId, + actionType: thisAction.action, + actionId, + deviceId: trigger.deviceId, + deviceTriggerId: trigger.triggerId, + values: trigger.values, + deviceActionArguments, + name: triggeredAction.name, + }, + }) }) - addedPreviewIds.push(adLibPreviewId) - } else { - const previewedAdLibs = thisAction.preview(context) + if (!isPreviewableAction(thisAction)) { + const adLibPreviewId = protectString(`${actionId}_preview`) - previewedAdLibs.forEach((adLib) => { - const adLibPreviewId = protectString( - `${triggeredAction._id}_${studioId}_${key}_${adLib._id}` - ) - DeviceTriggerMountedActionAdlibsPreview.upsert(adLibPreviewId, { + addedPreviewIds.push(adLibPreviewId) + await DeviceTriggerMountedActionAdlibsPreview.upsertAsync(adLibPreviewId, { $set: literal({ - ...adLib, _id: adLibPreviewId, + _rank: 0, + partId: null, + type: undefined, + label: thisAction.action, + item: null, triggeredActionId: triggeredAction._id, actionId, studioId, showStyleBaseId, - sourceLayerType: adLib.sourceLayerId - ? sourceLayers[adLib.sourceLayerId]?.type - : undefined, - sourceLayerName: adLib.sourceLayerId - ? { - name: sourceLayers[adLib.sourceLayerId]?.name, - abbreviation: sourceLayers[adLib.sourceLayerId]?.abbreviation, - } - : undefined, + sourceLayerType: undefined, + sourceLayerName: undefined, styleClassNames: triggeredAction.styleClassNames, }), }) + } else { + const previewedAdLibs = thisAction.preview(context) + + const previewedAdlibsUpdatePromises = previewedAdLibs.map(async (adLib) => { + const adLibPreviewId = protectString( + `${triggeredAction._id}_${studioId}_${key}_${adLib._id}` + ) + + addedPreviewIds.push(adLibPreviewId) + return DeviceTriggerMountedActionAdlibsPreview.upsertAsync(adLibPreviewId, { + $set: literal({ + ...adLib, + _id: adLibPreviewId, + triggeredActionId: triggeredAction._id, + actionId, + studioId, + showStyleBaseId, + sourceLayerType: adLib.sourceLayerId + ? sourceLayers[adLib.sourceLayerId]?.type + : undefined, + sourceLayerName: adLib.sourceLayerId + ? { + name: sourceLayers[adLib.sourceLayerId]?.name, + abbreviation: sourceLayers[adLib.sourceLayerId]?.abbreviation, + } + : undefined, + styleClassNames: triggeredAction.styleClassNames, + }), + }) + }) - addedPreviewIds.push(adLibPreviewId) - }) + await Promise.all(previewedAdlibsUpdatePromises) + } + + await Promise.all(updateMountedActionsPromises) } - }) + ) - DeviceTriggerMountedActionAdlibsPreview.remove({ + await Promise.all(updateActionsPromises) + + await DeviceTriggerMountedActionAdlibsPreview.removeAsync({ triggeredActionId: triggeredAction._id, _id: { $nin: addedPreviewIds, @@ -200,7 +208,7 @@ export class StudioDeviceTriggerManager { }) } - DeviceTriggerMountedActions.remove({ + await DeviceTriggerMountedActions.removeAsync({ studioId, showStyleBaseId, _id: { @@ -211,7 +219,7 @@ export class StudioDeviceTriggerManager { actionManager.deleteActionsOtherThan(touchedActionIds) } - clearTriggers(): void { + async clearTriggers(): Promise { const studioId = this.studioId const showStyleBaseId = this.#lastShowStyleBaseId @@ -226,28 +234,34 @@ export class StudioDeviceTriggerManager { `No Studio Action Manager available to handle action context in Studio "${studioId}"` ) - DeviceTriggerMountedActions.find({ + const mountedActions = await DeviceTriggerMountedActions.find({ studioId, showStyleBaseId, - }).forEach((mountedAction) => { + }).fetchAsync() + for (const mountedAction of mountedActions) { actionManager.deleteAction(mountedAction.actionId) - }) - DeviceTriggerMountedActions.remove({ - studioId, - showStyleBaseId, - }) - DeviceTriggerMountedActionAdlibsPreview.remove({ - studioId, - showStyleBaseId, - }) + } + + await Promise.all([ + DeviceTriggerMountedActions.removeAsync({ + studioId, + showStyleBaseId, + }), + DeviceTriggerMountedActionAdlibsPreview.removeAsync({ + studioId, + showStyleBaseId, + }), + ]) + actionManager.deleteContext() this.#lastShowStyleBaseId = null + return } - stop(): void { - this.clearTriggers() + async stop(): Promise { StudioActionManagers.delete(this.studioId) + return await this.clearTriggers() } } @@ -266,8 +280,8 @@ function convertDocument(doc: ReadonlyObjectDeep): UITrigger }) } -function createCurrentContextFromCache(cache: ContentCache): ReactivePlaylistActionContext { - const rundownPlaylist = cache.RundownPlaylists.findOne({ +async function createCurrentContextFromCache(cache: ContentCache): Promise { + const rundownPlaylist = await cache.RundownPlaylists.findOneAsync({ activationId: { $exists: true, }, @@ -275,24 +289,26 @@ function createCurrentContextFromCache(cache: ContentCache): ReactivePlaylistAct if (!rundownPlaylist) throw new Error('There should be an active RundownPlaylist!') - const currentPartInstance = rundownPlaylist.currentPartInfo - ? cache.PartInstances.findOne(rundownPlaylist.currentPartInfo.partInstanceId) - : undefined - const nextPartInstance = rundownPlaylist.nextPartInfo - ? cache.PartInstances.findOne(rundownPlaylist.nextPartInfo.partInstanceId) - : undefined + const [currentPartInstance, nextPartInstance] = await Promise.all([ + rundownPlaylist.currentPartInfo + ? cache.PartInstances.findOneAsync(rundownPlaylist.currentPartInfo.partInstanceId) + : undefined, + rundownPlaylist.nextPartInfo + ? cache.PartInstances.findOneAsync(rundownPlaylist.nextPartInfo.partInstanceId) + : undefined, + ]) const currentSegmentPartIds = currentPartInstance - ? cache.Parts.find({ + ? await cache.Parts.find({ segmentId: currentPartInstance.part.segmentId, - }).map((part) => part._id) + }).mapAsync((part) => part._id) : [] const nextSegmentPartIds = nextPartInstance ? nextPartInstance.part.segmentId === currentPartInstance?.part.segmentId ? currentSegmentPartIds - : cache.Parts.find({ + : await cache.Parts.find({ segmentId: nextPartInstance.part.segmentId, - }).map((part) => part._id) + }).mapAsync((part) => part._id) : [] return { diff --git a/meteor/server/api/deviceTriggers/observer.ts b/meteor/server/api/deviceTriggers/observer.ts index bcc7fa8853..ef3be0679c 100644 --- a/meteor/server/api/deviceTriggers/observer.ts +++ b/meteor/server/api/deviceTriggers/observer.ts @@ -29,28 +29,28 @@ Meteor.startup(() => { const studioObserversAndManagers = new Map() const jobQueue = new JobQueueWithClasses({ autoStart: true, - executionWrapper: Meteor.bindEnvironment, - resolutionWrapper: Meteor.defer, }) - function workInQueue(fnc: () => Promise) { - jobQueue.add(fnc).catch((e) => { - logger.error(`Error in DeviceTriggers Studio observer reaction: ${stringifyError(e)}`) - }) + function workInQueue(fnc: () => Promise) { + jobQueue + .add(async () => { + const res = await fnc() + return res + }) + .catch((e) => { + logger.error(`Error in DeviceTriggers Studio observer reaction: ${stringifyError(e)}`) + }) } function createObserverAndManager(studioId: StudioId) { logger.debug(`Creating observer for studio "${studioId}"`) const manager = new StudioDeviceTriggerManager(studioId) const observer = new StudioObserver(studioId, (showStyleBaseId, cache) => { - workInQueue(async () => { - manager.updateTriggers(cache, showStyleBaseId) - }) + logger.silly(`Studio observer updating triggers for "${studioId}":"${showStyleBaseId}"`) + workInQueue(async () => manager.updateTriggers(cache, showStyleBaseId)) return () => { - workInQueue(async () => { - manager.clearTriggers() - }) + workInQueue(async () => manager.clearTriggers()) } }) @@ -58,15 +58,16 @@ Meteor.startup(() => { } function destroyObserverAndManager(studioId: StudioId) { - logger.debug(`Destroying observer for studio "${studioId}"`) - const toRemove = studioObserversAndManagers.get(studioId) - if (toRemove) { - toRemove.observer.stop() - toRemove.manager.stop() - studioObserversAndManagers.delete(studioId) - } else { - logger.error(`Observer for studio "${studioId}" not found`) - } + workInQueue(async () => { + const toRemove = studioObserversAndManagers.get(studioId) + if (toRemove) { + toRemove.observer.stop() + await toRemove.manager.stop() + studioObserversAndManagers.delete(studioId) + } else { + logger.error(`Observer for studio "${studioId}" not found`) + } + }) } Studios.observeChanges( diff --git a/meteor/server/publications/lib/ReactiveCacheCollection.ts b/meteor/server/publications/lib/ReactiveCacheCollection.ts index 294430cab1..6b7df53a34 100644 --- a/meteor/server/publications/lib/ReactiveCacheCollection.ts +++ b/meteor/server/publications/lib/ReactiveCacheCollection.ts @@ -69,6 +69,55 @@ export class ReactiveCacheCollection, + options?: Omit, 'limit'> + ): Promise { + return this.#collection.findOne(selector as any, options) + } + + async insertAsync(doc: Mongo.OptionalId): Promise { + const id = await this.#collection.insertAsync(doc) + this.runReaction() + return id + } + + async removeAsync(selector: Document['_id'] | MongoQuery): Promise { + const num = await this.#collection.removeAsync(selector as any) + if (num > 0) { + this.runReaction() + } + return num + } + + async updateAsync( + selector: Document['_id'] | MongoQuery, + modifier: MongoModifier, + options?: { + multi?: boolean + upsert?: boolean + arrayFilters?: { [identifier: string]: any }[] + } + ): Promise { + const num = await this.#collection.updateAsync(selector as any, modifier as any, options) + if (num > 0) { + this.runReaction() + } + return num + } + + async upsertAsync( + selector: Document['_id'] | Mongo.Selector, + modifier: Mongo.Modifier, + options?: { multi?: boolean } + ): Promise<{ numberAffected?: number; insertedId?: string }> { + const res = await this.#collection.upsertAsync(selector as any, modifier as any, options) + if (res.numberAffected || res.insertedId) { + this.runReaction() + } + return res + } + link(cb?: () => void): ObserveChangesCallbacks { return { added: (id: Document['_id'], fields: Partial) => { From 13f055601b9aba2d2d233e2fa29b5d19ab9d8ffc Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 29 Nov 2024 18:08:49 +0100 Subject: [PATCH 5/8] chore: improve documentation --- .../lib/ReactMeteorData/ReactMeteorData.tsx | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx index efe17b7371..10257bcea9 100644 --- a/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx +++ b/meteor/client/lib/ReactMeteorData/ReactMeteorData.tsx @@ -372,43 +372,58 @@ export function useTracker( return meteorData } -function useReadyState(): { - ready: boolean - setReady: (value: boolean) => void - cancelPreviousReady: (timeout: number) => void +/** + * A hook to track a boolean state with a sort of histeresis, with preference for `true`. `setState` makes the returned + * `state` be `true` immediately, but `false` only after `resetState` is called and `timeout` elapses. If `setState` + * is called with `true` before `timeout` elapses, then `resetState` is aborted and `state` will remain `ture. + * + * Later `resetState` calls replace earlier unelapsed calls and their timeout periods. + * + * @param {boolean} [initialState=false] + * @return {*} {{ + * state: boolean + * setState: (value: boolean) => void + * resetState: (timeout: number) => void + * }} + */ +function useDelayState(initialState = false): { + state: boolean + setState: (value: boolean) => void + resetState: (timeout: number) => void } { - const [ready, setReady] = useState(false) - const [prevReady, setPrevReady] = useState(false) + const [state, setState] = useState(initialState) + const [prevState, setPrevState] = useState(initialState) const prevReadyTimeoutRef = useRef(null) - const setIsReady = useCallback( + const setStateAndClearResets = useCallback( (value: boolean) => { - setReady(value) + setState(value) if (value) { - setPrevReady(true) + setPrevState(true) if (prevReadyTimeoutRef.current !== null) { window.clearTimeout(prevReadyTimeoutRef.current) prevReadyTimeoutRef.current = null } } }, - [setReady, setPrevReady] + [setState, setPrevState] ) - const cancelPrevReady = useCallback( - (timeout: number) => { - prevReadyTimeoutRef.current = window.setTimeout(() => { - setPrevReady(false) - }, timeout) - }, - [prevReadyTimeoutRef] - ) + const resetStateAfterDelay = useCallback((timeout: number) => { + if (prevReadyTimeoutRef.current !== null) { + window.clearTimeout(prevReadyTimeoutRef.current) + } + prevReadyTimeoutRef.current = window.setTimeout(() => { + prevReadyTimeoutRef.current = null + setPrevState(false) + }, timeout) + }, []) return { - ready: ready || prevReady, - setReady: setIsReady, - cancelPreviousReady: cancelPrevReady, + state: state || prevState, + setState: setStateAndClearResets, + resetState: resetStateAfterDelay, } } @@ -425,7 +440,7 @@ export function useSubscription( sub: K, ...args: Parameters ): boolean { - const { ready, setReady, cancelPreviousReady } = useReadyState() + const { state: ready, setState: setReady, resetState: cancelPreviousReady } = useDelayState() useEffect(() => { const subscription = Tracker.nonreactive(() => meteorSubscribe(sub, ...args)) @@ -465,7 +480,7 @@ export function useSubscriptionIfEnabled( enable: boolean, ...args: Parameters ): boolean { - const { ready, setReady, cancelPreviousReady } = useReadyState() + const { state: ready, setState: setReady, resetState: cancelPreviousReady } = useDelayState() useEffect(() => { if (!enable) { @@ -510,7 +525,7 @@ export function useSubscriptionIfEnabledReadyOnce ): boolean { - const { ready, setReady, cancelPreviousReady } = useReadyState() + const { state: ready, setState: setReady, resetState: cancelPreviousReady } = useDelayState() useEffect(() => { if (!enable) { From d2a3cdf425d49e40345537c62a97f635d1d1261e Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Wed, 4 Dec 2024 11:16:09 +0100 Subject: [PATCH 6/8] chore(release): 1.51.4 --- meteor/CHANGELOG.md | 10 +++++ meteor/package.json | 2 +- meteor/yarn.lock | 12 +++--- packages/blueprints-integration/CHANGELOG.md | 8 ++++ packages/blueprints-integration/package.json | 4 +- packages/corelib/package.json | 6 +-- packages/documentation/package.json | 2 +- packages/job-worker/package.json | 8 ++-- packages/lerna.json | 2 +- packages/live-status-gateway/package.json | 10 ++--- packages/mos-gateway/CHANGELOG.md | 8 ++++ packages/mos-gateway/package.json | 6 +-- packages/openapi/package.json | 2 +- packages/playout-gateway/CHANGELOG.md | 8 ++++ packages/playout-gateway/package.json | 6 +-- packages/server-core-integration/CHANGELOG.md | 8 ++++ packages/server-core-integration/package.json | 4 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 38 +++++++++---------- 19 files changed, 94 insertions(+), 52 deletions(-) diff --git a/meteor/CHANGELOG.md b/meteor/CHANGELOG.md index be59164e1b..e4498ae87c 100644 --- a/meteor/CHANGELOG.md +++ b/meteor/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.51.4](///compare/v1.51.3...v1.51.4) (2024-12-04) + + +### Bug Fixes + +* Device Action Studio Context gets lost, Adlib previews are unstable 193815d +* Live Status Gateway Dockerfile (regular) still uses yarn to start 0ae53c4 +* release scripts broken on Windows 9636051 +* RundownView shows spinner when unMOSing a Rundown from a Playlist 874e85c + ### [1.51.2](https://github.com/nrkno/tv-automation-server-core/compare/v1.51.1...v1.51.2) (2024-11-21) diff --git a/meteor/package.json b/meteor/package.json index 3e27c5e714..91f635f3a0 100644 --- a/meteor/package.json +++ b/meteor/package.json @@ -1,6 +1,6 @@ { "name": "automation-core", - "version": "1.51.3", + "version": "1.51.4", "private": true, "engines": { "node": ">=14.19.1" diff --git a/meteor/yarn.lock b/meteor/yarn.lock index a6f56b2e2b..c22865dcff 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1321,7 +1321,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@portal:../packages/blueprints-integration::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.4 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -1362,8 +1362,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/corelib@portal:../packages/corelib::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -1394,9 +1394,9 @@ __metadata: resolution: "@sofie-automation/job-worker@portal:../packages/job-worker::locator=automation-core%40workspace%3A." dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/corelib": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/corelib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 diff --git a/packages/blueprints-integration/CHANGELOG.md b/packages/blueprints-integration/CHANGELOG.md index abf1b45e2d..4105116d47 100644 --- a/packages/blueprints-integration/CHANGELOG.md +++ b/packages/blueprints-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package @sofie-automation/blueprints-integration + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) **Note:** Version bump only for package @sofie-automation/blueprints-integration diff --git a/packages/blueprints-integration/package.json b/packages/blueprints-integration/package.json index fc71da3f4f..2af513ab05 100644 --- a/packages/blueprints-integration/package.json +++ b/packages/blueprints-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/blueprints-integration", - "version": "1.51.3", + "version": "1.51.4", "description": "Library to define the interaction between core and the blueprints.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -38,7 +38,7 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/shared-lib": "1.51.4", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/corelib/package.json b/packages/corelib/package.json index 4ac419dab0..1be22fa65f 100644 --- a/packages/corelib/package.json +++ b/packages/corelib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/corelib", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "Internal library for some types shared by core and workers", "main": "dist/index.js", @@ -39,8 +39,8 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/blueprints-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "fast-clone": "^1.5.13", "i18next": "^21.10.0", "influx": "^5.9.3", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 3e30e7ac85..28ad6a1d6b 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -1,6 +1,6 @@ { "name": "sofie-documentation", - "version": "1.51.3", + "version": "1.51.4", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/packages/job-worker/package.json b/packages/job-worker/package.json index bbac4c7c60..bbb939e723 100644 --- a/packages/job-worker/package.json +++ b/packages/job-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/job-worker", - "version": "1.51.3", + "version": "1.51.4", "description": "Worker for things", "main": "dist/index.js", "license": "MIT", @@ -41,9 +41,9 @@ ], "dependencies": { "@slack/webhook": "^6.1.0", - "@sofie-automation/blueprints-integration": "1.51.3", - "@sofie-automation/corelib": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/blueprints-integration": "1.51.4", + "@sofie-automation/corelib": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "amqplib": "^0.10.3", "deepmerge": "^4.3.1", "elastic-apm-node": "^3.51.0", diff --git a/packages/lerna.json b/packages/lerna.json index 74b8a3c69c..3aee830fb3 100644 --- a/packages/lerna.json +++ b/packages/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.51.3", + "version": "1.51.4", "npmClient": "yarn", "useWorkspaces": true } diff --git a/packages/live-status-gateway/package.json b/packages/live-status-gateway/package.json index 4397d3b2f3..0cd6b534b4 100644 --- a/packages/live-status-gateway/package.json +++ b/packages/live-status-gateway/package.json @@ -1,6 +1,6 @@ { "name": "live-status-gateway", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "Provides state from Sofie over sockets", "license": "MIT", @@ -53,10 +53,10 @@ "production" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.3", - "@sofie-automation/corelib": "1.51.3", - "@sofie-automation/server-core-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/blueprints-integration": "1.51.4", + "@sofie-automation/corelib": "1.51.4", + "@sofie-automation/server-core-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "debug": "^4.3.4", "fast-clone": "^1.5.13", "influx": "^5.9.3", diff --git a/packages/mos-gateway/CHANGELOG.md b/packages/mos-gateway/CHANGELOG.md index 9a91703d98..12651308e8 100644 --- a/packages/mos-gateway/CHANGELOG.md +++ b/packages/mos-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package mos-gateway + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) diff --git a/packages/mos-gateway/package.json b/packages/mos-gateway/package.json index e0085ca549..d8c3461b16 100644 --- a/packages/mos-gateway/package.json +++ b/packages/mos-gateway/package.json @@ -1,6 +1,6 @@ { "name": "mos-gateway", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "MOS-Gateway for the Sofie project", "license": "MIT", @@ -66,8 +66,8 @@ ], "dependencies": { "@mos-connection/connector": "4.1.1", - "@sofie-automation/server-core-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/server-core-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "tslib": "^2.6.2", "type-fest": "^3.13.1", "underscore": "^1.13.6", diff --git a/packages/openapi/package.json b/packages/openapi/package.json index a79735ff45..4f9e693cc6 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/openapi", - "version": "1.51.3", + "version": "1.51.4", "license": "MIT", "repository": { "type": "git", diff --git a/packages/playout-gateway/CHANGELOG.md b/packages/playout-gateway/CHANGELOG.md index 560b526971..0396e96547 100644 --- a/packages/playout-gateway/CHANGELOG.md +++ b/packages/playout-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package playout-gateway + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index 0d8e33c4fa..77702d6d29 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -1,6 +1,6 @@ { "name": "playout-gateway", - "version": "1.51.3", + "version": "1.51.4", "private": true, "description": "Connect to Core, play stuff", "license": "MIT", @@ -56,8 +56,8 @@ "production" ], "dependencies": { - "@sofie-automation/server-core-integration": "1.51.3", - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/server-core-integration": "1.51.4", + "@sofie-automation/shared-lib": "1.51.4", "debug": "^4.3.4", "influx": "^5.9.3", "timeline-state-resolver": "9.2.1", diff --git a/packages/server-core-integration/CHANGELOG.md b/packages/server-core-integration/CHANGELOG.md index 7dfd8d5ce6..b259defec9 100644 --- a/packages/server-core-integration/CHANGELOG.md +++ b/packages/server-core-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) + +**Note:** Version bump only for package @sofie-automation/server-core-integration + + + + + ## [1.51.3](https://github.com/nrkno/sofie-core/compare/v1.51.2...v1.51.3) (2024-11-21) **Note:** Version bump only for package @sofie-automation/server-core-integration diff --git a/packages/server-core-integration/package.json b/packages/server-core-integration/package.json index 954e9f8f04..e8be09e879 100644 --- a/packages/server-core-integration/package.json +++ b/packages/server-core-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/server-core-integration", - "version": "1.51.3", + "version": "1.51.4", "description": "Library for connecting to Core", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -70,7 +70,7 @@ "production" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.3", + "@sofie-automation/shared-lib": "1.51.4", "ejson": "^2.2.3", "eventemitter3": "^4.0.7", "faye-websocket": "^0.11.4", diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 22e2b6b7fc..60928b7eaa 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/shared-lib", - "version": "1.51.3", + "version": "1.51.4", "description": "Library for types & values shared by core, workers and gateways", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/yarn.lock b/packages/yarn.lock index cf52fe25db..2cd2a6209b 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4565,11 +4565,11 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/blueprints-integration@1.51.3, @sofie-automation/blueprints-integration@workspace:blueprints-integration": +"@sofie-automation/blueprints-integration@1.51.4, @sofie-automation/blueprints-integration@workspace:blueprints-integration": version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@workspace:blueprints-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.4 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -4606,12 +4606,12 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/corelib@1.51.3, @sofie-automation/corelib@workspace:corelib": +"@sofie-automation/corelib@1.51.4, @sofie-automation/corelib@workspace:corelib": version: 0.0.0-use.local resolution: "@sofie-automation/corelib@workspace:corelib" dependencies: - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -4642,9 +4642,9 @@ __metadata: resolution: "@sofie-automation/job-worker@workspace:job-worker" dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/corelib": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/corelib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 @@ -4674,11 +4674,11 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/server-core-integration@1.51.3, @sofie-automation/server-core-integration@workspace:server-core-integration": +"@sofie-automation/server-core-integration@1.51.4, @sofie-automation/server-core-integration@workspace:server-core-integration": version: 0.0.0-use.local resolution: "@sofie-automation/server-core-integration@workspace:server-core-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/shared-lib": 1.51.4 ejson: ^2.2.3 eventemitter3: ^4.0.7 faye-websocket: ^0.11.4 @@ -4688,7 +4688,7 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/shared-lib@1.51.3, @sofie-automation/shared-lib@workspace:shared-lib": +"@sofie-automation/shared-lib@1.51.4, @sofie-automation/shared-lib@workspace:shared-lib": version: 0.0.0-use.local resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: @@ -15334,10 +15334,10 @@ asn1@evs-broadcast/node-asn1: "@asyncapi/generator": ^1.17.25 "@asyncapi/html-template": ^2.3.9 "@asyncapi/nodejs-ws-template": ^0.9.36 - "@sofie-automation/blueprints-integration": 1.51.3 - "@sofie-automation/corelib": 1.51.3 - "@sofie-automation/server-core-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/blueprints-integration": 1.51.4 + "@sofie-automation/corelib": 1.51.4 + "@sofie-automation/server-core-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 debug: ^4.3.4 fast-clone: ^1.5.13 influx: ^5.9.3 @@ -17410,8 +17410,8 @@ asn1@evs-broadcast/node-asn1: resolution: "mos-gateway@workspace:mos-gateway" dependencies: "@mos-connection/connector": 4.1.1 - "@sofie-automation/server-core-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/server-core-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 tslib: ^2.6.2 type-fest: ^3.13.1 underscore: ^1.13.6 @@ -19397,8 +19397,8 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: - "@sofie-automation/server-core-integration": 1.51.3 - "@sofie-automation/shared-lib": 1.51.3 + "@sofie-automation/server-core-integration": 1.51.4 + "@sofie-automation/shared-lib": 1.51.4 debug: ^4.3.4 influx: ^5.9.3 timeline-state-resolver: 9.2.1 From a7d69998085c05617c3e056327bb6cd203ebdd39 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Fri, 13 Dec 2024 19:08:53 +0100 Subject: [PATCH 7/8] fix(job-worker/playout): Hold mode doesn't work at all --- .../src/playout/model/PlayoutModel.ts | 5 ++ .../model/implementation/PlayoutModelImpl.ts | 10 +-- packages/job-worker/src/playout/take.ts | 84 ++++++++++--------- .../src/playout/timings/partPlayback.ts | 1 + 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/packages/job-worker/src/playout/model/PlayoutModel.ts b/packages/job-worker/src/playout/model/PlayoutModel.ts index 396a465373..3b944f9f3f 100644 --- a/packages/job-worker/src/playout/model/PlayoutModel.ts +++ b/packages/job-worker/src/playout/model/PlayoutModel.ts @@ -234,6 +234,11 @@ export interface PlayoutModel extends PlayoutModelReadonly, StudioPlayoutModelBa */ cycleSelectedPartInstances(): void + /** + * Reset the hold state to a base state + */ + resetHoldState(): void + /** * Set the RundownPlaylist as deactivated */ diff --git a/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts b/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts index b2d0508a08..5b57a57152 100644 --- a/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts +++ b/packages/job-worker/src/playout/model/implementation/PlayoutModelImpl.ts @@ -420,15 +420,13 @@ export class PlayoutModelImpl extends PlayoutModelReadonlyImpl implements Playou this.playlistImpl.nextPartInfo = null this.playlistImpl.lastTakeTime = getCurrentTime() - if (!this.playlistImpl.holdState || this.playlistImpl.holdState === RundownHoldState.COMPLETE) { - this.playlistImpl.holdState = RundownHoldState.NONE - } else { - this.playlistImpl.holdState = this.playlistImpl.holdState + 1 - } - this.#playlistHasChanged = true } + resetHoldState(): void { + this.setHoldState(RundownHoldState.NONE) + } + deactivatePlaylist(): void { delete this.playlistImpl.activationId diff --git a/packages/job-worker/src/playout/take.ts b/packages/job-worker/src/playout/take.ts index f4a404d993..c089685d8d 100644 --- a/packages/job-worker/src/playout/take.ts +++ b/packages/job-worker/src/playout/take.ts @@ -178,20 +178,23 @@ export async function performTakeToNextedPart( } } + // If hold is COMPLETE, clear the hold state by this take if (playoutModel.playlist.holdState === RundownHoldState.COMPLETE) { playoutModel.setHoldState(RundownHoldState.NONE) - // If hold is active, then this take is to clear it + // If hold is ACTIVE, then this take is to complete it } else if (playoutModel.playlist.holdState === RundownHoldState.ACTIVE) { await completeHold(context, playoutModel, await pShowStyle, currentPartInstance) + await updateTimeline(context, playoutModel) + if (span) span.end() return } const takePartInstance = nextPartInstance - if (!takePartInstance) throw new Error('takePart not found!') + if (!takePartInstance) throw new Error('takePartInstance not found!') const takeRundown = playoutModel.getRundown(takePartInstance.partInstance.rundownId) if (!takeRundown) throw new Error(`takeRundown: takeRundown not found! ("${takePartInstance.partInstance.rundownId}")`) @@ -263,12 +266,10 @@ export async function performTakeToNextedPart( // Once everything is synced, we can choose the next part await setNextPart(context, playoutModel, nextPart, false) - // Setup the parts for the HOLD we are starting - if ( - playoutModel.playlist.previousPartInfo && - (playoutModel.playlist.holdState as RundownHoldState) === RundownHoldState.ACTIVE - ) { - startHold(context, currentPartInstance, nextPartInstance) + // If the Hold is PENDING, make it active + if (playoutModel.playlist.holdState === RundownHoldState.PENDING) { + // Setup the parts for the HOLD we are starting + activateHold(context, playoutModel, currentPartInstance, takePartInstance) } await afterTake(context, playoutModel, takePartInstance) @@ -535,35 +536,39 @@ export async function afterTake( /** * A Hold starts by extending the "extendOnHold"-able pieces in the previous Part. */ -function startHold( +function activateHold( context: JobContext, + playoutModel: PlayoutModel, holdFromPartInstance: PlayoutPartInstanceModel | null, holdToPartInstance: PlayoutPartInstanceModel | undefined ) { if (!holdFromPartInstance) throw new Error('previousPart not found!') if (!holdToPartInstance) throw new Error('currentPart not found!') - const span = context.startSpan('startHold') + const span = context.startSpan('activateHold') + + playoutModel.setHoldState(RundownHoldState.ACTIVE) // Make a copy of any item which is flagged as an 'infinite' extension const pieceInstancesToCopy = holdFromPartInstance.pieceInstances.filter((p) => !!p.pieceInstance.piece.extendOnHold) - pieceInstancesToCopy.forEach((instance) => { - if (!instance.pieceInstance.infinite) { - // mark current one as infinite - instance.prepareForHold() - - // This gets deleted once the nextpart is activated, so it doesnt linger for long - const extendedPieceInstance = holdToPartInstance.insertHoldPieceInstance(instance) - - const content = clone(instance.pieceInstance.piece.content) as VTContent | undefined - if (content?.fileName && content.sourceDuration && instance.pieceInstance.plannedStartedPlayback) { - content.seek = Math.min( - content.sourceDuration, - getCurrentTime() - instance.pieceInstance.plannedStartedPlayback - ) - } - extendedPieceInstance.updatePieceProps({ content }) + for (const instance of pieceInstancesToCopy) { + // skip any infinites + if (instance.pieceInstance.infinite) continue + + instance.prepareForHold() + + // This gets deleted once the nextpart is activated, so it doesnt linger for long + const extendedPieceInstance = holdToPartInstance.insertHoldPieceInstance(instance) + + const content = clone(instance.pieceInstance.piece.content) as VTContent | undefined + if (content?.fileName && content.sourceDuration && instance.pieceInstance.plannedStartedPlayback) { + content.seek = Math.min( + content.sourceDuration, + getCurrentTime() - instance.pieceInstance.plannedStartedPlayback + ) } - }) + extendedPieceInstance.updatePieceProps({ content }) + } + if (span) span.end() } @@ -575,19 +580,16 @@ async function completeHold( ): Promise { playoutModel.setHoldState(RundownHoldState.COMPLETE) - if (playoutModel.playlist.currentPartInfo) { - if (!currentPartInstance) throw new Error('currentPart not found!') + if (!playoutModel.playlist.currentPartInfo) return + if (!currentPartInstance) throw new Error('currentPart not found!') - // Clear the current extension line - innerStopPieces( - context, - playoutModel, - showStyleCompound.sourceLayers, - currentPartInstance, - (p) => !!p.infinite?.fromHold, - undefined - ) - } - - await updateTimeline(context, playoutModel) + // Clear the current extension line + innerStopPieces( + context, + playoutModel, + showStyleCompound.sourceLayers, + currentPartInstance, + (p) => !!p.infinite?.fromHold, + undefined + ) } diff --git a/packages/job-worker/src/playout/timings/partPlayback.ts b/packages/job-worker/src/playout/timings/partPlayback.ts index 8c3fc07d16..279d1dd410 100644 --- a/packages/job-worker/src/playout/timings/partPlayback.ts +++ b/packages/job-worker/src/playout/timings/partPlayback.ts @@ -58,6 +58,7 @@ export async function onPartPlaybackStarted( // this is the next part, clearly an autoNext has taken place playoutModel.cycleSelectedPartInstances() + playoutModel.resetHoldState() reportPartInstanceHasStarted(context, playoutModel, playingPartInstance, data.startedPlayback) From 4253eea19e7354532b0bf56957b5fc66a3daa121 Mon Sep 17 00:00:00 2001 From: Jan Starzak Date: Tue, 7 Jan 2025 11:25:26 +0100 Subject: [PATCH 8/8] chore(release): 1.51.5 --- meteor/CHANGELOG.md | 7 ++++ meteor/package.json | 2 +- meteor/yarn.lock | 12 +++--- packages/blueprints-integration/CHANGELOG.md | 8 ++++ packages/blueprints-integration/package.json | 4 +- packages/corelib/package.json | 6 +-- packages/documentation/package.json | 2 +- packages/job-worker/package.json | 8 ++-- packages/lerna.json | 2 +- packages/live-status-gateway/package.json | 10 ++--- packages/mos-gateway/CHANGELOG.md | 8 ++++ packages/mos-gateway/package.json | 6 +-- packages/openapi/package.json | 2 +- packages/package.json | 2 +- packages/playout-gateway/CHANGELOG.md | 8 ++++ packages/playout-gateway/package.json | 6 +-- packages/server-core-integration/CHANGELOG.md | 8 ++++ packages/server-core-integration/package.json | 4 +- packages/shared-lib/package.json | 2 +- packages/yarn.lock | 38 +++++++++---------- 20 files changed, 92 insertions(+), 53 deletions(-) diff --git a/meteor/CHANGELOG.md b/meteor/CHANGELOG.md index e4498ae87c..f0e4b48d77 100644 --- a/meteor/CHANGELOG.md +++ b/meteor/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.51.5](///compare/v1.51.4...v1.51.5) (2025-01-07) + + +### Bug Fixes + +* **job-worker/playout:** Hold mode doesn't work at all a7d6999 + ### [1.51.4](///compare/v1.51.3...v1.51.4) (2024-12-04) diff --git a/meteor/package.json b/meteor/package.json index 91f635f3a0..9ffa5aae53 100644 --- a/meteor/package.json +++ b/meteor/package.json @@ -1,6 +1,6 @@ { "name": "automation-core", - "version": "1.51.4", + "version": "1.51.5", "private": true, "engines": { "node": ">=14.19.1" diff --git a/meteor/yarn.lock b/meteor/yarn.lock index c22865dcff..65328eed31 100644 --- a/meteor/yarn.lock +++ b/meteor/yarn.lock @@ -1321,7 +1321,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@portal:../packages/blueprints-integration::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.5 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: node @@ -1362,8 +1362,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sofie-automation/corelib@portal:../packages/corelib::locator=automation-core%40workspace%3A." dependencies: - "@sofie-automation/blueprints-integration": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/blueprints-integration": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -1394,9 +1394,9 @@ __metadata: resolution: "@sofie-automation/job-worker@portal:../packages/job-worker::locator=automation-core%40workspace%3A." dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.4 - "@sofie-automation/corelib": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/blueprints-integration": 1.51.5 + "@sofie-automation/corelib": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 diff --git a/packages/blueprints-integration/CHANGELOG.md b/packages/blueprints-integration/CHANGELOG.md index 4105116d47..6402ee17d3 100644 --- a/packages/blueprints-integration/CHANGELOG.md +++ b/packages/blueprints-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.5](https://github.com/nrkno/sofie-core/compare/v1.51.4...v1.51.5) (2025-01-07) + +**Note:** Version bump only for package @sofie-automation/blueprints-integration + + + + + ## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) **Note:** Version bump only for package @sofie-automation/blueprints-integration diff --git a/packages/blueprints-integration/package.json b/packages/blueprints-integration/package.json index 2af513ab05..6bc28f61b3 100644 --- a/packages/blueprints-integration/package.json +++ b/packages/blueprints-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/blueprints-integration", - "version": "1.51.4", + "version": "1.51.5", "description": "Library to define the interaction between core and the blueprints.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -38,7 +38,7 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/shared-lib": "1.51.5", "tslib": "^2.6.2", "type-fest": "^3.13.1" }, diff --git a/packages/corelib/package.json b/packages/corelib/package.json index 1be22fa65f..d4030a8f9c 100644 --- a/packages/corelib/package.json +++ b/packages/corelib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/corelib", - "version": "1.51.4", + "version": "1.51.5", "private": true, "description": "Internal library for some types shared by core and workers", "main": "dist/index.js", @@ -39,8 +39,8 @@ "/LICENSE" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.4", - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/blueprints-integration": "1.51.5", + "@sofie-automation/shared-lib": "1.51.5", "fast-clone": "^1.5.13", "i18next": "^21.10.0", "influx": "^5.9.3", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 28ad6a1d6b..4512f72057 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -1,6 +1,6 @@ { "name": "sofie-documentation", - "version": "1.51.4", + "version": "1.51.5", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/packages/job-worker/package.json b/packages/job-worker/package.json index bbb939e723..8029fc1d6d 100644 --- a/packages/job-worker/package.json +++ b/packages/job-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/job-worker", - "version": "1.51.4", + "version": "1.51.5", "description": "Worker for things", "main": "dist/index.js", "license": "MIT", @@ -41,9 +41,9 @@ ], "dependencies": { "@slack/webhook": "^6.1.0", - "@sofie-automation/blueprints-integration": "1.51.4", - "@sofie-automation/corelib": "1.51.4", - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/blueprints-integration": "1.51.5", + "@sofie-automation/corelib": "1.51.5", + "@sofie-automation/shared-lib": "1.51.5", "amqplib": "^0.10.3", "deepmerge": "^4.3.1", "elastic-apm-node": "^3.51.0", diff --git a/packages/lerna.json b/packages/lerna.json index 3aee830fb3..819bc12178 100644 --- a/packages/lerna.json +++ b/packages/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.51.4", + "version": "1.51.5", "npmClient": "yarn", "useWorkspaces": true } diff --git a/packages/live-status-gateway/package.json b/packages/live-status-gateway/package.json index 0cd6b534b4..3c1ddd1d5d 100644 --- a/packages/live-status-gateway/package.json +++ b/packages/live-status-gateway/package.json @@ -1,6 +1,6 @@ { "name": "live-status-gateway", - "version": "1.51.4", + "version": "1.51.5", "private": true, "description": "Provides state from Sofie over sockets", "license": "MIT", @@ -53,10 +53,10 @@ "production" ], "dependencies": { - "@sofie-automation/blueprints-integration": "1.51.4", - "@sofie-automation/corelib": "1.51.4", - "@sofie-automation/server-core-integration": "1.51.4", - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/blueprints-integration": "1.51.5", + "@sofie-automation/corelib": "1.51.5", + "@sofie-automation/server-core-integration": "1.51.5", + "@sofie-automation/shared-lib": "1.51.5", "debug": "^4.3.4", "fast-clone": "^1.5.13", "influx": "^5.9.3", diff --git a/packages/mos-gateway/CHANGELOG.md b/packages/mos-gateway/CHANGELOG.md index 12651308e8..4cac07fa5a 100644 --- a/packages/mos-gateway/CHANGELOG.md +++ b/packages/mos-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.5](https://github.com/nrkno/sofie-core/compare/v1.51.4...v1.51.5) (2025-01-07) + +**Note:** Version bump only for package mos-gateway + + + + + ## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) **Note:** Version bump only for package mos-gateway diff --git a/packages/mos-gateway/package.json b/packages/mos-gateway/package.json index d8c3461b16..3f6d2e949b 100644 --- a/packages/mos-gateway/package.json +++ b/packages/mos-gateway/package.json @@ -1,6 +1,6 @@ { "name": "mos-gateway", - "version": "1.51.4", + "version": "1.51.5", "private": true, "description": "MOS-Gateway for the Sofie project", "license": "MIT", @@ -66,8 +66,8 @@ ], "dependencies": { "@mos-connection/connector": "4.1.1", - "@sofie-automation/server-core-integration": "1.51.4", - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/server-core-integration": "1.51.5", + "@sofie-automation/shared-lib": "1.51.5", "tslib": "^2.6.2", "type-fest": "^3.13.1", "underscore": "^1.13.6", diff --git a/packages/openapi/package.json b/packages/openapi/package.json index 4f9e693cc6..a887c805e0 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/openapi", - "version": "1.51.4", + "version": "1.51.5", "license": "MIT", "repository": { "type": "git", diff --git a/packages/package.json b/packages/package.json index b38fcdc147..8ca58b6de3 100644 --- a/packages/package.json +++ b/packages/package.json @@ -65,4 +65,4 @@ }, "name": "packages", "packageManager": "yarn@3.5.0" -} \ No newline at end of file +} diff --git a/packages/playout-gateway/CHANGELOG.md b/packages/playout-gateway/CHANGELOG.md index 0396e96547..2fadf7cf31 100644 --- a/packages/playout-gateway/CHANGELOG.md +++ b/packages/playout-gateway/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.5](https://github.com/nrkno/sofie-core/compare/v1.51.4...v1.51.5) (2025-01-07) + +**Note:** Version bump only for package playout-gateway + + + + + ## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) **Note:** Version bump only for package playout-gateway diff --git a/packages/playout-gateway/package.json b/packages/playout-gateway/package.json index 77702d6d29..7d99add74d 100644 --- a/packages/playout-gateway/package.json +++ b/packages/playout-gateway/package.json @@ -1,6 +1,6 @@ { "name": "playout-gateway", - "version": "1.51.4", + "version": "1.51.5", "private": true, "description": "Connect to Core, play stuff", "license": "MIT", @@ -56,8 +56,8 @@ "production" ], "dependencies": { - "@sofie-automation/server-core-integration": "1.51.4", - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/server-core-integration": "1.51.5", + "@sofie-automation/shared-lib": "1.51.5", "debug": "^4.3.4", "influx": "^5.9.3", "timeline-state-resolver": "9.2.1", diff --git a/packages/server-core-integration/CHANGELOG.md b/packages/server-core-integration/CHANGELOG.md index b259defec9..915d072c8f 100644 --- a/packages/server-core-integration/CHANGELOG.md +++ b/packages/server-core-integration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.51.5](https://github.com/nrkno/sofie-core/compare/v1.51.4...v1.51.5) (2025-01-07) + +**Note:** Version bump only for package @sofie-automation/server-core-integration + + + + + ## [1.51.4](https://github.com/nrkno/sofie-core/compare/v1.51.3...v1.51.4) (2024-12-04) **Note:** Version bump only for package @sofie-automation/server-core-integration diff --git a/packages/server-core-integration/package.json b/packages/server-core-integration/package.json index e8be09e879..60e0be8345 100644 --- a/packages/server-core-integration/package.json +++ b/packages/server-core-integration/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/server-core-integration", - "version": "1.51.4", + "version": "1.51.5", "description": "Library for connecting to Core", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -70,7 +70,7 @@ "production" ], "dependencies": { - "@sofie-automation/shared-lib": "1.51.4", + "@sofie-automation/shared-lib": "1.51.5", "ejson": "^2.2.3", "eventemitter3": "^4.0.7", "faye-websocket": "^0.11.4", diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 60928b7eaa..50e78219f8 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -1,6 +1,6 @@ { "name": "@sofie-automation/shared-lib", - "version": "1.51.4", + "version": "1.51.5", "description": "Library for types & values shared by core, workers and gateways", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/yarn.lock b/packages/yarn.lock index 2cd2a6209b..0134d3c2ca 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -4565,11 +4565,11 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/blueprints-integration@1.51.4, @sofie-automation/blueprints-integration@workspace:blueprints-integration": +"@sofie-automation/blueprints-integration@1.51.5, @sofie-automation/blueprints-integration@workspace:blueprints-integration": version: 0.0.0-use.local resolution: "@sofie-automation/blueprints-integration@workspace:blueprints-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.5 tslib: ^2.6.2 type-fest: ^3.13.1 languageName: unknown @@ -4606,12 +4606,12 @@ __metadata: languageName: node linkType: hard -"@sofie-automation/corelib@1.51.4, @sofie-automation/corelib@workspace:corelib": +"@sofie-automation/corelib@1.51.5, @sofie-automation/corelib@workspace:corelib": version: 0.0.0-use.local resolution: "@sofie-automation/corelib@workspace:corelib" dependencies: - "@sofie-automation/blueprints-integration": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/blueprints-integration": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 fast-clone: ^1.5.13 i18next: ^21.10.0 influx: ^5.9.3 @@ -4642,9 +4642,9 @@ __metadata: resolution: "@sofie-automation/job-worker@workspace:job-worker" dependencies: "@slack/webhook": ^6.1.0 - "@sofie-automation/blueprints-integration": 1.51.4 - "@sofie-automation/corelib": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/blueprints-integration": 1.51.5 + "@sofie-automation/corelib": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 amqplib: ^0.10.3 deepmerge: ^4.3.1 elastic-apm-node: ^3.51.0 @@ -4674,11 +4674,11 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/server-core-integration@1.51.4, @sofie-automation/server-core-integration@workspace:server-core-integration": +"@sofie-automation/server-core-integration@1.51.5, @sofie-automation/server-core-integration@workspace:server-core-integration": version: 0.0.0-use.local resolution: "@sofie-automation/server-core-integration@workspace:server-core-integration" dependencies: - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/shared-lib": 1.51.5 ejson: ^2.2.3 eventemitter3: ^4.0.7 faye-websocket: ^0.11.4 @@ -4688,7 +4688,7 @@ __metadata: languageName: unknown linkType: soft -"@sofie-automation/shared-lib@1.51.4, @sofie-automation/shared-lib@workspace:shared-lib": +"@sofie-automation/shared-lib@1.51.5, @sofie-automation/shared-lib@workspace:shared-lib": version: 0.0.0-use.local resolution: "@sofie-automation/shared-lib@workspace:shared-lib" dependencies: @@ -15334,10 +15334,10 @@ asn1@evs-broadcast/node-asn1: "@asyncapi/generator": ^1.17.25 "@asyncapi/html-template": ^2.3.9 "@asyncapi/nodejs-ws-template": ^0.9.36 - "@sofie-automation/blueprints-integration": 1.51.4 - "@sofie-automation/corelib": 1.51.4 - "@sofie-automation/server-core-integration": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/blueprints-integration": 1.51.5 + "@sofie-automation/corelib": 1.51.5 + "@sofie-automation/server-core-integration": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 debug: ^4.3.4 fast-clone: ^1.5.13 influx: ^5.9.3 @@ -17410,8 +17410,8 @@ asn1@evs-broadcast/node-asn1: resolution: "mos-gateway@workspace:mos-gateway" dependencies: "@mos-connection/connector": 4.1.1 - "@sofie-automation/server-core-integration": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/server-core-integration": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 tslib: ^2.6.2 type-fest: ^3.13.1 underscore: ^1.13.6 @@ -19397,8 +19397,8 @@ asn1@evs-broadcast/node-asn1: version: 0.0.0-use.local resolution: "playout-gateway@workspace:playout-gateway" dependencies: - "@sofie-automation/server-core-integration": 1.51.4 - "@sofie-automation/shared-lib": 1.51.4 + "@sofie-automation/server-core-integration": 1.51.5 + "@sofie-automation/shared-lib": 1.51.5 debug: ^4.3.4 influx: ^5.9.3 timeline-state-resolver: 9.2.1