Skip to content

Commit 82b98c6

Browse files
committed
wip
1 parent 62d693b commit 82b98c6

File tree

8 files changed

+223
-241
lines changed

8 files changed

+223
-241
lines changed

meteor/server/api/deviceTriggers/triggersContext.ts

Lines changed: 69 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,25 @@ import { PartId, StudioId } from '@sofie-automation/corelib/dist/dataModel/Ids'
1414
import { DummyReactiveVar } from '@sofie-automation/meteor-lib/dist/triggers/reactive-var'
1515
import { ReactivePlaylistActionContext } from '@sofie-automation/meteor-lib/dist/triggers/actionFactory'
1616
import { MongoQuery } from '@sofie-automation/corelib/dist/mongo'
17-
import { CollectionName } from '@sofie-automation/corelib/dist/dataModel/Collections'
18-
import { AdLibAction } from '@sofie-automation/corelib/dist/dataModel/AdlibAction'
19-
import { AdLibPiece } from '@sofie-automation/corelib/dist/dataModel/AdLibPiece'
20-
import { PartInstance } from '@sofie-automation/meteor-lib/dist/collections/PartInstances'
17+
import { DBRundownPlaylist, SelectedPartInstance } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
18+
import {
19+
AdLibActions,
20+
AdLibPieces,
21+
PartInstances,
22+
Parts,
23+
RundownBaselineAdLibActions,
24+
RundownBaselineAdLibPieces,
25+
RundownPlaylists,
26+
Rundowns,
27+
Segments,
28+
} from '../../collections'
2129
import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part'
22-
import { RundownBaselineAdLibAction } from '@sofie-automation/corelib/dist/dataModel/RundownBaselineAdLibAction'
23-
import { RundownBaselineAdLibItem } from '@sofie-automation/corelib/dist/dataModel/RundownBaselineAdLibPiece'
24-
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
25-
import { DBRundown } from '@sofie-automation/corelib/dist/dataModel/Rundown'
26-
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
27-
import { createSyncReadOnlyMongoCollection } from './triggersContextCollection'
30+
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
2831

2932
export function hashSingleUseToken(token: string): string {
3033
return getHash(SINGLE_USE_TOKEN_SALT + token)
3134
}
3235

