From 3f08ff8da157b03aab279972d6c9b60cb87d466a Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 4 Dec 2024 01:19:41 -0500 Subject: [PATCH 1/6] Add registry for handling class setup functions. --- src/registries.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/registries.ts diff --git a/src/registries.ts b/src/registries.ts new file mode 100644 index 0000000..3340479 --- /dev/null +++ b/src/registries.ts @@ -0,0 +1,34 @@ +import { Class } from "./models"; + +type ClassSetupFunction = (cls: Class, storyName: string) => void; + +class ClassSetupRegistry { + + private members: { [storyName: string]: ClassSetupFunction[] | undefined } = {}; + + register(setup: ClassSetupFunction, storyName: string) { + if (!(storyName in this.members)) { + this.members[storyName] = []; + } + this.members[storyName]?.push(setup); + } + + unregister(setup: ClassSetupFunction, storyName: string) { + const setups = this.members[storyName]; + if (!setups) { + return; + } + + const index = setups.indexOf(setup); + if (index > -1) { + setups.splice(index, 1); + } + } + + setupFunctions(storyName: string): ClassSetupFunction[] | undefined { + return this.members[storyName]; + } + +} + +export const classSetupRegistry = new ClassSetupRegistry(); From 0b6c5951adee6acc2d09efee397d9038911a6e5b Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 4 Dec 2024 01:20:41 -0500 Subject: [PATCH 2/6] Add cls-hooked module for automatic transaction management. Move Hubble-specific setup to its own method. --- package-lock.json | 111 ++++++++++++++++++++++++++++ package.json | 2 + src/database.ts | 68 ++++++++++------- src/main.ts | 1 + src/models/class.ts | 6 +- src/models/story.ts | 5 ++ src/stories/hubbles_law/database.ts | 14 +++- 7 files changed, 180 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8764fd3..d690f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "@effect/schema": "^0.63.2", "@jest/globals": "^29.7.0", "@types/body-parser": "^1.19.2", + "@types/cls-hooked": "^4.3.9", "@types/cookie-parser": "^1.4.2", "@types/cors": "^2.8.12", "@types/crypto-js": "^4.1.0", @@ -20,6 +21,7 @@ "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", "body-parser": "^1.19.1", + "cls-hooked": "^4.2.2", "connect-session-sequelize": "^7.1.3", "cookie-parser": "^1.4.6", "cors": "^2.8.5", @@ -1311,6 +1313,14 @@ "@types/node": "*" } }, + "node_modules/@types/cls-hooked": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.9.tgz", + "integrity": "sha512-CMtHMz6Q/dkfcHarq9nioXH8BDPP+v5xvd+N90lBQ2bdmu06UvnLDqxTKoOJzz4SzIwb/x9i4UXGAAcnUDuIvg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -2107,6 +2117,17 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "node_modules/async-hook-jl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", + "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", + "dependencies": { + "stack-chain": "^1.3.7" + }, + "engines": { + "node": "^4.7 || >=6.9 || >=7.3" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2576,6 +2597,27 @@ "node": ">=12" } }, + "node_modules/cls-hooked": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", + "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", + "dependencies": { + "async-hook-jl": "^1.7.6", + "emitter-listener": "^1.0.1", + "semver": "^5.4.1" + }, + "engines": { + "node": "^4.7 || >=6.9 || >=7.3 || >=8.2.1" + } + }, + "node_modules/cls-hooked/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3009,6 +3051,14 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz", "integrity": "sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ==" }, + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dependencies": { + "shimmer": "^1.2.0" + } + }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", @@ -6617,6 +6667,11 @@ "node": ">=8" } }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -6692,6 +6747,11 @@ "node": ">= 0.6" } }, + "node_modules/stack-chain": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", + "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==" + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -8520,6 +8580,14 @@ "@types/node": "*" } }, + "@types/cls-hooked": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.9.tgz", + "integrity": "sha512-CMtHMz6Q/dkfcHarq9nioXH8BDPP+v5xvd+N90lBQ2bdmu06UvnLDqxTKoOJzz4SzIwb/x9i4UXGAAcnUDuIvg==", + "requires": { + "@types/node": "*" + } + }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -9176,6 +9244,14 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "async-hook-jl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", + "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", + "requires": { + "stack-chain": "^1.3.7" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -9493,6 +9569,23 @@ "wrap-ansi": "^7.0.0" } }, + "cls-hooked": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", + "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", + "requires": { + "async-hook-jl": "^1.7.6", + "emitter-listener": "^1.0.1", + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + } + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -9818,6 +9911,14 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz", "integrity": "sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ==" }, + "emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "requires": { + "shimmer": "^1.2.0" + } + }, "emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", @@ -12466,6 +12567,11 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, + "shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, "side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -12526,6 +12632,11 @@ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" }, + "stack-chain": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", + "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==" + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", diff --git a/package.json b/package.json index 57a2835..6ea7e12 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@effect/schema": "^0.63.2", "@jest/globals": "^29.7.0", "@types/body-parser": "^1.19.2", + "@types/cls-hooked": "^4.3.9", "@types/cookie-parser": "^1.4.2", "@types/cors": "^2.8.12", "@types/crypto-js": "^4.1.0", @@ -22,6 +23,7 @@ "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", "body-parser": "^1.19.1", + "cls-hooked": "^4.2.2", "connect-session-sequelize": "^7.1.3", "cookie-parser": "^1.4.6", "cors": "^2.8.5", diff --git a/src/database.ts b/src/database.ts index 7ed43ea..f6e7595 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,5 +1,6 @@ import { BaseError, Model, Op, QueryTypes, Sequelize, Transaction, UniqueConstraintError, WhereOptions } from "sequelize"; import dotenv from "dotenv"; +import { createNamespace } from "cls-hooked"; import * as S from "@effect/schema/Schema"; @@ -42,6 +43,7 @@ import { Question } from "./models/question"; import { logger } from "./logger"; import { Stage } from "./models/stage"; import { addClassToMergeGroup } from "./stories/hubbles_law/database"; +import { classSetupRegistry } from "./registries"; export type LoginResponse = { type: "none" | "student" | "educator" | "admin", @@ -93,6 +95,9 @@ export function getDatabaseConnection(options?: DBConnectionOptions) { // Create any associations that we need setUpAssociations(); + const namespace = createNamespace("cds-api-namespace"); + Sequelize.useCLS(namespace); + return database; } @@ -282,7 +287,7 @@ export async function signUpStudent(options: SignUpStudentOptions): Promise { result = signupResultFromError(error); }); @@ -314,6 +319,7 @@ export const CreateClassSchema = S.struct({ name: S.string, expected_size: S.number.pipe(S.int()), asynchronous: S.optional(S.boolean), + story_name: S.optional(S.string), }); export type CreateClassOptions = S.Schema.To; @@ -330,20 +336,22 @@ export async function createClass(options: CreateClassOptions): Promise { + console.log(db); + const cls = await db.transaction(async _transaction => { - const cls = await Class.create(creationInfo, { transaction }); + const cls = await Class.create(creationInfo); - // For the pilot, the Hubble Data Story will be the only option, - // so we'll automatically associate that with the class - // TODO: When there are more classes available, we need to make - // this functionality more generic - if (cls) { + const storyName = options.story_name; + if (storyName) { await ClassStories.create({ - story_name: "hubbles_law", - class_id: cls.id - }, { transaction }); + story_name: storyName, + class_id: cls.id, + }); + classSetupRegistry.setupFunctions(storyName)?.forEach(setup => { + console.log(setup); + setup(cls, storyName); + }); } return cls; @@ -687,8 +695,7 @@ export async function getClassRoster(classID: number): Promise { } /** These functions are for testing purposes only */ -export async function newDummyClassForStory(storyName: string, transaction?: Transaction): Promise<{cls: Class, dummy: DummyClass}> { - const trans = transaction ?? null; +export async function newDummyClassForStory(storyName: string): Promise<{cls: Class, dummy: DummyClass}> { const ct = await Class.count({ where: { educator_id: 0, @@ -696,16 +703,14 @@ export async function newDummyClassForStory(storyName: string, transaction?: Tra [Op.like]: `DummyClass_${storyName}_` } }, - transaction: trans, }); const cls = await Class.create({ educator_id: 0, name: `DummyClass_${storyName}_${ct+1}`, code: "xxxxxx" - }, { transaction: trans }); + }); let dc = await DummyClass.findOne({ where: { story_name: storyName }, - transaction: trans, }); if (dc !== null) { dc.update({ class_id: cls.id }) @@ -716,8 +721,8 @@ export async function newDummyClassForStory(storyName: string, transaction?: Tra } else { dc = await DummyClass.create({ class_id: cls.id, - story_name: storyName - }, { transaction: trans }); + story_name: storyName, + }); } return { cls: cls, dummy: dc }; } @@ -738,7 +743,7 @@ export async function newDummyStudent(seed = false, } try { - const transactionResult = await db.transaction(async transaction => { + const transactionResult = await db.transaction(async _transaction => { const student = await Student.create({ username: `dummy_student_${newID}`, verified: 1, @@ -751,25 +756,23 @@ export async function newDummyStudent(seed = false, seed: seed ? 1 : 0, team_member: teamMember, dummy: true - }, { transaction }); + }); // If we have a story name, and are creating a seed student, we want to add this student to the current "dummy class" for that story if (seed && storyName !== null) { let cls: Class | null = null; let dummyClass = await DummyClass.findOne({ where: { story_name: storyName }, - transaction }); let clsSize: number; if (dummyClass === null) { - const res = await newDummyClassForStory(storyName, transaction); + const res = await newDummyClassForStory(storyName); dummyClass = res.dummy; cls = res.cls; clsSize = 0; } else { clsSize = await StudentsClasses.count({ where: { class_id: dummyClass.class_id }, - transaction, }); } @@ -780,14 +783,13 @@ export async function newDummyStudent(seed = false, } else { cls = await Class.findOne({ where: { id: dummyClass.class_id }, - transaction, }); } if (cls !== null) { await StudentsClasses.create({ class_id: cls.id, student_id: student.id - }, { transaction }); + }); } } return student; @@ -939,3 +941,19 @@ export async function getDashboardGroupClasses(code: string): Promise, InferCreationAttributes declare id: CreationOptional; declare name: string; declare display_name: string; + declare description: CreationOptional; } export function initializeStoryModel(sequelize: Sequelize) { @@ -23,6 +24,10 @@ export function initializeStoryModel(sequelize: Sequelize) { type: DataTypes.STRING, allowNull: false, unique: true + }, + description: { + type: DataTypes.STRING, + allowNull: true, } }, { sequelize, diff --git a/src/stories/hubbles_law/database.ts b/src/stories/hubbles_law/database.ts index 52712fa..28c54c7 100644 --- a/src/stories/hubbles_law/database.ts +++ b/src/stories/hubbles_law/database.ts @@ -2,7 +2,7 @@ import { Attributes, FindOptions, Op, QueryTypes, Sequelize, WhereAttributeHash, import { AsyncMergedHubbleStudentClasses, Galaxy, HubbleMeasurement, HubbleWaitingRoomOverride, SampleHubbleMeasurement, SyncMergedHubbleClasses } from "./models"; import { findClassById, findStudentById } from "../../database"; import { RemoveHubbleMeasurementResult, SubmitHubbleMeasurementResult } from "./request_results"; -import { Class, StoryState, Student, StudentsClasses } from "../../models"; +import { Class, ClassStories, StoryState, Student, StudentsClasses } from "../../models"; import { HubbleStudentData } from "./models/hubble_student_data"; import { HubbleClassData } from "./models/hubble_class_data"; import { IgnoreStudent } from "../../models/ignore_student"; @@ -911,3 +911,15 @@ export async function removeWaitingRoomOverride(classID: number): Promise NaN); } + +export async function hubbleClassSetup( + cls: Class, + _storyName: string, +) { + if (cls) { + console.log(cls); + if (cls.asynchronous || cls.small_class) { + await addClassToMergeGroup(cls.id); + } + } +} From 8bb534c33635c493a612de3e1bf2c2cd5ff00184 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 4 Dec 2024 01:22:09 -0500 Subject: [PATCH 3/6] Register Hubble setup function method with registry. --- src/registries.ts | 2 +- src/stories/hubbles_law/main.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/registries.ts b/src/registries.ts index 3340479..77e1021 100644 --- a/src/registries.ts +++ b/src/registries.ts @@ -6,7 +6,7 @@ class ClassSetupRegistry { private members: { [storyName: string]: ClassSetupFunction[] | undefined } = {}; - register(setup: ClassSetupFunction, storyName: string) { + register(storyName: string, setup: ClassSetupFunction) { if (!(storyName in this.members)) { this.members[storyName] = []; } diff --git a/src/stories/hubbles_law/main.ts b/src/stories/hubbles_law/main.ts index d986f2b..f0c1701 100644 --- a/src/stories/hubbles_law/main.ts +++ b/src/stories/hubbles_law/main.ts @@ -1,5 +1,9 @@ +import { classSetupRegistry } from "../../registries"; +import { hubbleClassSetup } from "./database"; import { router, setup } from "./router"; +classSetupRegistry.register("hubbles_law", hubbleClassSetup); + module.exports = { path: "/hubbles_law", router, From bbd95f08ecafca6a4e71f18a9480d8ed7e9ac385 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 4 Dec 2024 10:02:07 -0500 Subject: [PATCH 4/6] Make sure that we await setup functions. --- src/database.ts | 34 ++++++---------------------------- src/registries.ts | 2 +- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/database.ts b/src/database.ts index f6e7595..3e2b948 100644 --- a/src/database.ts +++ b/src/database.ts @@ -348,23 +348,17 @@ export async function createClass(options: CreateClassOptions): Promise { - console.log(setup); - setup(cls, storyName); - }); + const setupFunctions = classSetupRegistry.setupFunctions(storyName); + if (setupFunctions) { + for (const setupFunc of setupFunctions) { + await setupFunc(cls, storyName); + } + } } return cls; }); - // Another piece of Hubble-specific functionality - // Note that we need to reload the class so that the virtual `small_class` - // column has its value populated - await cls.reload(); - if (cls.asynchronous || cls.small_class) { - await addClassToMergeGroup(cls.id); - } - return { result: result, class: creationInfo }; } catch (error) { result = (error instanceof BaseError) ? createClassResultFromError(error) : CreateClassResult.Error; @@ -941,19 +935,3 @@ export async function getDashboardGroupClasses(code: string): Promise void; +type ClassSetupFunction = (cls: Class, storyName: string) => Promise; class ClassSetupRegistry { From 346edbbea4f6490cb20e9b78c999781b14c1819f Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 4 Dec 2024 10:28:58 -0500 Subject: [PATCH 5/6] Remove unused imports. --- src/database.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/database.ts b/src/database.ts index 3e2b948..5cc8fcf 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,4 +1,4 @@ -import { BaseError, Model, Op, QueryTypes, Sequelize, Transaction, UniqueConstraintError, WhereOptions } from "sequelize"; +import { BaseError, Model, Op, QueryTypes, Sequelize, UniqueConstraintError, WhereOptions } from "sequelize"; import dotenv from "dotenv"; import { createNamespace } from "cls-hooked"; @@ -42,7 +42,6 @@ import { StudentOption, StudentOptions } from "./models/student_options"; import { Question } from "./models/question"; import { logger } from "./logger"; import { Stage } from "./models/stage"; -import { addClassToMergeGroup } from "./stories/hubbles_law/database"; import { classSetupRegistry } from "./registries"; export type LoginResponse = { From bdd7d682cea76bbf22e7c926b42b46d2bb2d0b08 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 4 Dec 2024 10:39:29 -0500 Subject: [PATCH 6/6] Fix linting issues. --- src/database.ts | 3 +-- src/stories/hubbles_law/database.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/database.ts b/src/database.ts index 5cc8fcf..3381c34 100644 --- a/src/database.ts +++ b/src/database.ts @@ -335,8 +335,7 @@ export async function createClass(options: CreateClassOptions): Promise { + await db.transaction(async _transaction => { const cls = await Class.create(creationInfo); diff --git a/src/stories/hubbles_law/database.ts b/src/stories/hubbles_law/database.ts index 28c54c7..0209d5f 100644 --- a/src/stories/hubbles_law/database.ts +++ b/src/stories/hubbles_law/database.ts @@ -2,7 +2,7 @@ import { Attributes, FindOptions, Op, QueryTypes, Sequelize, WhereAttributeHash, import { AsyncMergedHubbleStudentClasses, Galaxy, HubbleMeasurement, HubbleWaitingRoomOverride, SampleHubbleMeasurement, SyncMergedHubbleClasses } from "./models"; import { findClassById, findStudentById } from "../../database"; import { RemoveHubbleMeasurementResult, SubmitHubbleMeasurementResult } from "./request_results"; -import { Class, ClassStories, StoryState, Student, StudentsClasses } from "../../models"; +import { Class, StoryState, Student, StudentsClasses } from "../../models"; import { HubbleStudentData } from "./models/hubble_student_data"; import { HubbleClassData } from "./models/hubble_class_data"; import { IgnoreStudent } from "../../models/ignore_student";