Skip to content

Commit 8ebf2a2

Browse files
committed
feat: rework ExpectedPackages generation/management to share documents within rundown/bucket
1 parent fe2da3f commit 8ebf2a2

File tree

23 files changed

+558
-513
lines changed

23 files changed

+558
-513
lines changed

meteor/server/api/ingest/packageInfo.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,28 @@ export async function onUpdatedPackageInfo(packageId: ExpectedPackageId, _doc: P
2525
return
2626
}
2727

28-
if (pkg.package.listenToPackageInfoUpdates) {
29-
for (const source of pkg.ingestSources) {
30-
switch (source.fromPieceType) {
31-
case ExpectedPackageDBType.PIECE:
32-
case ExpectedPackageDBType.ADLIB_PIECE:
33-
case ExpectedPackageDBType.ADLIB_ACTION:
34-
case ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
35-
case ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
36-
case ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
37-
onUpdatedPackageInfoForRundownDebounce(pkg)
38-
break
39-
case ExpectedPackageDBType.BUCKET_ADLIB:
40-
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
41-
onUpdatedPackageInfoForBucketItemDebounce(pkg, source)
42-
break
43-
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
44-
onUpdatedPackageInfoForStudioBaselineDebounce(pkg)
45-
break
46-
default:
47-
assertNever(source)
48-
break
49-
}
28+
for (const source of pkg.ingestSources) {
29+
if (!source.listenToPackageInfoUpdates) continue
30+
31+
switch (source.fromPieceType) {
32+
case ExpectedPackageDBType.PIECE:
33+
case ExpectedPackageDBType.ADLIB_PIECE:
34+
case ExpectedPackageDBType.ADLIB_ACTION:
35+
case ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
36+
case ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
37+
case ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
38+
onUpdatedPackageInfoForRundownDebounce(pkg)
39+
break
40+
case ExpectedPackageDBType.BUCKET_ADLIB:
41+
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
42+
onUpdatedPackageInfoForBucketItemDebounce(pkg, source)
43+
break
44+
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
45+
onUpdatedPackageInfoForStudioBaselineDebounce(pkg)
46+
break
47+
default:
48+
assertNever(source)
49+
break
5050
}
5151
}
5252
}

meteor/server/migration/X_X_X.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
5555
pieceId: pkg.pieceId,
5656
partId: pkg.partId,
5757
segmentId: pkg.segmentId,
58+
blueprintPackageId: pkg.blueprintPackageId,
59+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
5860
}
5961
break
6062
case PackagesPreR53.ExpectedPackageDBType.ADLIB_ACTION:
@@ -64,26 +66,34 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
6466
pieceId: pkg.pieceId,
6567
partId: pkg.partId,
6668
segmentId: pkg.segmentId,
69+
blueprintPackageId: pkg.blueprintPackageId,
70+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
6771
}
6872
break
6973
case PackagesPreR53.ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
7074
rundownId = pkg.rundownId
7175
ingestSource = {
7276
fromPieceType: pkg.fromPieceType,
7377
pieceId: pkg.pieceId,
78+
blueprintPackageId: pkg.blueprintPackageId,
79+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
7480
}
7581
break
7682
case PackagesPreR53.ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
7783
rundownId = pkg.rundownId
7884
ingestSource = {
7985
fromPieceType: pkg.fromPieceType,
8086
pieceId: pkg.pieceId,
87+
blueprintPackageId: pkg.blueprintPackageId,
88+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
8189
}
8290
break
8391
case PackagesPreR53.ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
8492
rundownId = pkg.rundownId
8593
ingestSource = {
8694
fromPieceType: pkg.fromPieceType,
95+
blueprintPackageId: pkg.blueprintPackageId,
96+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
8797
}
8898
break
8999
case PackagesPreR53.ExpectedPackageDBType.BUCKET_ADLIB:
@@ -92,6 +102,8 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
92102
fromPieceType: pkg.fromPieceType,
93103
pieceId: pkg.pieceId,
94104
pieceExternalId: pkg.pieceExternalId,
105+
blueprintPackageId: pkg.blueprintPackageId,
106+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
95107
}
96108
break
97109
case PackagesPreR53.ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
@@ -100,11 +112,15 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
100112
fromPieceType: pkg.fromPieceType,
101113
pieceId: pkg.pieceId,
102114
pieceExternalId: pkg.pieceExternalId,
115+
blueprintPackageId: pkg.blueprintPackageId,
116+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
103117
}
104118
break
105119
case PackagesPreR53.ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
106120
ingestSource = {
107121
fromPieceType: pkg.fromPieceType,
122+
blueprintPackageId: pkg.blueprintPackageId,
123+
listenToPackageInfoUpdates: pkg.listenToPackageInfoUpdates,
108124
}
109125
break
110126
default:

