Skip to content

Commit

Permalink
feat: support packageinfo update flow for buckets and studio baseline
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Oct 13, 2023
1 parent 716bef1 commit 4c9834a
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 145 deletions.
2 changes: 2 additions & 0 deletions meteor/server/api/__tests__/cleanup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ async function setDefaultDatatoDB(env: DefaultEnvironment, now: number) {
actionId: '',
display: {} as any,
importVersions: {} as any,
ingestInfo: undefined,
showStyleVariantId,
userData: {} as any,
userDataManifest: {} as any,
Expand All @@ -232,6 +233,7 @@ async function setDefaultDatatoDB(env: DefaultEnvironment, now: number) {
studioId,
showStyleBaseId: env.showStyleBaseId,
importVersions: {} as any,
ingestInfo: undefined,
showStyleVariantId,
_rank: 0,
content: {} as any,
Expand Down
5 changes: 3 additions & 2 deletions meteor/server/api/buckets.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as _ from 'underscore'
import { Meteor } from 'meteor/meteor'
import { Bucket } from '../../lib/collections/Buckets'
import { getRandomId, literal } from '../../lib/lib'
import { getRandomId, getRandomString, literal } from '../../lib/lib'
import { BucketSecurity } from '../security/buckets'
import { BucketAdLib } from '@sofie-automation/corelib/dist/dataModel/BucketAdLibPiece'
import { AdLibAction, AdLibActionCommon } from '@sofie-automation/corelib/dist/dataModel/AdlibAction'
Expand Down Expand Up @@ -165,12 +165,13 @@ export namespace BucketsAPI {
adLibAction = {
...(_.omit(action, ['partId', 'rundownId']) as Omit<AdLibAction, 'partId' | 'rundownId'>),
_id: getRandomId(),
externalId: '', // TODO - is this ok?
externalId: getRandomString(), // This needs to be something unique, so that the regenerate logic doesn't get it mixed up with something else
bucketId: access.bucket._id,
studioId: access.studioId,
showStyleBaseId: rundown.showStyleBaseId,
showStyleVariantId: action.allVariants ? null : rundown.showStyleVariantId,
importVersions: rundown.importVersions,
ingestInfo: undefined,
}
}

Expand Down
151 changes: 70 additions & 81 deletions meteor/server/api/ingest/packageInfo.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { ExpectedPackageDBType } from '@sofie-automation/corelib/dist/dataModel/ExpectedPackages'
import {
ExpectedPackageDBFromBucketAdLib,
ExpectedPackageDBFromBucketAdLibAction,
ExpectedPackageDBFromStudioBaselineObjects,
ExpectedPackageDBType,
} from '@sofie-automation/corelib/dist/dataModel/ExpectedPackages'
import { PackageInfoDB } from '@sofie-automation/corelib/dist/dataModel/PackageInfos'
import { Buckets, ExpectedPackages, Rundowns } from '../../collections'
import { BucketAdLibActions, BucketAdLibs, ExpectedPackages, Rundowns } from '../../collections'
import { assertNever, lazyIgnore } from '../../../lib/lib'
import { logger } from '../../logging'
import { runIngestOperation } from './lib'
import { IngestJobs } from '@sofie-automation/corelib/dist/worker/ingest'
import {
BucketAdLibActionId,
BucketAdLibId,
BucketId,
ExpectedPackageId,
RundownId,
} from '@sofie-automation/corelib/dist/dataModel/Ids'
import { Bucket } from '../../../lib/collections/Buckets'
import { ExpectedPackageId, RundownId } from '@sofie-automation/corelib/dist/dataModel/Ids'
import { Rundown } from '@sofie-automation/corelib/dist/dataModel/Rundown'
import { BucketAdLibAction } from '@sofie-automation/corelib/dist/dataModel/BucketAdLibAction'
import { BucketAdLib } from '@sofie-automation/corelib/dist/dataModel/BucketAdLibPiece'
import { QueueStudioJob } from '../../worker/worker'
import { StudioJobs } from '@sofie-automation/corelib/dist/worker/studio'

export async function onUpdatedPackageInfo(packageId: ExpectedPackageId, _doc: PackageInfoDB | null): Promise<void> {
logger.info(`PackageInfo updated "${packageId}"`)
Expand Down Expand Up @@ -56,40 +58,40 @@ export async function onUpdatedPackageInfo(packageId: ExpectedPackageId, _doc: P
)
break
}
case ExpectedPackageDBType.BUCKET_ADLIB:
case ExpectedPackageDBType.BUCKET_ADLIB: {
const bucketAction = (await BucketAdLibs.findOneAsync(
{ _id: pkg.pieceId, bucketId: pkg.bucketId },
{
projection: { externalId: 1 },
}
)) as Pick<BucketAdLib, 'externalId'>

if (bucketAction) {
onUpdatedPackageInfoForBucketItemDebounce(pkg, bucketAction.externalId)
} else {
logger.info(`onUpdatedPackageInfo: Received update for missing BucketAdLib: ${pkg.pieceId}`)
}

break
}
case ExpectedPackageDBType.BUCKET_ADLIB_ACTION: {
const identifier = `${pkg.bucketId}_${pkg.pieceId}`
const existingEntry = pendingBucketItemPackageUpdates.get(identifier)
if (existingEntry) {
// already queued, add to the batch
existingEntry.packageIds.push(pkg._id)
const bucketAction = (await BucketAdLibActions.findOneAsync(
{ _id: pkg.pieceId, bucketId: pkg.bucketId },
{
projection: { externalId: 1 },
}
)) as Pick<BucketAdLibAction, 'externalId'>

if (bucketAction) {
onUpdatedPackageInfoForBucketItemDebounce(pkg, bucketAction.externalId)
} else {
pendingBucketItemPackageUpdates.set(identifier, {
bucketId: pkg.bucketId,
pieceId: pkg.pieceId,
packageIds: [pkg._id],
})
logger.info(`onUpdatedPackageInfo: Received update for missing BucketAdLibAction: ${pkg.pieceId}`)
}

lazyIgnore(
`onUpdatedPackageInfoForBucket_${identifier}`,
() => {
const updateInfo = pendingBucketItemPackageUpdates.get(identifier)
if (updateInfo) {
pendingBucketItemPackageUpdates.delete(identifier)
onUpdatedPackageInfoForBucketItem(updateInfo).catch((e) => {
logger.error(
`Updating ExpectedPackages for Bucket "${updateInfo.bucketId}" Item "${updateInfo.pieceId}" failed: ${e}`
)
})
}
},
1000
)
break
}
case ExpectedPackageDBType.STUDIO_BASELINE_OBJECTS:
// Ignore, as we can't handle that for now
onUpdatedPackageInfoForStudioBaselineDebounce(pkg)
break
default:
assertNever(pkg)
Expand Down Expand Up @@ -128,51 +130,38 @@ async function onUpdatedPackageInfoForRundown(
})
}

interface PendingBucketItemPackageUpdateInfoBase {
bucketId: BucketId
pieceId: BucketAdLibId | BucketAdLibActionId
packageIds: ExpectedPackageId[]
function onUpdatedPackageInfoForBucketItemDebounce(
pkg: ExpectedPackageDBFromBucketAdLib | ExpectedPackageDBFromBucketAdLibAction,
externalId: string
) {
lazyIgnore(
`onUpdatedPackageInfoForBucket_${pkg.studioId}_${pkg.bucketId}_${externalId}`,
() => {
runIngestOperation(pkg.studioId, IngestJobs.BucketItemRegenerate, {
bucketId: pkg.bucketId,
externalId: externalId,
}).catch((err) => {
logger.error(
`Updating ExpectedPackages for Bucket "${pkg.bucketId}" Item "${externalId}" failed: ${err}`
)
})
},
1000
)
}

// interface PendingBucketAdLibPiecePackageUpdateInfo extends PendingBucketItemPackageUpdateInfoBase {
// fromPieceType: ExpectedPackageDBType.BUCKET_ADLIB
// /** The Bucket adlib this package belongs to */
// pieceId: BucketAdLibId
// }
// interface PendingBucketAdLibActionPackageUpdateInfo extends PendingBucketItemPackageUpdateInfoBase {
// fromPieceType: ExpectedPackageDBType.BUCKET_ADLIB_ACTION
// /** The Bucket adlib-action this package belongs to */
// pieceId: BucketAdLibActionId
// }

type SomePendingBucketItemPackageUpdateInfo = PendingBucketItemPackageUpdateInfoBase
// | PendingBucketAdLibPiecePackageUpdateInfo
// | PendingBucketAdLibActionPackageUpdateInfo

const pendingBucketItemPackageUpdates = new Map<string, SomePendingBucketItemPackageUpdateInfo>()

async function onUpdatedPackageInfoForBucketItem(info: SomePendingBucketItemPackageUpdateInfo): Promise<void> {
if (info.packageIds.length === 0) {
return
}

const tmpBucket = (await Buckets.findOneAsync(info.bucketId, {
projection: {
studioId: 1,
function onUpdatedPackageInfoForStudioBaselineDebounce(pkg: ExpectedPackageDBFromStudioBaselineObjects) {
lazyIgnore(
`onUpdatedPackageInfoForStudioBaseline_${pkg.studioId}`,
() => {
QueueStudioJob(StudioJobs.UpdateStudioBaseline, pkg.studioId, undefined)
.then(async (job) => {
await job.complete
})
.catch((err) => {
logger.error(`Updating ExpectedPackages for StudioBaseline "${pkg.studioId}" failed: ${err}`)
})
},
})) as Pick<Bucket, 'studioId'> | undefined
if (!tmpBucket) {
logger.error(
`onUpdatedPackageInfoForBucketItem: Missing Bucket "${info.bucketId}" for packages "${info.packageIds.join(
', '
)}"`
)
return
}

await runIngestOperation(tmpBucket.studioId, IngestJobs.PackageInfosUpdatedBucketItem, {
bucketId: info.bucketId,
pieceId: info.pieceId,
packageIds: info.packageIds,
})
1000
)
}
2 changes: 2 additions & 0 deletions packages/corelib/src/dataModel/BucketAdLibAction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BucketAdLibActionId, BucketId, StudioId, ShowStyleVariantId, ShowStyleBaseId } from './Ids'
import { RundownImportVersions } from './Rundown'
import { AdLibActionCommon } from './AdlibAction'
import { BucketAdLibIngestInfo } from './BucketAdLibPiece'

export interface BucketAdLibAction extends Omit<AdLibActionCommon, 'rundownId'> {
_id: BucketAdLibActionId
Expand All @@ -18,6 +19,7 @@ export interface BucketAdLibAction extends Omit<AdLibActionCommon, 'rundownId'>
/** if showStyleVariantId is null, the adlibAction can be used with any variant */
showStyleVariantId: ShowStyleVariantId | null
importVersions: RundownImportVersions // TODO - is this good?
ingestInfo: BucketAdLibIngestInfo | undefined

/** The following extended interface allows assigning namespace information to the actions as they are stored in the
* database after being emitted from the blueprints
Expand Down
8 changes: 7 additions & 1 deletion packages/corelib/src/dataModel/BucketAdLibPiece.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { IBlueprintAdLibPiece, SomeContent } from '@sofie-automation/blueprints-integration'
import { IBlueprintAdLibPiece, IngestAdlib, SomeContent } from '@sofie-automation/blueprints-integration'
import { BucketAdLibId, BucketId, StudioId, ShowStyleVariantId, ShowStyleBaseId } from './Ids'
import { PieceTimelineObjectsBlob } from './Piece'
import { RundownImportVersions } from './Rundown'

export interface BucketAdLibIngestInfo {
limitToShowStyleVariantIds: ShowStyleVariantId[] | undefined
payload: IngestAdlib
}

export interface BucketAdLib extends Omit<IBlueprintAdLibPiece, 'content'> {
_id: BucketAdLibId
bucketId: BucketId
Expand All @@ -20,6 +25,7 @@ export interface BucketAdLib extends Omit<IBlueprintAdLibPiece, 'content'> {
showStyleVariantId: ShowStyleVariantId | null

importVersions: RundownImportVersions // TODO - is this good?
ingestInfo: BucketAdLibIngestInfo | undefined

/** Stringified timelineObjects */
timelineObjectsString: PieceTimelineObjectsBlob
Expand Down
14 changes: 6 additions & 8 deletions packages/corelib/src/worker/ingest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
AdLibActionId,
BucketAdLibActionId,
BucketAdLibId,
BucketId,
ExpectedPackageId,
PeripheralDeviceId,
Expand Down Expand Up @@ -124,6 +123,7 @@ export enum IngestJobs {

// For now these are in this queue, but if this gets split up to be per rundown, then a single bucket queue will be needed
BucketItemImport = 'bucketItemImport',
BucketItemRegenerate = 'bucketItemRegenerate',
BucketActionRegenerateExpectedPackages = 'bucketActionRegenerateExpectedPackages',
BucketActionModify = 'bucketActionModify',
BucketPieceModify = 'bucketPieceModify',
Expand Down Expand Up @@ -219,12 +219,6 @@ export interface PackageInfosUpdatedRundownProps extends IngestPropsBase {
packageIds: ExpectedPackageId[]
}

export interface PackageInfosUpdatedBucketItemProps {
bucketId: BucketId
pieceId: BucketAdLibId | BucketAdLibActionId
packageIds: ExpectedPackageId[]
}

export interface UserRundownPropsBase {
rundownId: RundownId
}
Expand All @@ -239,6 +233,10 @@ export interface BucketItemImportProps {
showStyleVariantIds?: ShowStyleVariantId[]
payload: IngestAdlib
}
export interface BucketItemRegenerateProps {
bucketId: BucketId
externalId: string
}
export interface BucketActionRegenerateExpectedPackagesProps {
actionId: BucketAdLibActionId
}
Expand Down Expand Up @@ -290,12 +288,12 @@ export type IngestJobFunc = {

[IngestJobs.ExpectedPackagesRegenerate]: (data: ExpectedPackagesRegenerateProps) => void
[IngestJobs.PackageInfosUpdatedRundown]: (data: PackageInfosUpdatedRundownProps) => void
[IngestJobs.PackageInfosUpdatedBucketItem]: (data: PackageInfosUpdatedBucketItemProps) => void

[IngestJobs.UserRemoveRundown]: (data: UserRemoveRundownProps) => void
[IngestJobs.UserUnsyncRundown]: (data: UserUnsyncRundownProps) => void

[IngestJobs.BucketItemImport]: (data: BucketItemImportProps) => void
[IngestJobs.BucketItemRegenerate]: (data: BucketItemRegenerateProps) => void
[IngestJobs.BucketActionModify]: (data: BucketActionModifyProps) => void
[IngestJobs.BucketPieceModify]: (data: BucketPieceModifyProps) => void
[IngestJobs.BucketActionRegenerateExpectedPackages]: (data: BucketActionRegenerateExpectedPackagesProps) => void
Expand Down
20 changes: 13 additions & 7 deletions packages/job-worker/src/blueprints/postProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { RundownBaselineAdLibAction } from '@sofie-automation/corelib/dist/dataM
import { ArrayElement, getHash, literal, omit } from '@sofie-automation/corelib/dist/lib'
import { BucketAdLibAction } from '@sofie-automation/corelib/dist/dataModel/BucketAdLibAction'
import { RundownImportVersions } from '@sofie-automation/corelib/dist/dataModel/Rundown'
import { BucketAdLib } from '@sofie-automation/corelib/dist/dataModel/BucketAdLibPiece'
import { BucketAdLib, BucketAdLibIngestInfo } from '@sofie-automation/corelib/dist/dataModel/BucketAdLibPiece'
import {
interpollateTranslation,
wrapTranslatableMessageFromBlueprints,
Expand Down Expand Up @@ -393,25 +393,28 @@ export function postProcessBucketAdLib(
context: JobContext,
showStyleCompound: ReadonlyDeep<ProcessedShowStyleCompound>,
itemOrig: IBlueprintAdLibPiece,
externalId: string,
ingestInfo: BucketAdLibIngestInfo,
blueprintId: BlueprintId,
bucketId: BucketId,
rank: number | undefined,
importVersions: RundownImportVersions
): BucketAdLib {
const id: PieceId = protectString(
getHash(`${showStyleCompound.showStyleVariantId}_${context.studioId}_${bucketId}_bucket_adlib_${externalId}`)
getHash(
`${showStyleCompound.showStyleVariantId}_${context.studioId}_${bucketId}_bucket_adlib_${ingestInfo.payload.externalId}`
)
)
const piece: BucketAdLib = {
...itemOrig,
content: omit(itemOrig.content, 'timelineObjects'),
_id: id,
externalId,
externalId: ingestInfo.payload.externalId,
studioId: context.studioId,
showStyleBaseId: showStyleCompound._id,
showStyleVariantId: showStyleCompound.showStyleVariantId,
bucketId,
importVersions,
ingestInfo,
_rank: rank || itemOrig._rank,
timelineObjectsString: EmptyPieceTimelineObjectsBlob,
}
Expand Down Expand Up @@ -439,24 +442,27 @@ export function postProcessBucketAction(
context: JobContext,
showStyleCompound: ReadonlyDeep<ProcessedShowStyleCompound>,
itemOrig: IBlueprintActionManifest,
externalId: string,
ingestInfo: BucketAdLibIngestInfo,
blueprintId: BlueprintId,
bucketId: BucketId,
rank: number | undefined,
importVersions: RundownImportVersions
): BucketAdLibAction {
const id: AdLibActionId = protectString(
getHash(`${showStyleCompound.showStyleVariantId}_${context.studioId}_${bucketId}_bucket_adlib_${externalId}`)
getHash(
`${showStyleCompound.showStyleVariantId}_${context.studioId}_${bucketId}_bucket_adlib_${ingestInfo.payload.externalId}`
)
)
const action: BucketAdLibAction = {
...omit(itemOrig, 'partId'),
_id: id,
externalId,
externalId: ingestInfo.payload.externalId,
studioId: context.studioId,
showStyleBaseId: showStyleCompound._id,
showStyleVariantId: itemOrig.allVariants ? null : showStyleCompound.showStyleVariantId,
bucketId,
importVersions,
ingestInfo,
...processAdLibActionITranslatableMessages(itemOrig, blueprintId, rank),
}

Expand Down
Loading

0 comments on commit 4c9834a

Please sign in to comment.