Skip to content

feat: rework ExpectedPackages generation/management to share documents within rundown/bucket #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: feat/expected-packages-restructure-ownership
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions meteor/server/api/ingest/packageInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,28 @@ export async function onUpdatedPackageInfo(packageId: ExpectedPackageId, _doc: P
return
}

if (pkg.package.listenToPackageInfoUpdates) {
for (const source of pkg.ingestSources) {
switch (source.fromPieceType) {
case ExpectedPackageDBType.PIECE:
case ExpectedPackageDBType.ADLIB_PIECE:
case ExpectedPackageDBType.ADLIB_ACTION:
case ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
case ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
case ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
onUpdatedPackageInfoForRundownDebounce(pkg)
break
case ExpectedPackageDBType.BUCKET_ADLIB:
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
onUpdatedPackageInfoForBucketItemDebounce(pkg, source)
break
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
onUpdatedPackageInfoForStudioBaselineDebounce(pkg)
break
default:
assertNever(source)
break
}
for (const source of pkg.ingestSources) {
if (!source.listenToPackageInfoUpdates) continue

switch (source.fromPieceType) {
case ExpectedPackageDBType.PIECE:
case ExpectedPackageDBType.ADLIB_PIECE:
case ExpectedPackageDBType.ADLIB_ACTION:
case ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
case ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
case ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
onUpdatedPackageInfoForRundownDebounce(pkg)
break
case ExpectedPackageDBType.BUCKET_ADLIB:
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
onUpdatedPackageInfoForBucketItemDebounce(pkg, source)
break
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
onUpdatedPackageInfoForStudioBaselineDebounce(pkg)
break
default:
assertNever(source)
break
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions meteor/server/migration/X_X_X.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
pieceId: pkg.pieceId,
partId: pkg.partId,
segmentId: pkg.segmentId,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.ADLIB_ACTION:
Expand All @@ -64,26 +66,34 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
pieceId: pkg.pieceId,
partId: pkg.partId,
segmentId: pkg.segmentId,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
rundownId = pkg.rundownId
ingestSource = {
fromPieceType: pkg.fromPieceType,
pieceId: pkg.pieceId,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
rundownId = pkg.rundownId
ingestSource = {
fromPieceType: pkg.fromPieceType,
pieceId: pkg.pieceId,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
rundownId = pkg.rundownId
ingestSource = {
fromPieceType: pkg.fromPieceType,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.BUCKET_ADLIB:
Expand All @@ -92,6 +102,8 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
fromPieceType: pkg.fromPieceType,
pieceId: pkg.pieceId,
pieceExternalId: pkg.pieceExternalId,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
Expand All @@ -100,11 +112,15 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
fromPieceType: pkg.fromPieceType,
pieceId: pkg.pieceId,
pieceExternalId: pkg.pieceExternalId,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
case PackagesPreR53.ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
ingestSource = {
fromPieceType: pkg.fromPieceType,
blueprintPackageId: pkg.blueprintPackageId,
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
}
break
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import {
VTContent,
} from '@sofie-automation/blueprints-integration'
import {
ExpectedPackageDBType,
getExpectedPackageIdForPieceInstance,
getExpectedPackageIdFromIngestSource,
getExpectedPackageIdNew,
} from '@sofie-automation/corelib/dist/dataModel/ExpectedPackages'
import {
BucketId,
Expand Down Expand Up @@ -666,21 +665,7 @@ async function checkPieceContentExpectedPackageStatus(

checkedPackageContainers.add(matchedPackageContainer[0])

const expectedPackageIds = [
// Synthesize the expected packageId from the piece
getExpectedPackageIdFromIngestSource(
packageOwnerId,
{
fromPieceType: ExpectedPackageDBType.PIECE,
// HACK: This shouldn't be cast as any, because this could be a bucket piece, but that gives the same result
pieceId: piece._id as any,
// HACK: We need a value, but the method doesn't use them..
partId: piece._id as any,
segmentId: piece._id as any,
},
expectedPackage._id
),
]
const expectedPackageIds = [getExpectedPackageIdNew(packageOwnerId, expectedPackage)]
if (piece.pieceInstanceId) {
// If this is a PieceInstance, try looking up the PieceInstance first
expectedPackageIds.unshift(
Expand Down
97 changes: 36 additions & 61 deletions packages/corelib/src/dataModel/ExpectedPackages.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ExpectedPackage, Time } from '@sofie-automation/blueprints-integration'
import { protectString, unprotectString } from '../protectedString.js'
import { getHash, assertNever } from '../lib.js'
import { protectString } from '../protectedString.js'
import { getHash, hashObj } from '../lib.js'
import {
AdLibActionId,
BucketAdLibActionId,
Expand Down Expand Up @@ -51,33 +51,43 @@ export interface ExpectedPackageDB {

created: Time

package: ReadonlyDeep<ExpectedPackage.Any>
package: ReadonlyDeep<Omit<ExpectedPackage.Base, 'listenToPackageInfoUpdates'>>

// HACK: This should be ExpectedPackageIngestSource[], but for the first iteration this is limited to a single source
ingestSources: [ExpectedPackageIngestSource]
/**
* The ingest sources that generated this package.
*/
ingestSources: ExpectedPackageIngestSource[]

// playoutSources: {
// /** Any playout PieceInstance. This is limited to the current and next partInstances */
// pieceInstanceIds: PieceInstanceId[]
// }
}

export interface ExpectedPackageIngestSourceBucketPiece {
export interface ExpectedPackageIngestSourceBase {
/** The id of the package as known by the blueprints */
blueprintPackageId: string

/** Whether the blueprints are listening for updates to packageInfos for this package */
listenToPackageInfoUpdates: boolean | undefined
}

export interface ExpectedPackageIngestSourceBucketAdlibPiece extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.BUCKET_ADLIB
/** The Bucket adlib this package belongs to */
pieceId: BucketAdLibId
/** The `externalId` of the Bucket adlib this package belongs to */
pieceExternalId: string
}
export interface ExpectedPackageIngestSourceBucketAdlibAction {
export interface ExpectedPackageIngestSourceBucketAdlibAction extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.BUCKET_ADLIB_ACTION
/** The Bucket adlib-action this package belongs to */
pieceId: BucketAdLibActionId
/** The `externalId` of the Bucket adlib-action this package belongs to */
pieceExternalId: string
}

export interface ExpectedPackageIngestSourcePiece {
export interface ExpectedPackageIngestSourcePiece extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.PIECE | ExpectedPackageDBType.ADLIB_PIECE
/** The Piece this package belongs to */
pieceId: PieceId
Expand All @@ -86,7 +96,7 @@ export interface ExpectedPackageIngestSourcePiece {
/** The Segment this package belongs to */
segmentId: SegmentId
}
export interface ExpectedPackageIngestSourceAdlibAction {
export interface ExpectedPackageIngestSourceAdlibAction extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.ADLIB_ACTION
/** The Piece this package belongs to */
pieceId: AdLibActionId
Expand All @@ -95,29 +105,29 @@ export interface ExpectedPackageIngestSourceAdlibAction {
/** The Segment this package belongs to */
segmentId: SegmentId
}
export interface ExpectedPackageIngestSourceBaselineAdlibPiece {
export interface ExpectedPackageIngestSourceBaselineAdlibPiece extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.BASELINE_ADLIB_PIECE
/** The Piece this package belongs to */
pieceId: PieceId
}
export interface ExpectedPackageIngestSourceBaselineAdlibAction {
export interface ExpectedPackageIngestSourceBaselineAdlibAction extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.BASELINE_ADLIB_ACTION
/** The Piece this package belongs to */
pieceId: RundownBaselineAdLibActionId
}
export interface ExpectedPackageIngestSourceBaselineObjects {
export interface ExpectedPackageIngestSourceBaselineObjects extends ExpectedPackageIngestSourceBase {
fromPieceType: ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS
}

export interface ExpectedPackageIngestSourceStudioBaseline {
export interface ExpectedPackageIngestSourceStudioBaseline extends ExpectedPackageIngestSourceBase {
// Future: Technically this is a playout source, but for now it needs to be treated as an ingest source
fromPieceType: ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS
}

export type ExpectedPackageIngestSourcePart = ExpectedPackageIngestSourcePiece | ExpectedPackageIngestSourceAdlibAction

export type ExpectedPackageIngestSourceBucket =
| ExpectedPackageIngestSourceBucketPiece
| ExpectedPackageIngestSourceBucketAdlibPiece
| ExpectedPackageIngestSourceBucketAdlibAction

export type ExpectedPackageIngestSourceRundownBaseline =
Expand Down Expand Up @@ -145,56 +155,21 @@ export function getExpectedPackageIdForPieceInstance(
}

/**
* Generate the temporary expectedPackageId for the given package.
* Note: This will soon be replaced with a new flow based on the contentVersionHash once shared ownership is implemented.
* Generate the expectedPackageId for the given expectedPackage.
* This is a stable id derived from the package and its parent. This document is expected to be owned by multiple sources.
*/
export function getExpectedPackageIdFromIngestSource(
export function getExpectedPackageIdNew(
/** Preferably a RundownId or BucketId, but StudioId is allowed when not owned by a rundown or bucket */
parentId: RundownId | StudioId | BucketId,
source: ExpectedPackageIngestSource,
/** The locally unique id of the expectedPackage */
localExpectedPackageId: ExpectedPackage.Base['_id']
expectedPackage: ReadonlyDeep<Omit<ExpectedPackage.Base, 'listenToPackageInfoUpdates'>>
): ExpectedPackageId {
let ownerId: string
const ownerPieceType = source.fromPieceType
switch (source.fromPieceType) {
case ExpectedPackageDBType.PIECE:
case ExpectedPackageDBType.ADLIB_PIECE:
case ExpectedPackageDBType.ADLIB_ACTION:
case ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
case ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
ownerId = unprotectString(source.pieceId)
break
case ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
ownerId = 'rundownBaselineObjects'
break
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
ownerId = 'studioBaseline'
break
case ExpectedPackageDBType.BUCKET_ADLIB:
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
ownerId = unprotectString(source.pieceId)
break

default:
assertNever(source)
throw new Error(`Unknown fromPieceType "${ownerPieceType}"`)
}
return protectString(`${parentId}_${ownerId}_${getHash(localExpectedPackageId)}`)
// This may be too agressive, but we don't know how to merge some of the properties
const objHash = hashObj({
...expectedPackage,
_id: '', // Ignore the _id, this is not guaranteed to be stable
listenToPackageInfoUpdates: false, // Not relevant for the hash
} satisfies ReadonlyDeep<ExpectedPackage.Base>)

return protectString(`${parentId}_${getHash(objHash)}`)
}

// Future implementation of id generation, once shared ownership is implemented
// export function getExpectedPackageIdNew(
// /** _id of the rundown*/
// rundownId: RundownId,
// /** The locally unique id of the expectedPackage */
// expectedPackage: ReadonlyDeep<ExpectedPackage.Any>
// ): ExpectedPackageId {
// // This may be too agressive, but we don't know how to merge some of the properties
// const objHash = hashObj({
// ...expectedPackage,
// listenToPackageInfoUpdates: false, // Not relevant for the hash
// } satisfies ReadonlyDeep<ExpectedPackage.Any>)

// return protectString(`${rundownId}_${getHash(objHash)}`)
// }
Loading
Loading