33-
/**
34-
* Some synchronous read-only collections to satisfy the TriggersContext interface
35-
*/
36-
const AdLibActions = createSyncReadOnlyMongoCollection<AdLibAction>(CollectionName.AdLibActions)
37-
const AdLibPieces = createSyncReadOnlyMongoCollection<AdLibPiece>(CollectionName.AdLibPieces)
38-
const PartInstances = createSyncReadOnlyMongoCollection<PartInstance>(CollectionName.PartInstances)
39-
const Parts = createSyncReadOnlyMongoCollection<DBPart>(CollectionName.Parts)
40-
const RundownBaselineAdLibActions = createSyncReadOnlyMongoCollection<RundownBaselineAdLibAction>(
41-
CollectionName.RundownBaselineAdLibActions
42-
)
43-
const RundownBaselineAdLibPieces = createSyncReadOnlyMongoCollection<RundownBaselineAdLibItem>(
44-
CollectionName.RundownBaselineAdLibPieces
45-
)
46-
const RundownPlaylists = createSyncReadOnlyMongoCollection<DBRundownPlaylist>(CollectionName.RundownPlaylists)
47-
const Rundowns = createSyncReadOnlyMongoCollection<DBRundown>(CollectionName.Rundowns)
48-
const Segments = createSyncReadOnlyMongoCollection<DBSegment>(CollectionName.Segments)
49-
5036
export const MeteorTriggersContext: TriggersContext = {
5137
MeteorCall,
5238

@@ -83,71 +69,86 @@ export const MeteorTriggersContext: TriggersContext = {
8369

8470
nonreactiveTracker: Tracker.nonreactive,
8571

86-
memoizedIsolatedAutorun: <T extends (...args: any) => any>(
87-
fnc: T,
72+
memoizedIsolatedAutorun: async <TArgs extends any[], TRes>(
73+
fnc: (...args: TArgs) => Promise<TRes>,
8874
_functionName: string,
89-
...params: Parameters<T>
90-
): ReturnType<T> => {
91-
return fnc(...(params as any))
75+
...params: TArgs
76+
): Promise<TRes> => {
77+
return fnc(...params)
9278
},
9379

9480
createContextForRundownPlaylistChain,
9581
}
9682

97-
function createContextForRundownPlaylistChain(
83+
async function createContextForRundownPlaylistChain(
9884
studioId: StudioId,
9985
filterChain: IBaseFilterLink[]
100-
): ReactivePlaylistActionContext | undefined {
101-
const playlist = rundownPlaylistFilter(
86+
): Promise<ReactivePlaylistActionContext | undefined> {
87+
const playlist = await rundownPlaylistFilter(
10288
studioId,
10389
filterChain.filter((link) => link.object === 'rundownPlaylist') as IRundownPlaylistFilterLink[]
10490
)
10591

10692
if (!playlist) return undefined
10793

108-
let currentPartId: PartId | null = null,
109-
nextPartId: PartId | null = null,
110-
currentPartInstance: PartInstance | null = null,
111-
currentSegmentPartIds: PartId[] = [],
112-
nextSegmentPartIds: PartId[] = []
113-
114-
if (playlist.currentPartInfo) {
115-
currentPartInstance = PartInstances.findOne(playlist.currentPartInfo.partInstanceId) ?? null
116-
const currentPart = currentPartInstance?.part ?? null
117-
if (currentPart) {
118-
currentPartId = currentPart._id
119-
currentSegmentPartIds = Parts.find({
120-
segmentId: currentPart.segmentId,
121-
}).map((part) => part._id)
122-
}
123-
}
124-
if (playlist.nextPartInfo) {
125-
const nextPart = PartInstances.findOne(playlist.nextPartInfo.partInstanceId)?.part ?? null
126-
if (nextPart) {
127-
nextPartId = nextPart._id
128-
nextSegmentPartIds = Parts.find({
129-
segmentId: nextPart.segmentId,
130-
}).map((part) => part._id)
131-
}
132-
}
94+
const [currentPartInfo, nextPartInfo] = await Promise.all([
95+
fetchInfoForSelectedPart(playlist.currentPartInfo),
96+
fetchInfoForSelectedPart(playlist.nextPartInfo),
97+
])
13398

13499
return {
135100
studioId: new DummyReactiveVar(studioId),
136101
rundownPlaylistId: new DummyReactiveVar(playlist?._id),
137102
rundownPlaylist: new DummyReactiveVar(playlist),
138-
currentRundownId: new DummyReactiveVar(currentPartInstance?.rundownId ?? playlist.rundownIdsInOrder[0] ?? null),
139-
currentPartId: new DummyReactiveVar(currentPartId),
140-
currentSegmentPartIds: new DummyReactiveVar(currentSegmentPartIds),
141-
nextPartId: new DummyReactiveVar(nextPartId),
142-
nextSegmentPartIds: new DummyReactiveVar(nextSegmentPartIds),
103+
currentRundownId: new DummyReactiveVar(
104+
playlist.currentPartInfo?.rundownId ?? playlist.rundownIdsInOrder[0] ?? null
105+
),
106+
currentPartId: new DummyReactiveVar(currentPartInfo?.partId ?? null),
107+
currentSegmentPartIds: new DummyReactiveVar(currentPartInfo?.segmentPartIds ?? []),
108+
nextPartId: new DummyReactiveVar(nextPartInfo?.partId ?? null),
109+
nextSegmentPartIds: new DummyReactiveVar(nextPartInfo?.segmentPartIds ?? []),
143110
currentPartInstanceId: new DummyReactiveVar(playlist.currentPartInfo?.partInstanceId ?? null),
144111
}
145112
}
146113

147-
function rundownPlaylistFilter(
114+
async function fetchInfoForSelectedPart(partInfo: SelectedPartInstance | null): Promise<{
115+
partId: PartId
116+
segmentPartIds: PartId[]
117+
} | null> {
118+
if (!partInfo) return null
119+
120+
const partInstance = (await PartInstances.findOneAsync(partInfo.partInstanceId, {
121+
projection: {
122+
// @ts-expect-error deep property
123+
'part._id': 1,
124+
segmentId: 1,
125+
},
126+
})) as (Pick<DBPartInstance, 'segmentId'> & { part: Pick<DBPart, '_id'> }) | null
127+
128+
if (!partInstance) return null
129+
130+
const partId = partInstance.part._id
131+
const segmentPartIds = await Parts.findFetchAsync(
132+
{
133+
segmentId: partInstance.segmentId,
134+
},
135+
{
136+
projection: {
137+
_id: 1,
138+
},
139+
}
140+
).then((parts) => parts.map((part) => part._id))
141+
142+
return {
143+
partId,
144+
segmentPartIds,
145+
}
146+
}
147+
148+
async function rundownPlaylistFilter(
148149
studioId: StudioId,
149150
filterChain: IRundownPlaylistFilterLink[]
150-
): DBRundownPlaylist | undefined {
151+
): Promise<DBRundownPlaylist | undefined> {
151152
const selector: MongoQuery<DBRundownPlaylist> = {
152153
$and: [
153154
{
@@ -181,5 +182,5 @@ function rundownPlaylistFilter(
181182
}
182183
})
183184

184-
return RundownPlaylists.findOne(selector)
185+
return RundownPlaylists.findOneAsync(selector)
185186
}

meteor/server/api/deviceTriggers/triggersContextCollection.ts

Lines changed: 0 additions & 76 deletions
This file was deleted.

packages/meteor-lib/src/collections/lib.ts

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@ import type { Collection as RawCollection, Db as RawDb } from 'mongodb'
22
import { MongoFieldSpecifier, MongoModifier, MongoQuery, SortSpecifier } from '@sofie-automation/corelib/dist/mongo'
33
import { ProtectedString } from '@sofie-automation/corelib/dist/protectedString'
44

5+
export interface MongoAsyncReadOnlyCollection<DBInterface extends { _id: ProtectedString<any> }> {
6+
/**
7+
* Find and return multiple documents
8+
* @param selector A query describing the documents to find
9+
* @param options Options for the operation
10+
*/
11+
findFetchAsync(selector: MongoQuery<DBInterface>, options?: FindOptions<DBInterface>): Promise<Array<DBInterface>>
12+
13+
/**
14+
* Finds the first document that matches the selector, as ordered by sort and skip options. Returns `undefined` if no matching document is found.
15+
* @param selector A query describing the documents to find
16+
*/
17+
findOneAsync(
18+
selector: MongoQuery<DBInterface> | DBInterface['_id'],
19+
options?: FindOneOptions<DBInterface>
20+
): Promise<DBInterface | undefined>
21+
}
22+
523
export interface MongoReadOnlyCollection<DBInterface extends { _id: ProtectedString<any> }> {
624
/**
725
* Find the documents in a collection that match the selector.
@@ -109,32 +127,17 @@ export interface MongoLiveQueryHandle {
109127
}
110128

111129
// Note: This is a subset of the Meteor Mongo.Cursor type
112-
export interface MongoCursor<DBInterface extends { _id: ProtectedString<any> }> {
113-
/**
114-
* Returns the number of documents that match a query.
115-
* @param applySkipLimit If set to `false`, the value returned will reflect the total number of matching documents, ignoring any value supplied for limit. (Default: true)
116-
*/
117-
count(applySkipLimit?: boolean): number
130+
131+
export interface MongoAsyncCursor<DBInterface extends { _id: ProtectedString<any> }> {
118132
/**
119133
* Returns the number of documents that match a query.
120134
* @param applySkipLimit If set to `false`, the value returned will reflect the total number of matching documents, ignoring any value supplied for limit. (Default: true)
121135
*/
122136
countAsync(applySkipLimit?: boolean): Promise<number>
123-
/**
124-
* Return all matching documents as an Array.
125-
*/
126-
fetch(): Array<DBInterface>
127137
/**
128138
* Return all matching documents as an Array.
129139
*/
130140
fetchAsync(): Promise<Array<DBInterface>>
131-
/**
132-
* Call `callback` once for each matching document, sequentially and
133-
* synchronously.
134-
* @param callback Function to call. It will be called with three arguments: the document, a 0-based index, and <em>cursor</em> itself.
135-
* @param thisArg An object which will be the value of `this` inside `callback`.
136-
*/
137-
forEach(callback: (doc: DBInterface, index: number, cursor: MongoCursor<DBInterface>) => void, thisArg?: any): void
138141
/**
139142
* Call `callback` once for each matching document, sequentially and
140143
* synchronously.
@@ -150,19 +153,54 @@ export interface MongoCursor<DBInterface extends { _id: ProtectedString<any> }>
150153
* @param callback Function to call. It will be called with three arguments: the document, a 0-based index, and <em>cursor</em> itself.
151154
* @param thisArg An object which will be the value of `this` inside `callback`.
152155
*/
153-
map<M>(callback: (doc: DBInterface, index: number, cursor: MongoCursor<DBInterface>) => M, thisArg?: any): Array<M>
156+
mapAsync<M>(
157+
callback: (doc: DBInterface, index: number, cursor: MongoCursor<DBInterface>) => M,
158+
thisArg?: any
159+
): Promise<Array<M>>
160+
161+
[Symbol.asyncIterator](): AsyncIterator<DBInterface, never, never>
162+
163+
/**
164+
* Watch a query. Receive callbacks as the result set changes.
165+
* @param callbacks Functions to call to deliver the result set as it changes
166+
*/
167+
observeAsync(callbacks: ObserveCallbacks<DBInterface>): Promise<MongoLiveQueryHandle>
168+
/**
169+
* Watch a query. Receive callbacks as the result set changes. Only the differences between the old and new documents are passed to the callbacks.
170+
* @param callbacks Functions to call to deliver the result set as it changes
171+
* @param options { nonMutatingCallbacks: boolean }
172+
*/
173+
observeChangesAsync(
174+
callbacks: ObserveChangesCallbacks<DBInterface>,
175+
options?: { nonMutatingCallbacks?: boolean | undefined }
176+
): Promise<MongoLiveQueryHandle>
177+
}
178+
179+
export interface MongoCursor<DBInterface extends { _id: ProtectedString<any> }> extends MongoAsyncCursor<DBInterface> {
180+
/**
181+
* Returns the number of documents that match a query.
182+
* @param applySkipLimit If set to `false`, the value returned will reflect the total number of matching documents, ignoring any value supplied for limit. (Default: true)
183+
*/
184+
count(applySkipLimit?: boolean): number
185+
/**
186+
* Return all matching documents as an Array.
187+
*/
188+
fetch(): Array<DBInterface>
189+
/**
190+
* Call `callback` once for each matching document, sequentially and
191+
* synchronously.
192+
* @param callback Function to call. It will be called with three arguments: the document, a 0-based index, and <em>cursor</em> itself.
193+
* @param thisArg An object which will be the value of `this` inside `callback`.
194+
*/
195+
forEach(callback: (doc: DBInterface, index: number, cursor: MongoCursor<DBInterface>) => void, thisArg?: any): void
154196
/**
155197
* Map callback over all matching documents. Returns an Array.
156198
* @param callback Function to call. It will be called with three arguments: the document, a 0-based index, and <em>cursor</em> itself.
157199
* @param thisArg An object which will be the value of `this` inside `callback`.
158200
*/
159-
mapAsync<M>(
160-
callback: (doc: DBInterface, index: number, cursor: MongoCursor<DBInterface>) => M,
161-
thisArg?: any
162-
): Promise<Array<M>>
201+
map<M>(callback: (doc: DBInterface, index: number, cursor: MongoCursor<DBInterface>) => M, thisArg?: any): Array<M>
163202

164203
[Symbol.iterator](): Iterator<DBInterface, never, never>
165-
[Symbol.asyncIterator](): AsyncIterator<DBInterface, never, never>
166204

167205
/**
168206
* Watch a query. Receive callbacks as the result set changes.

0 commit comments

Comments
 (0)