meteor/server/publications/pieceContentStatusUI/checkPieceContentStatus.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ import {
1111
VTContent,
1212
} from '@sofie-automation/blueprints-integration'
1313
import {
14-
ExpectedPackageDBType,
1514
getExpectedPackageIdForPieceInstance,
16-
getExpectedPackageIdFromIngestSource,
15+
getExpectedPackageIdNew,
1716
} from '@sofie-automation/corelib/dist/dataModel/ExpectedPackages'
1817
import {
1918
BucketId,
@@ -666,21 +665,7 @@ async function checkPieceContentExpectedPackageStatus(
666665

667666
checkedPackageContainers.add(matchedPackageContainer[0])
668667

669-
const expectedPackageIds = [
670-
// Synthesize the expected packageId from the piece
671-
getExpectedPackageIdFromIngestSource(
672-
packageOwnerId,
673-
{
674-
fromPieceType: ExpectedPackageDBType.PIECE,
675-
// HACK: This shouldn't be cast as any, because this could be a bucket piece, but that gives the same result
676-
pieceId: piece._id as any,
677-
// HACK: We need a value, but the method doesn't use them..
678-
partId: piece._id as any,
679-
segmentId: piece._id as any,
680-
},
681-
expectedPackage._id
682-
),
683-
]
668+
const expectedPackageIds = [getExpectedPackageIdNew(packageOwnerId, expectedPackage)]
684669
if (piece.pieceInstanceId) {
685670
// If this is a PieceInstance, try looking up the PieceInstance first
686671
expectedPackageIds.unshift(

packages/corelib/src/dataModel/ExpectedPackages.ts

Lines changed: 36 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ExpectedPackage, Time } from '@sofie-automation/blueprints-integration'
2-
import { protectString, unprotectString } from '../protectedString.js'
3-
import { getHash, assertNever } from '../lib.js'
2+
import { protectString } from '../protectedString.js'
3+
import { getHash, hashObj } from '../lib.js'
44
import {
55
AdLibActionId,
66
BucketAdLibActionId,
@@ -51,33 +51,43 @@ export interface ExpectedPackageDB {
5151

5252
created: Time
5353

54-
package: ReadonlyDeep<ExpectedPackage.Any>
54+
package: ReadonlyDeep<Omit<ExpectedPackage.Base, 'listenToPackageInfoUpdates'>>
5555

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

5961
// playoutSources: {
6062
// /** Any playout PieceInstance. This is limited to the current and next partInstances */
6163
// pieceInstanceIds: PieceInstanceId[]
6264
// }
6365
}
6466

65-
export interface ExpectedPackageIngestSourceBucketPiece {
67+
export interface ExpectedPackageIngestSourceBase {
68+
/** The id of the package as known by the blueprints */
69+
blueprintPackageId: string
70+
71+
/** Whether the blueprints are listening for updates to packageInfos for this package */
72+
listenToPackageInfoUpdates: boolean | undefined
73+
}
74+
75+
export interface ExpectedPackageIngestSourceBucketAdlibPiece extends ExpectedPackageIngestSourceBase {
6676
fromPieceType: ExpectedPackageDBType.BUCKET_ADLIB
6777
/** The Bucket adlib this package belongs to */
6878
pieceId: BucketAdLibId
6979
/** The `externalId` of the Bucket adlib this package belongs to */
7080
pieceExternalId: string
7181
}
72-
export interface ExpectedPackageIngestSourceBucketAdlibAction {
82+
export interface ExpectedPackageIngestSourceBucketAdlibAction extends ExpectedPackageIngestSourceBase {
7383
fromPieceType: ExpectedPackageDBType.BUCKET_ADLIB_ACTION
7484
/** The Bucket adlib-action this package belongs to */
7585
pieceId: BucketAdLibActionId
7686
/** The `externalId` of the Bucket adlib-action this package belongs to */
7787
pieceExternalId: string
7888
}
7989

80-
export interface ExpectedPackageIngestSourcePiece {
90+
export interface ExpectedPackageIngestSourcePiece extends ExpectedPackageIngestSourceBase {
8191
fromPieceType: ExpectedPackageDBType.PIECE | ExpectedPackageDBType.ADLIB_PIECE
8292
/** The Piece this package belongs to */
8393
pieceId: PieceId
@@ -86,7 +96,7 @@ export interface ExpectedPackageIngestSourcePiece {
8696
/** The Segment this package belongs to */
8797
segmentId: SegmentId
8898
}
89-
export interface ExpectedPackageIngestSourceAdlibAction {
99+
export interface ExpectedPackageIngestSourceAdlibAction extends ExpectedPackageIngestSourceBase {
90100
fromPieceType: ExpectedPackageDBType.ADLIB_ACTION
91101
/** The Piece this package belongs to */
92102
pieceId: AdLibActionId
@@ -95,29 +105,29 @@ export interface ExpectedPackageIngestSourceAdlibAction {
95105
/** The Segment this package belongs to */
96106
segmentId: SegmentId
97107
}
98-
export interface ExpectedPackageIngestSourceBaselineAdlibPiece {
108+
export interface ExpectedPackageIngestSourceBaselineAdlibPiece extends ExpectedPackageIngestSourceBase {
99109
fromPieceType: ExpectedPackageDBType.BASELINE_ADLIB_PIECE
100110
/** The Piece this package belongs to */
101111
pieceId: PieceId
102112
}
103-
export interface ExpectedPackageIngestSourceBaselineAdlibAction {
113+
export interface ExpectedPackageIngestSourceBaselineAdlibAction extends ExpectedPackageIngestSourceBase {
104114
fromPieceType: ExpectedPackageDBType.BASELINE_ADLIB_ACTION
105115
/** The Piece this package belongs to */
106116
pieceId: RundownBaselineAdLibActionId
107117
}
108-
export interface ExpectedPackageIngestSourceBaselineObjects {
118+
export interface ExpectedPackageIngestSourceBaselineObjects extends ExpectedPackageIngestSourceBase {
109119
fromPieceType: ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS
110120
}
111121

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

117127
export type ExpectedPackageIngestSourcePart = ExpectedPackageIngestSourcePiece | ExpectedPackageIngestSourceAdlibAction
118128

119129
export type ExpectedPackageIngestSourceBucket =
120-
| ExpectedPackageIngestSourceBucketPiece
130+
| ExpectedPackageIngestSourceBucketAdlibPiece
121131
| ExpectedPackageIngestSourceBucketAdlibAction
122132

123133
export type ExpectedPackageIngestSourceRundownBaseline =
@@ -145,56 +155,21 @@ export function getExpectedPackageIdForPieceInstance(
145155
}
146156

147157
/**
148-
* Generate the temporary expectedPackageId for the given package.
149-
* Note: This will soon be replaced with a new flow based on the contentVersionHash once shared ownership is implemented.
158+
* Generate the expectedPackageId for the given expectedPackage.
159+
* This is a stable id derived from the package and its parent. This document is expected to be owned by multiple sources.
150160
*/
151-
export function getExpectedPackageIdFromIngestSource(
161+
export function getExpectedPackageIdNew(
152162
/** Preferably a RundownId or BucketId, but StudioId is allowed when not owned by a rundown or bucket */
153163
parentId: RundownId | StudioId | BucketId,
154-
source: ExpectedPackageIngestSource,
155164
/** The locally unique id of the expectedPackage */
156-
localExpectedPackageId: ExpectedPackage.Base['_id']
165+
expectedPackage: ReadonlyDeep<Omit<ExpectedPackage.Base, 'listenToPackageInfoUpdates'>>
157166
): ExpectedPackageId {
158-
let ownerId: string
159-
const ownerPieceType = source.fromPieceType
160-
switch (source.fromPieceType) {
161-
case ExpectedPackageDBType.PIECE:
162-
case ExpectedPackageDBType.ADLIB_PIECE:
163-
case ExpectedPackageDBType.ADLIB_ACTION:
164-
case ExpectedPackageDBType.BASELINE_ADLIB_PIECE:
165-
case ExpectedPackageDBType.BASELINE_ADLIB_ACTION:
166-
ownerId = unprotectString(source.pieceId)
167-
break
168-
case ExpectedPackageDBType.RUNDOWN_BASELINE_OBJECTS:
169-
ownerId = 'rundownBaselineObjects'
170-
break
171-
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
172-
ownerId = 'studioBaseline'
173-
break
174-
case ExpectedPackageDBType.BUCKET_ADLIB:
175-
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION:
176-
ownerId = unprotectString(source.pieceId)
177-
break
178-
179-
default:
180-
assertNever(source)
181-
throw new Error(`Unknown fromPieceType "${ownerPieceType}"`)
182-
}
183-
return protectString(`${parentId}_${ownerId}_${getHash(localExpectedPackageId)}`)
167+
// This may be too agressive, but we don't know how to merge some of the properties
168+
const objHash = hashObj({
169+
...expectedPackage,
170+
_id: '', // Ignore the _id, this is not guaranteed to be stable
171+
listenToPackageInfoUpdates: false, // Not relevant for the hash
172+
} satisfies ReadonlyDeep<ExpectedPackage.Base>)
173+
174+
return protectString(`${parentId}_${getHash(objHash)}`)
184175
}
185-
186-
// Future implementation of id generation, once shared ownership is implemented
187-
// export function getExpectedPackageIdNew(
188-
// /** _id of the rundown*/
189-
// rundownId: RundownId,
190-
// /** The locally unique id of the expectedPackage */
191-
// expectedPackage: ReadonlyDeep<ExpectedPackage.Any>
192-
// ): ExpectedPackageId {
193-
// // This may be too agressive, but we don't know how to merge some of the properties
194-
// const objHash = hashObj({
195-
// ...expectedPackage,
196-
// listenToPackageInfoUpdates: false, // Not relevant for the hash
197-
// } satisfies ReadonlyDeep<ExpectedPackage.Any>)
198-
199-
// return protectString(`${rundownId}_${getHash(objHash)}`)
200-
// }

0 commit comments

Comments
 (0)