diff --git a/cosmosdb-schema/README.md b/cosmosdb-schema/README.md new file mode 100644 index 0000000..6438f53 --- /dev/null +++ b/cosmosdb-schema/README.md @@ -0,0 +1,15 @@ +# adaptTo() Live Server - Schema Creation for Cosmos DB (MS Azure) + +As stated in the [CosmosDB documentation][cosmosdb-limitations], it's not possible to create a unique index after a collection was created: + +> Azure Cosmos DB API for SQL or MongoDB accounts that create unique index after the container is created aren't supported for continuous backup. Only containers that create unique index as a part of the initial container creation are supported. For MongoDB accounts, you create unique index using [extension commands][cosmosdb-extension-commands]. + +The collection `qa-entries` requires a compound unique partial index to ensure the `entryIndex` numbers are numbered continuously for each talk, generating a number of QA entry numbers for each talk. This works via Mongoose schema definition of a native MongoDB instance, but not for CosmosDB with continuous backup. + +The solution is to drop the collection `qa-entries` after creating the collections via Mongoose on server setup, and then recreate it via MongoDB shell using this script: + +[qa-entries.txt](qa-entries.txt) + + +[cosmosdb-limitations]: https://learn.microsoft.com/en-us/azure/cosmos-db/continuous-backup-restore-introduction#current-limitations +[cosmosdb-extension-commands]: https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/custom-commands \ No newline at end of file diff --git a/cosmosdb-schema/qa-entries.txt b/cosmosdb-schema/qa-entries.txt new file mode 100644 index 0000000..f879a46 --- /dev/null +++ b/cosmosdb-schema/qa-entries.txt @@ -0,0 +1,49 @@ +use adaptto-live + +db["qa-entries"].drop() + +db.runCommand({ + customAction: "CreateCollection", + collection: "qa-entries", + indexes: [ + { + name: "_id_", + key: { "_id": 1 }, + unique: true + }, + { + name: "talkId_1", + key: { "talkId": 1 } + }, + { + name: "date_1", + key: { "date": 1 } + }, + { + name: "userid_1", + key: { "userid": 1 } + }, + { + name: "entryIndex_1", + key: { "entryIndex": 1 } + }, + { + name: "replyTo_1", + key: { "replyTo": 1 } + }, + { + name: "userid_1_username_1", + key: { "userid": 1, "username": 1 } + }, + { + name: "qaEntryId_1_userid_1", + key: { "qaEntryId": 1, "userid": 1 } + }, + { + name: "talkId_1_entryIndex_1", + key: { "talkId": 1, "entryIndex": -1 }, + unique: true, + partialFilterExpression: { "entryIndex": { "$gt": 0 } } + } + ] +}) diff --git a/package-lock.json b/package-lock.json index 9c3e5cb..9bd6cc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "adaptto-live-server", - "version": "1.6.2", + "version": "1.6.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "adaptto-live-server", - "version": "1.6.2", + "version": "1.6.3", "dependencies": { "dotenv": "^16.4.5", "express": "^4.19.2", diff --git a/package.json b/package.json index a51cffb..96ea294 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adaptto-live-server", - "version": "1.6.2", + "version": "1.6.3", "private": true, "scripts": { "dev": "nodemon src/index.ts | pino-pretty", diff --git a/src/socket/admin/kpi.ts b/src/socket/admin/kpi.ts index 1da888d..e6d9dd5 100644 --- a/src/socket/admin/kpi.ts +++ b/src/socket/admin/kpi.ts @@ -5,11 +5,11 @@ import log from '../../util/log' import { MessageModel, QAEntryModel, TalkRatingModel, UserModel } from '../../repository/mongodb.schema' export async function handleAdminKPI(socket : Socket) { - const { admin } = socket.data + const { admin, qaadmin } = socket.data const minuteSlots = [0, 30] // admin-only operations - if (!admin) { + if (!(admin || qaadmin)) { return } diff --git a/src/socket/admin/statistics.ts b/src/socket/admin/statistics.ts index 1f3f7d6..d4566d9 100644 --- a/src/socket/admin/statistics.ts +++ b/src/socket/admin/statistics.ts @@ -5,10 +5,10 @@ import log from '../../util/log' import { LoginCodeModel, MessageModel, QAEntryModel, TalkRatingModel, UserModel } from '../../repository/mongodb.schema' export async function handleAdminStatistics(socket : Socket) { - const { admin } = socket.data + const { admin, qaadmin } = socket.data // admin-only operations - if (!admin) { + if (!(admin || qaadmin)) { return } diff --git a/src/socket/socket.server.types.ts b/src/socket/socket.server.types.ts index 61d8ec6..4a7b4cb 100644 --- a/src/socket/socket.server.types.ts +++ b/src/socket/socket.server.types.ts @@ -1,4 +1,4 @@ -export interface InterServerEvents {} // eslint-disable-line @typescript-eslint/no-empty-interface +export interface InterServerEvents {} // eslint-disable-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-empty-object-type export interface SocketData { userid: string