Skip to content
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
1 change: 0 additions & 1 deletion meteor/__mocks__/helpers/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const METHOD_NAMES = [
'findOne',
'insert',
'rawCollection',
'rawDatabase',
'remove',
'update',
'upsert',
Expand Down
3 changes: 0 additions & 3 deletions meteor/__mocks__/mongo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,6 @@ export namespace MongoMock {
// todo
}

rawDatabase(): any {
throw new Error('Not implemented')
}
rawCollection(): any {
return {
bulkWrite: async (updates: AnyBulkWriteOperation<any>[], _options: unknown) => {
Expand Down
2 changes: 1 addition & 1 deletion meteor/server/api/blueprints/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ async function innerUploadBlueprint(
parseVersion(blueprintManifest.integrationVersion)
parseVersion(blueprintManifest.TSRVersion)

await Blueprints.upsertAsync(newBlueprint._id, newBlueprint)
await Blueprints.replaceAsync(newBlueprint)

// check for translations on the manifest and store them if they exist
if (
Expand Down
57 changes: 21 additions & 36 deletions meteor/server/api/integration/expectedPackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@ import { MethodContext } from '../methodContext'
import { checkAccessAndGetPeripheralDevice } from '../../security/check'
import { ExpectedPackageStatusAPI, PackageInfo } from '@sofie-automation/blueprints-integration'
import { ExpectedPackageWorkStatus } from '@sofie-automation/corelib/dist/dataModel/ExpectedPackageWorkStatuses'
import { assertNever, literal } from '@sofie-automation/corelib/dist/lib'
import { assertNever } from '@sofie-automation/corelib/dist/lib'
import { protectString } from '@sofie-automation/corelib/dist/protectedString'
import { getCurrentTime } from '../../lib/lib'
import {
getPackageContainerPackageId,
PackageContainerPackageStatusDB,
} from '@sofie-automation/corelib/dist/dataModel/PackageContainerPackageStatus'
import { getPackageContainerPackageId } from '@sofie-automation/corelib/dist/dataModel/PackageContainerPackageStatus'
import { getPackageInfoId, PackageInfoDB } from '@sofie-automation/corelib/dist/dataModel/PackageInfos'
import type { AnyBulkWriteOperation } from 'mongodb'
import type { MongoBulkWriteOperation } from '@sofie-automation/corelib/dist/mongo'
import { onUpdatedPackageInfo } from '../ingest/packageInfo'
import {
getPackageContainerId,
PackageContainerStatusDB,
} from '@sofie-automation/corelib/dist/dataModel/PackageContainerStatus'
import { getPackageContainerId } from '@sofie-automation/corelib/dist/dataModel/PackageContainerStatus'
import {
ExpectedPackageId,
ExpectedPackageWorkStatusId,
Expand Down Expand Up @@ -64,7 +58,7 @@ export namespace PackageManagerIntegration {
if (!peripheralDevice.studioAndConfigId)
throw new Meteor.Error(400, 'Device "' + peripheralDevice._id + '" has no studio')

const bulkChanges: AnyBulkWriteOperation<ExpectedPackageWorkStatus>[] = []
const bulkChanges: MongoBulkWriteOperation<ExpectedPackageWorkStatus>[] = []
const removedIds: ExpectedPackageWorkStatusId[] = []

const ps: Promise<void>[] = []
Expand Down Expand Up @@ -220,16 +214,14 @@ export namespace PackageManagerIntegration {
// The PackageContainerStatus doesn't exist
// Create it on the fly:

await PackageContainerPackageStatuses.upsertAsync(id, {
$set: literal<PackageContainerPackageStatusDB>({
_id: id,
studioId: studioId,
containerId: change.containerId,
deviceId: peripheralDevice._id,
packageId: protectString<ExpectedPackageId>(change.packageId),
status: change.status,
modified: getCurrentTime(),
}),
await PackageContainerPackageStatuses.replaceAsync({
_id: id,
studioId: studioId,
containerId: change.containerId,
deviceId: peripheralDevice._id,
packageId: protectString<ExpectedPackageId>(change.packageId),
status: change.status,
modified: getCurrentTime(),
})
}
})
Expand Down Expand Up @@ -308,15 +300,13 @@ export namespace PackageManagerIntegration {
// The PackageContainerStatus doesn't exist
// Create it on the fly:

await PackageContainerStatuses.upsertAsync(id, {
$set: literal<PackageContainerStatusDB>({
_id: id,
studioId: studioId,
containerId: change.containerId,
deviceId: peripheralDevice._id,
status: change.status,
modified: getCurrentTime(),
}),
await PackageContainerStatuses.replaceAsync({
_id: id,
studioId: studioId,
containerId: change.containerId,
deviceId: peripheralDevice._id,
status: change.status,
modified: getCurrentTime(),
})
}
})
Expand Down Expand Up @@ -416,12 +406,7 @@ export namespace PackageManagerIntegration {
type: type,
payload: payload,
}
await PackageInfos.upsertAsync(id, {
$set: doc,
$unset: {
removeTime: 1,
},
})
await PackageInfos.replaceAsync(doc)

await onUpdatedPackageInfo(packageId, doc)
}
Expand Down
10 changes: 5 additions & 5 deletions meteor/server/api/integration/media-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export namespace MediaScannerIntegration {
// logger.debug('updateMediaObject')
const peripheralDevice = await checkAccessAndGetPeripheralDevice(deviceId, deviceToken, context)
const studioId = await getStudioIdFromDevice(peripheralDevice)
if (!studioId)
throw new Meteor.Error(400, 'updateMediaObject: Device "' + peripheralDevice._id + '" has no studio')

const _id: MediaObjId = protectString(collectionId + '_' + objId)
if (doc === null) {
Expand All @@ -63,16 +65,14 @@ export namespace MediaScannerIntegration {
if (doc.mediaId !== doc.mediaId.toUpperCase())
throw new Meteor.Error(400, 'mediaId must only use uppercase characters')

const doc2 = {
// logger.debug(doc2)
await MediaObjects.replaceAsync({
...doc,
studioId: studioId,
collectionId: collectionId,
objId: objId,
_id: _id,
}

// logger.debug(doc2)
await MediaObjects.upsertAsync(_id, { $set: doc2 })
})
} else {
throw new Meteor.Error(400, 'missing doc argument')
}
Expand Down
6 changes: 3 additions & 3 deletions meteor/server/api/rest/v1/showstyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class ShowStylesServerAPI implements ShowStylesRestAPI {
}
}

await ShowStyleBases.upsertAsync(showStyleBaseId, showStyle)
await ShowStyleBases.replaceAsync(showStyle)

// wait for the upsert to complete before validation and upgrade read from the showStyleBases collection
await new Promise<void>((resolve) => setTimeout(() => resolve(), 200))
Expand Down Expand Up @@ -169,7 +169,7 @@ class ShowStylesServerAPI implements ShowStylesRestAPI {
const showStyle = await showStyleBaseFrom(apiShowStyleBase, showStyleBaseId)
if (!showStyle) throw new Meteor.Error(400, `Invalid ShowStyleBase`)

await ShowStyleBases.upsertAsync(showStyleBaseId, showStyle)
await ShowStyleBases.replaceAsync(showStyle)

// wait for the upsert to complete before validation and upgrade read from the showStyleBases collection
await new Promise<void>((resolve) => setTimeout(() => resolve(), 200))
Expand Down Expand Up @@ -298,7 +298,7 @@ class ShowStylesServerAPI implements ShowStylesRestAPI {
}
}

await ShowStyleVariants.upsertAsync(showStyleVariantId, showStyle)
await ShowStyleVariants.replaceAsync(showStyle)
return ClientAPI.responseSuccess(undefined, 200)
}

Expand Down
4 changes: 2 additions & 2 deletions meteor/server/api/rest/v1/studios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class StudiosServerAPI implements StudiosRestAPI {
}
}

await Studios.upsertAsync(studioId, newStudio)
await Studios.replaceAsync(newStudio)

const validation = await validateConfigForStudio(studioId)
checkValidation(`addOrUpdateStudio ${studioId}`, validation.messages)
Expand Down Expand Up @@ -148,7 +148,7 @@ class StudiosServerAPI implements StudiosRestAPI {
const newStudio = await studioFrom(apiStudio, studioId)
if (!newStudio) throw new Meteor.Error(400, `Invalid Studio`)

await Studios.upsertAsync(studioId, newStudio)
await Studios.replaceAsync(newStudio)

const validation = await validateConfigForStudio(studioId)
checkValidation(`updateStudioConfig ${studioId}`, validation.messages)
Expand Down
3 changes: 2 additions & 1 deletion meteor/server/api/rundownLayouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ shelfLayoutsRouter.post(
check(layout.name, String)
check(layout.type, String)

layout._id = layout._id || getRandomId()
layout.showStyleBaseId = showStyleBase._id

await RundownLayouts.upsertAsync(layout._id, layout)
await RundownLayouts.replaceAsync(layout)

ctx.response.status = 200
ctx.body = ''
Expand Down
20 changes: 8 additions & 12 deletions meteor/server/api/translationsBundles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,15 @@ export async function upsertBundles(
// originating blueprint and language
const _id = createBundleId(originId, language)

await TranslationsBundleCollection.upsertAsync(
await TranslationsBundleCollection.replaceAsync({
_id,
{
_id,
originId,
type,
namespace: unprotectString(originId),
language,
data: fromI18NextData(data),
hash: getHash(JSON.stringify(data)),
},
{ multi: false }
)
originId,
type,
namespace: unprotectString(originId),
language,
data: fromI18NextData(data),
hash: getHash(JSON.stringify(data)),
})
}
}

Expand Down
10 changes: 9 additions & 1 deletion meteor/server/api/triggeredActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,15 @@ actionTriggersRouter.post(

// TODO - should we clear `blueprintUniqueId`, to avoid blueprints getting them confused with data they own?

await TriggeredActions.upsertManyAsync(triggeredActions)
await TriggeredActions.bulkWriteAsync(
triggeredActions.map((triggeredActionsObj) => ({
replaceOne: {
filter: { _id: triggeredActionsObj._id },
replacement: triggeredActionsObj,
upsert: true,
},
}))
)

ctx.response.status = 200
ctx.body = ''
Expand Down
38 changes: 13 additions & 25 deletions meteor/server/collections/collection.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { FindOptions, MongoModifier, MongoQuery, ObserveChangesOptions } from '@sofie-automation/corelib/dist/mongo'
import {
FindOptions,
MongoBulkWriteOperation,
MongoModifier,
MongoQuery,
ObserveChangesOptions,
} from '@sofie-automation/corelib/dist/mongo'
import { ProtectedString } from '@sofie-automation/corelib/dist/protectedString'
import { Meteor } from 'meteor/meteor'
import { Mongo } from 'meteor/mongo'
import { NpmModuleMongodb } from 'meteor/npm-mongo'
import { PromisifyCallbacks } from '@sofie-automation/shared-lib/dist/lib/types'
import type { AnyBulkWriteOperation, Collection as RawCollection } from 'mongodb'
import type { Collection as RawCollection } from 'mongodb'
import { CollectionName } from '@sofie-automation/corelib/dist/dataModel/Collections'
import { registerCollection } from './lib'
import { WrappedMockCollection } from './implementations/mock'
Expand All @@ -16,7 +22,6 @@ import {
ObserveCallbacks,
ObserveChangesCallbacks,
UpdateOptions,
UpsertOptions,
} from '@sofie-automation/meteor-lib/dist/collections/lib'
import { MinimalMongoCursor } from './implementations/asyncCollection'
import { UserPermissions } from '@sofie-automation/meteor-lib/dist/userPermissions'
Expand Down Expand Up @@ -144,28 +149,11 @@ export interface AsyncOnlyMongoCollection<
): Promise<number>

/**
* Perform an update/insert of a document
* @param selector A query describing the documents to update. Typically this will be an id
* @param modifier The operation to apply to each matching document
* @param options Options for the operation
*/
upsertAsync(
selector: DBInterface['_id'] | { _id: DBInterface['_id'] },
modifier: MongoModifier<DBInterface>,
options?: UpsertOptions
): Promise<{ numberAffected?: number; insertedId?: DBInterface['_id'] }>
upsertAsync(
selector: MongoQuery<DBInterface>,
modifier: MongoModifier<DBInterface>,
// Require { multi } to be set when selecting multiple documents to be updated, otherwise only the first found document will be updated
options: UpdateOptions & Required<Pick<UpdateOptions, 'multi'>>
): Promise<{ numberAffected?: number; insertedId?: DBInterface['_id'] }>

/**
* Perform an upsert for multiple documents, based on the `_id` of each document
* @param documents Documents to upsert
* Replace a single document with a full document, matched by its `_id` (upserting if not present).
* @param doc The full document to store
* @returns `true` if an existing document was replaced, `false` if a new one was inserted
*/
upsertManyAsync(doc: DBInterface[]): Promise<{ numberAffected: number; insertedIds: DBInterface['_id'][] }>
replaceAsync(doc: DBInterface): Promise<boolean>

/**
* Remove one or more documents
Expand All @@ -178,7 +166,7 @@ export interface AsyncOnlyMongoCollection<
* This should be used instead of Promise.all(...) when doing multiple updates, as it is more performant
* @param ops Operations to perform
*/
bulkWriteAsync(ops: Array<AnyBulkWriteOperation<DBInterface>>): Promise<void>
bulkWriteAsync(ops: Array<MongoBulkWriteOperation<DBInterface>>): Promise<void>
}

/**
Expand Down
Loading
Loading