From 89144aafce9f7c3a095070330ab21620341097c2 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sat, 17 Feb 2024 17:25:39 -0500 Subject: [PATCH 1/8] Adds simple migration and edits pages for seeds in db --- .../20240217215104_model_revision_seed/migration.sql | 3 +++ packages/hub/prisma/schema.prisma | 3 ++- packages/hub/schema.graphql | 1 + .../hub/src/app/models/[owner]/[slug]/EditModelPage.tsx | 1 + .../app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx | 7 +++++++ packages/hub/src/graphql/types/ModelRevision.ts | 1 + 6 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql diff --git a/packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql b/packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql new file mode 100644 index 0000000000..5cf363523a --- /dev/null +++ b/packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql @@ -0,0 +1,3 @@ +ALTER TABLE "ModelRevision" ADD COLUMN "seed" TEXT DEFAULT 'DEFAULT_SEED'; +UPDATE "ModelRevision" SET "seed" = 'DEFAULT_SEED' WHERE "seed" IS NULL; +ALTER TABLE "ModelRevision" ALTER COLUMN "seed" SET NOT NULL; \ No newline at end of file diff --git a/packages/hub/prisma/schema.prisma b/packages/hub/prisma/schema.prisma index 049cdff78a..0af61b0ee0 100644 --- a/packages/hub/prisma/schema.prisma +++ b/packages/hub/prisma/schema.prisma @@ -211,7 +211,6 @@ model ModelRevision { // optional until we populate old rows after migration author User? @relation(fields: [authorId], references: [id]) authorId String? - comment String @default("") contentType ModelType @@ -225,6 +224,8 @@ model ModelRevision { // required by Prisma, but unused since `model` field should point at the same entity currentRevisionModel Model? @relation("CurrentRevision") + seed String @default("DEFAULT_SEED") + @@index([modelId]) } diff --git a/packages/hub/schema.graphql b/packages/hub/schema.graphql index 09546eb950..b306be5d75 100644 --- a/packages/hub/schema.graphql +++ b/packages/hub/schema.graphql @@ -193,6 +193,7 @@ type ModelRevision implements Node { id: ID! model: Model! relativeValuesExports: [RelativeValuesExport!]! + seed: String! } type ModelRevisionConnection { diff --git a/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx b/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx index 8aea85033c..c578518e9a 100644 --- a/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx +++ b/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx @@ -22,6 +22,7 @@ export const EditModelPage: FC<{ ... on Model { id currentRevision { + seed content { __typename } diff --git a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx index 1a766aa3fc..748c42eace 100644 --- a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx +++ b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx @@ -145,6 +145,7 @@ export const EditSquiggleSnippetModel: FC = ({ } currentRevision { id + seed content { __typename ... on SquiggleSnippet { @@ -399,6 +400,12 @@ export const EditSquiggleSnippetModel: FC = ({ }; } + console.log(model); + playgroundProps.environment = { + sampleCount: 1000, + seed: model.currentRevision.seed, + }; + if ( versionSupportsOnOpenExport.propsByVersion<"SquigglePlayground">( squiggle.version, diff --git a/packages/hub/src/graphql/types/ModelRevision.ts b/packages/hub/src/graphql/types/ModelRevision.ts index 056ee4acec..6cc3e1361a 100644 --- a/packages/hub/src/graphql/types/ModelRevision.ts +++ b/packages/hub/src/graphql/types/ModelRevision.ts @@ -42,6 +42,7 @@ export const ModelRevision = builder.prismaNode("ModelRevision", { model: t.relation("model"), author: t.relation("author", { nullable: true }), comment: t.exposeString("comment"), + seed: t.exposeString("seed", { nullable: false }), content: t.field({ type: ModelContent, select: { squiggleSnippet: true }, From 6bdf10c9c8a6dec6abd7ca54e6aba00de0148e9a Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sat, 17 Feb 2024 19:26:07 -0500 Subject: [PATCH 2/8] Add seed to more parts --- packages/hub/prisma/schema.prisma | 2 +- packages/hub/schema.graphql | 1 + .../src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx | 1 + packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts | 1 + .../hub/src/graphql/mutations/createSquiggleSnippetModel.ts | 1 + .../hub/src/graphql/mutations/updateSquiggleSnippetModel.ts | 2 ++ 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/hub/prisma/schema.prisma b/packages/hub/prisma/schema.prisma index 0af61b0ee0..04da8de8ca 100644 --- a/packages/hub/prisma/schema.prisma +++ b/packages/hub/prisma/schema.prisma @@ -224,7 +224,7 @@ model ModelRevision { // required by Prisma, but unused since `model` field should point at the same entity currentRevisionModel Model? @relation("CurrentRevision") - seed String @default("DEFAULT_SEED") + seed String @@index([modelId]) } diff --git a/packages/hub/schema.graphql b/packages/hub/schema.graphql index b306be5d75..1cefbf3b58 100644 --- a/packages/hub/schema.graphql +++ b/packages/hub/schema.graphql @@ -454,6 +454,7 @@ input MutationUpdateSquiggleSnippetModelInput { exports: [SquiggleModelExportInput!] owner: String! relativeValuesExports: [RelativeValuesExportInput!] + seed: String slug: String! } diff --git a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx index 748c42eace..39a963272a 100644 --- a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx +++ b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx @@ -239,6 +239,7 @@ export const EditSquiggleSnippetModel: FC = ({ comment: extraData?.comment, slug: model.slug, owner: model.owner.slug, + seed: revision.seed, }, }), confirmation: "Saved", diff --git a/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts b/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts index ddacc7a7e5..0d28cb1133 100644 --- a/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts +++ b/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts @@ -64,6 +64,7 @@ builder.mutationField("adminUpdateModelVersion", (t) => connect: { email: self.email! }, }, comment: `Automated upgrade from ${model.currentRevision.squiggleSnippet.version} to ${input.version}`, + seed: model.currentRevision.seed, relativeValuesExports: { createMany: { data: model.currentRevision.relativeValuesExports.map( diff --git a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts index 55bf004bf7..eb27d3a9c1 100644 --- a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts @@ -78,6 +78,7 @@ builder.mutationField("createSquiggleSnippetModel", (t) => id: model.id, }, }, + seed: "MY_TEST_SEED", }, }); diff --git a/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts index 7074b387fc..902a86dd8c 100644 --- a/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts @@ -70,6 +70,7 @@ builder.mutationField("updateSquiggleSnippetModel", (t) => required: true, }), comment: t.input.string(), + seed: t.input.string(), }, resolve: async (_, { input }, { session }) => { const existingModel = await getWriteableModel({ @@ -148,6 +149,7 @@ builder.mutationField("updateSquiggleSnippetModel", (t) => }, contentType: "SquiggleSnippet", comment: input.comment ?? "", + seed: input.seed || "DEFAULT_SEED", model: { connect: { id: existingModel.id }, }, From 8c49daa8411eaea3139e837068b62bc58bfdc0de Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sat, 17 Feb 2024 19:35:46 -0500 Subject: [PATCH 3/8] Use seedGenerator for new models --- .../components/src/lib/hooks/usePlaygroundSettings.ts | 5 +++-- packages/components/src/lib/seedGenerator.ts | 7 ------- .../graphql/mutations/createSquiggleSnippetModel.ts | 4 +++- packages/squiggle-lang/src/index.ts | 2 ++ packages/squiggle-lang/src/utility/seedGenerator.ts | 11 +++++++++++ .../lib => squiggle-lang/src/utility}/seedWords.ts | 0 6 files changed, 19 insertions(+), 10 deletions(-) delete mode 100644 packages/components/src/lib/seedGenerator.ts create mode 100644 packages/squiggle-lang/src/utility/seedGenerator.ts rename packages/{components/src/lib => squiggle-lang/src/utility}/seedWords.ts (100%) diff --git a/packages/components/src/lib/hooks/usePlaygroundSettings.ts b/packages/components/src/lib/hooks/usePlaygroundSettings.ts index 08dd10f04c..d37e5db2a2 100644 --- a/packages/components/src/lib/hooks/usePlaygroundSettings.ts +++ b/packages/components/src/lib/hooks/usePlaygroundSettings.ts @@ -1,12 +1,13 @@ import merge from "lodash/merge.js"; import { useCallback, useState } from "react"; +import { generateSeed } from "@quri/squiggle-lang"; + import { defaultPlaygroundSettings, PartialPlaygroundSettings, type PlaygroundSettings, } from "../../components/PlaygroundSettings.js"; -import { randomSeed } from "../seedGenerator.js"; export type Args = { defaultSettings: PartialPlaygroundSettings; @@ -41,7 +42,7 @@ export function usePlaygroundSettings({ ...settings, environment: { ...settings.environment, - seed: randomSeed(), + seed: generateSeed(), }, }); }; diff --git a/packages/components/src/lib/seedGenerator.ts b/packages/components/src/lib/seedGenerator.ts deleted file mode 100644 index 5a0af1f853..0000000000 --- a/packages/components/src/lib/seedGenerator.ts +++ /dev/null @@ -1,7 +0,0 @@ -import sample from "lodash/sample.js"; - -import { seedWords } from "./seedWords.js"; - -export function randomSeed(): string { - return [sample(seedWords), sample(seedWords), sample(seedWords)].join("_"); -} diff --git a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts index eb27d3a9c1..97de3a722b 100644 --- a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts @@ -1,5 +1,7 @@ import { ZodError } from "zod"; +import { generateSeed } from "@quri/squiggle-lang"; + import { builder } from "@/graphql/builder"; import { prisma } from "@/prisma"; @@ -78,7 +80,7 @@ builder.mutationField("createSquiggleSnippetModel", (t) => id: model.id, }, }, - seed: "MY_TEST_SEED", + seed: generateSeed(), }, }); diff --git a/packages/squiggle-lang/src/index.ts b/packages/squiggle-lang/src/index.ts index 928f1c9f6a..5005bee76f 100644 --- a/packages/squiggle-lang/src/index.ts +++ b/packages/squiggle-lang/src/index.ts @@ -130,3 +130,5 @@ export { SCALE_POWER_DEFAULT_CONSTANT, SCALE_SYMLOG_DEFAULT_CONSTANT, } from "./value/VScale.js"; + +export { generateSeed } from "./utility/seedGenerator.js"; diff --git a/packages/squiggle-lang/src/utility/seedGenerator.ts b/packages/squiggle-lang/src/utility/seedGenerator.ts new file mode 100644 index 0000000000..d8647d6ddc --- /dev/null +++ b/packages/squiggle-lang/src/utility/seedGenerator.ts @@ -0,0 +1,11 @@ +import sample from "lodash/sample.js"; + +import { seedWords } from "./seedWords.js"; + +export function generateSeed(): string { + return [ + sample(seedWords)?.toUpperCase(), + sample(seedWords)?.toUpperCase(), + sample(seedWords)?.toUpperCase(), + ].join("_"); +} diff --git a/packages/components/src/lib/seedWords.ts b/packages/squiggle-lang/src/utility/seedWords.ts similarity index 100% rename from packages/components/src/lib/seedWords.ts rename to packages/squiggle-lang/src/utility/seedWords.ts From 2159536ec7ddd044ebb1320d6d73cea37f1ae827 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 18 Feb 2024 09:55:15 -0500 Subject: [PATCH 4/8] Added changeset, minor cleanup --- .changeset/mean-flies-wave.md | 6 +++++ packages/hub/prisma/schema.prisma | 4 ++-- packages/hub/schema.graphql | 5 +++- .../hub/scripts/updateDefaultModelSeeds.ts | 23 +++++++++++++++++++ .../[slug]/EditSquiggleSnippetModel.tsx | 4 ++-- packages/hub/src/constants.ts | 2 ++ .../mutations/createSquiggleSnippetModel.ts | 4 ++++ .../mutations/updateSquiggleSnippetModel.ts | 4 ++-- .../hub/src/graphql/queries/runSquiggle.ts | 5 ++-- .../hub/src/graphql/types/ModelRevision.ts | 2 +- 10 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 .changeset/mean-flies-wave.md create mode 100644 packages/hub/scripts/updateDefaultModelSeeds.ts diff --git a/.changeset/mean-flies-wave.md b/.changeset/mean-flies-wave.md new file mode 100644 index 0000000000..eecb7e7829 --- /dev/null +++ b/.changeset/mean-flies-wave.md @@ -0,0 +1,6 @@ +--- +"@quri/squiggle-lang": patch +"@quri/squiggle-components": patch +--- + +Seeds should be stored for Model Revisions diff --git a/packages/hub/prisma/schema.prisma b/packages/hub/prisma/schema.prisma index 04da8de8ca..a423a3eed6 100644 --- a/packages/hub/prisma/schema.prisma +++ b/packages/hub/prisma/schema.prisma @@ -211,7 +211,7 @@ model ModelRevision { // optional until we populate old rows after migration author User? @relation(fields: [authorId], references: [id]) authorId String? - comment String @default("") + comment String @default("") contentType ModelType @@ -224,7 +224,7 @@ model ModelRevision { // required by Prisma, but unused since `model` field should point at the same entity currentRevisionModel Model? @relation("CurrentRevision") - seed String + seed String @default("DEFAULT_SEED") @@index([modelId]) } diff --git a/packages/hub/schema.graphql b/packages/hub/schema.graphql index 1cefbf3b58..d4e22374a8 100644 --- a/packages/hub/schema.graphql +++ b/packages/hub/schema.graphql @@ -348,6 +348,9 @@ input MutationCreateSquiggleSnippetModelInput { """Defaults to false""" isPrivate: Boolean + + """A unique seed, used for calculation""" + seed: String slug: String! version: String! } @@ -454,7 +457,7 @@ input MutationUpdateSquiggleSnippetModelInput { exports: [SquiggleModelExportInput!] owner: String! relativeValuesExports: [RelativeValuesExportInput!] - seed: String + seed: String! slug: String! } diff --git a/packages/hub/scripts/updateDefaultModelSeeds.ts b/packages/hub/scripts/updateDefaultModelSeeds.ts new file mode 100644 index 0000000000..d40d49ece7 --- /dev/null +++ b/packages/hub/scripts/updateDefaultModelSeeds.ts @@ -0,0 +1,23 @@ +// import the PrismaClient instance +import { prisma } from "@/prisma"; + +async function updateDefaultModelSeeds() { + try { + // Start transaction to update all models with DEFAULT_SEED to UPDATED_SEED + const updateResult = await prisma.model.updateMany({ + where: { + seed: "DEFAULT_SEED", + }, + data: { + seed: "UPDATED_SEED", + }, + }); + + console.log(`Updated ${updateResult.count} models.`); + } catch (error) { + console.error("Failed to update model seeds:", error); + } +} + +// Execute the script +updateDefaultModelSeeds(); diff --git a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx index 39a963272a..89d31e2185 100644 --- a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx +++ b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx @@ -31,6 +31,7 @@ import { import { EditModelExports } from "@/components/exports/EditModelExports"; import { ReactRoot } from "@/components/ReactRoot"; import { FormModal } from "@/components/ui/FormModal"; +import { SAMPLE_COUNT_DEFAULT } from "@/constants"; import { useAvailableHeight } from "@/hooks/useAvailableHeight"; import { useMutationForm } from "@/hooks/useMutationForm"; import { extractFromGraphqlErrorUnion } from "@/lib/graphqlHelpers"; @@ -401,9 +402,8 @@ export const EditSquiggleSnippetModel: FC = ({ }; } - console.log(model); playgroundProps.environment = { - sampleCount: 1000, + sampleCount: SAMPLE_COUNT_DEFAULT, seed: model.currentRevision.seed, }; diff --git a/packages/hub/src/constants.ts b/packages/hub/src/constants.ts index 4fafce342f..3be4715742 100644 --- a/packages/hub/src/constants.ts +++ b/packages/hub/src/constants.ts @@ -3,3 +3,5 @@ // Note that only `NEXT_PUBLIC_*` vars are affected; others can be used through `process.env.FOO` without issues. export const VERCEL_URL = process.env["NEXT_PUBLIC_VERCEL_URL"]; + +export const SAMPLE_COUNT_DEFAULT = 1000; diff --git a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts index 97de3a722b..4f17b1181e 100644 --- a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts @@ -38,6 +38,10 @@ builder.mutationField("createSquiggleSnippetModel", (t) => isPrivate: t.input.boolean({ description: "Defaults to false", }), + seed: t.input.string({ + required: false, + description: "A unique seed, used for calculation", + }), }, resolve: async (_, { input }, { session }) => { const model = await prisma.$transaction(async (tx) => { diff --git a/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts index 902a86dd8c..2c44e2dee2 100644 --- a/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts @@ -70,7 +70,7 @@ builder.mutationField("updateSquiggleSnippetModel", (t) => required: true, }), comment: t.input.string(), - seed: t.input.string(), + seed: t.input.string({ required: true }), }, resolve: async (_, { input }, { session }) => { const existingModel = await getWriteableModel({ @@ -149,7 +149,7 @@ builder.mutationField("updateSquiggleSnippetModel", (t) => }, contentType: "SquiggleSnippet", comment: input.comment ?? "", - seed: input.seed || "DEFAULT_SEED", + seed: input.seed, model: { connect: { id: existingModel.id }, }, diff --git a/packages/hub/src/graphql/queries/runSquiggle.ts b/packages/hub/src/graphql/queries/runSquiggle.ts index eb86528dcd..6598de4f07 100644 --- a/packages/hub/src/graphql/queries/runSquiggle.ts +++ b/packages/hub/src/graphql/queries/runSquiggle.ts @@ -3,6 +3,7 @@ import crypto from "crypto"; import { SqProject, SqValue } from "@quri/squiggle-lang"; +import { SAMPLE_COUNT_DEFAULT } from "@/constants"; import { builder } from "@/graphql/builder"; import { prisma } from "@/prisma"; @@ -80,9 +81,9 @@ export async function runSquiggle(code: string): Promise { const MAIN = "main"; const env = { - sampleCount: 1000, // int + sampleCount: SAMPLE_COUNT_DEFAULT, // int xyPointLength: 1000, // int - seed: "default_seed", + seed: "DEFAULT_SEED", }; const project = SqProject.create({ environment: env }); diff --git a/packages/hub/src/graphql/types/ModelRevision.ts b/packages/hub/src/graphql/types/ModelRevision.ts index 6cc3e1361a..7bffd3d7a9 100644 --- a/packages/hub/src/graphql/types/ModelRevision.ts +++ b/packages/hub/src/graphql/types/ModelRevision.ts @@ -42,7 +42,7 @@ export const ModelRevision = builder.prismaNode("ModelRevision", { model: t.relation("model"), author: t.relation("author", { nullable: true }), comment: t.exposeString("comment"), - seed: t.exposeString("seed", { nullable: false }), + seed: t.exposeString("seed"), content: t.field({ type: ModelContent, select: { squiggleSnippet: true }, From b2e283e56ffed7b66409a98912394ec8eb36a496 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 18 Feb 2024 12:16:30 -0500 Subject: [PATCH 5/8] Fixed updateModelSeeds script --- .../hub/scripts/updateDefaultModelSeeds.ts | 23 ------- .../hub/src/app/api/updateModelSeeds/route.ts | 69 +++++++++++++++++++ packages/hub/src/constants.ts | 2 + .../hub/src/graphql/queries/runSquiggle.ts | 4 +- 4 files changed, 73 insertions(+), 25 deletions(-) delete mode 100644 packages/hub/scripts/updateDefaultModelSeeds.ts create mode 100644 packages/hub/src/app/api/updateModelSeeds/route.ts diff --git a/packages/hub/scripts/updateDefaultModelSeeds.ts b/packages/hub/scripts/updateDefaultModelSeeds.ts deleted file mode 100644 index d40d49ece7..0000000000 --- a/packages/hub/scripts/updateDefaultModelSeeds.ts +++ /dev/null @@ -1,23 +0,0 @@ -// import the PrismaClient instance -import { prisma } from "@/prisma"; - -async function updateDefaultModelSeeds() { - try { - // Start transaction to update all models with DEFAULT_SEED to UPDATED_SEED - const updateResult = await prisma.model.updateMany({ - where: { - seed: "DEFAULT_SEED", - }, - data: { - seed: "UPDATED_SEED", - }, - }); - - console.log(`Updated ${updateResult.count} models.`); - } catch (error) { - console.error("Failed to update model seeds:", error); - } -} - -// Execute the script -updateDefaultModelSeeds(); diff --git a/packages/hub/src/app/api/updateModelSeeds/route.ts b/packages/hub/src/app/api/updateModelSeeds/route.ts new file mode 100644 index 0000000000..9affa1d423 --- /dev/null +++ b/packages/hub/src/app/api/updateModelSeeds/route.ts @@ -0,0 +1,69 @@ +import { PrismaClient } from "@prisma/client"; +import { NextRequest, NextResponse } from "next/server"; + +import { generateSeed } from "@quri/squiggle-lang"; + +import { DEFAULT_SEED } from "@/constants"; + +const prisma = new PrismaClient(); + +async function generateAndSetNewSeedForModels() { + // Find all models + const models = await prisma.model.findMany({ + include: { + revisions: { + orderBy: { + createdAt: "desc", + }, + take: 1, // Only include the last revision + }, + }, + }); + + for (const model of models) { + const lastRevision = model.revisions[0]; + + // Check if the last revision has the DEFAULT_SEED + if (lastRevision && lastRevision.seed === DEFAULT_SEED) { + // Generate a random seed for the model + const newSeed = generateSeed(); + + // Update seed for all revisions of the current model + await prisma.modelRevision.updateMany({ + where: { modelId: model.id }, + data: { seed: newSeed }, + }); + } + } +} + +export async function POST(req: NextRequest) { + const adminToken = req.headers.get("x-admin-token"); + const secretToken = process.env["ADMIN_SECRET_TOKEN"]; + + if (!secretToken || adminToken !== secretToken) { + return new NextResponse(null, { + status: 401, + statusText: "Unauthorized access.", + }); + } + + try { + await generateAndSetNewSeedForModels(); + return new NextResponse( + JSON.stringify({ + message: + "Successfully updated seeds for models where the last revision had DEFAULT_SEED.", + }), + { status: 200 } + ); + } catch (error) { + console.error("An error occurred:", error); + return new NextResponse( + JSON.stringify({ + error: "An error occurred while updating seeds.", + }), + { status: 500 } + ); + } +} diff --git a/packages/hub/src/constants.ts b/packages/hub/src/constants.ts index 3be4715742..4555d4d32a 100644 --- a/packages/hub/src/constants.ts +++ b/packages/hub/src/constants.ts @@ -5,3 +5,5 @@ export const VERCEL_URL = process.env["NEXT_PUBLIC_VERCEL_URL"]; export const SAMPLE_COUNT_DEFAULT = 1000; + +export const DEFAULT_SEED = "DEFAULT_SEED"; diff --git a/packages/hub/src/graphql/queries/runSquiggle.ts b/packages/hub/src/graphql/queries/runSquiggle.ts index 6598de4f07..dd4a590f03 100644 --- a/packages/hub/src/graphql/queries/runSquiggle.ts +++ b/packages/hub/src/graphql/queries/runSquiggle.ts @@ -3,7 +3,7 @@ import crypto from "crypto"; import { SqProject, SqValue } from "@quri/squiggle-lang"; -import { SAMPLE_COUNT_DEFAULT } from "@/constants"; +import { DEFAULT_SEED, SAMPLE_COUNT_DEFAULT } from "@/constants"; import { builder } from "@/graphql/builder"; import { prisma } from "@/prisma"; @@ -83,7 +83,7 @@ export async function runSquiggle(code: string): Promise { const env = { sampleCount: SAMPLE_COUNT_DEFAULT, // int xyPointLength: 1000, // int - seed: "DEFAULT_SEED", + seed: DEFAULT_SEED, }; const project = SqProject.create({ environment: env }); From 02aa15c79116e8eff3af9106421904f0b6f0a907 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Mon, 19 Feb 2024 16:47:35 -0500 Subject: [PATCH 6/8] Add seed on squiggleContent, not on ModelRevision --- packages/hub/package.json | 1 + .../migration.sql | 3 --- .../migration.sql | 3 +++ packages/hub/prisma/schema.prisma | 3 +-- packages/hub/schema.graphql | 6 +++--- .../upgrade-versions/UpgradeVersionsPage.tsx | 1 + .../models/[owner]/[slug]/EditModelPage.tsx | 1 - .../[slug]/EditSquiggleSnippetModel.tsx | 8 +++++--- packages/hub/src/app/new/model/NewModel.tsx | 2 ++ .../mutations/createSquiggleSnippetModel.ts | 6 ++---- .../mutations/updateSquiggleSnippetModel.ts | 4 ++-- .../hub/src/graphql/types/ModelRevision.ts | 19 +++++++++++++++++-- 12 files changed, 37 insertions(+), 20 deletions(-) delete mode 100644 packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql create mode 100644 packages/hub/prisma/migrations/20240217215104_squiggle_snippet_seed/migration.sql diff --git a/packages/hub/package.json b/packages/hub/package.json index fd51912bca..769ab86415 100644 --- a/packages/hub/package.json +++ b/packages/hub/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "db:migrate": "PRISMA_HIDE_UPDATE_MESSAGE=1 prisma migrate deploy", + "db:reset": "PRISMA_HIDE_UPDATE_MESSAGE=1 prisma migrate reset", "dev": "next dev -p 3001", "start": "__NEXT_PRIVATE_PREBUNDLED_REACT=next next start", "gen:prisma": "PRISMA_HIDE_UPDATE_MESSAGE=1 prisma generate", diff --git a/packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql b/packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql deleted file mode 100644 index 5cf363523a..0000000000 --- a/packages/hub/prisma/migrations/20240217215104_model_revision_seed/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE "ModelRevision" ADD COLUMN "seed" TEXT DEFAULT 'DEFAULT_SEED'; -UPDATE "ModelRevision" SET "seed" = 'DEFAULT_SEED' WHERE "seed" IS NULL; -ALTER TABLE "ModelRevision" ALTER COLUMN "seed" SET NOT NULL; \ No newline at end of file diff --git a/packages/hub/prisma/migrations/20240217215104_squiggle_snippet_seed/migration.sql b/packages/hub/prisma/migrations/20240217215104_squiggle_snippet_seed/migration.sql new file mode 100644 index 0000000000..25b51cbf73 --- /dev/null +++ b/packages/hub/prisma/migrations/20240217215104_squiggle_snippet_seed/migration.sql @@ -0,0 +1,3 @@ +ALTER TABLE "SquiggleSnippet" ADD COLUMN "seed" TEXT DEFAULT 'DEFAULT_SEED'; +UPDATE "SquiggleSnippet" SET "seed" = 'DEFAULT_SEED' WHERE "seed" IS NULL; +ALTER TABLE "SquiggleSnippet" ALTER COLUMN "seed" SET NOT NULL; \ No newline at end of file diff --git a/packages/hub/prisma/schema.prisma b/packages/hub/prisma/schema.prisma index a423a3eed6..cdd6023fd6 100644 --- a/packages/hub/prisma/schema.prisma +++ b/packages/hub/prisma/schema.prisma @@ -224,8 +224,6 @@ model ModelRevision { // required by Prisma, but unused since `model` field should point at the same entity currentRevisionModel Model? @relation("CurrentRevision") - seed String @default("DEFAULT_SEED") - @@index([modelId]) } @@ -234,6 +232,7 @@ model SquiggleSnippet { code String version String + seed String revision ModelRevision? } diff --git a/packages/hub/schema.graphql b/packages/hub/schema.graphql index d4e22374a8..7b1eb05dad 100644 --- a/packages/hub/schema.graphql +++ b/packages/hub/schema.graphql @@ -193,7 +193,6 @@ type ModelRevision implements Node { id: ID! model: Model! relativeValuesExports: [RelativeValuesExport!]! - seed: String! } type ModelRevisionConnection { @@ -350,7 +349,7 @@ input MutationCreateSquiggleSnippetModelInput { isPrivate: Boolean """A unique seed, used for calculation""" - seed: String + seed: String! slug: String! version: String! } @@ -457,7 +456,6 @@ input MutationUpdateSquiggleSnippetModelInput { exports: [SquiggleModelExportInput!] owner: String! relativeValuesExports: [RelativeValuesExportInput!] - seed: String! slug: String! } @@ -672,11 +670,13 @@ interface SquiggleOutput { type SquiggleSnippet implements Node { code: String! id: ID! + seed: String! version: String! } input SquiggleSnippetContentInput { code: String! + seed: String! version: String! } diff --git a/packages/hub/src/app/admin/upgrade-versions/UpgradeVersionsPage.tsx b/packages/hub/src/app/admin/upgrade-versions/UpgradeVersionsPage.tsx index e02ee978c3..19ac93bb0a 100644 --- a/packages/hub/src/app/admin/upgrade-versions/UpgradeVersionsPage.tsx +++ b/packages/hub/src/app/admin/upgrade-versions/UpgradeVersionsPage.tsx @@ -44,6 +44,7 @@ const UpgradeableModel: FC<{ modelRef: UpgradeVersionsPage_Model$key }> = ({ id code version + seed } } } diff --git a/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx b/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx index c578518e9a..8aea85033c 100644 --- a/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx +++ b/packages/hub/src/app/models/[owner]/[slug]/EditModelPage.tsx @@ -22,7 +22,6 @@ export const EditModelPage: FC<{ ... on Model { id currentRevision { - seed content { __typename } diff --git a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx index 89d31e2185..3b8614a839 100644 --- a/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx +++ b/packages/hub/src/app/models/[owner]/[slug]/EditSquiggleSnippetModel.tsx @@ -146,13 +146,13 @@ export const EditSquiggleSnippetModel: FC = ({ } currentRevision { id - seed content { __typename ... on SquiggleSnippet { id code version + seed } } exports { @@ -185,6 +185,8 @@ export const EditSquiggleSnippetModel: FC = ({ "SquiggleSnippet" ); + const seed = content.seed; + const initialFormValues: SquiggleSnippetFormShape = useMemo(() => { return { code: content.code, @@ -234,13 +236,13 @@ export const EditSquiggleSnippetModel: FC = ({ content: { code: formData.code, version, + seed: seed, }, relativeValuesExports: formData.relativeValuesExports, exports: formData.exports, comment: extraData?.comment, slug: model.slug, owner: model.owner.slug, - seed: revision.seed, }, }), confirmation: "Saved", @@ -404,7 +406,7 @@ export const EditSquiggleSnippetModel: FC = ({ playgroundProps.environment = { sampleCount: SAMPLE_COUNT_DEFAULT, - seed: model.currentRevision.seed, + seed: seed, }; if ( diff --git a/packages/hub/src/app/new/model/NewModel.tsx b/packages/hub/src/app/new/model/NewModel.tsx index fe961efb9e..14c5ffc5fe 100644 --- a/packages/hub/src/app/new/model/NewModel.tsx +++ b/packages/hub/src/app/new/model/NewModel.tsx @@ -6,6 +6,7 @@ import { FormProvider } from "react-hook-form"; import { useLazyLoadQuery } from "react-relay"; import { graphql } from "relay-runtime"; +import { generateSeed } from "@quri/squiggle-lang"; import { Button, CheckboxFormField } from "@quri/ui"; import { defaultSquiggleVersion } from "@quri/versioned-squiggle-components"; @@ -102,6 +103,7 @@ export const NewModel: FC = () => { isPrivate: data.isPrivate, code: defaultCode, version: defaultSquiggleVersion, + seed: generateSeed(), }, }), onCompleted: (result) => { diff --git a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts index 4f17b1181e..45381a4709 100644 --- a/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/createSquiggleSnippetModel.ts @@ -1,7 +1,5 @@ import { ZodError } from "zod"; -import { generateSeed } from "@quri/squiggle-lang"; - import { builder } from "@/graphql/builder"; import { prisma } from "@/prisma"; @@ -39,7 +37,7 @@ builder.mutationField("createSquiggleSnippetModel", (t) => description: "Defaults to false", }), seed: t.input.string({ - required: false, + required: true, description: "A unique seed, used for calculation", }), }, @@ -73,6 +71,7 @@ builder.mutationField("createSquiggleSnippetModel", (t) => create: { code: input.code, version: input.version, + seed: input.seed, }, }, author: { @@ -84,7 +83,6 @@ builder.mutationField("createSquiggleSnippetModel", (t) => id: model.id, }, }, - seed: generateSeed(), }, }); diff --git a/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts b/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts index 2c44e2dee2..c396a1ad5d 100644 --- a/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts +++ b/packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts @@ -35,6 +35,7 @@ const SquiggleSnippetContentInput = builder.inputType( fields: (t) => ({ code: t.string({ required: true }), version: t.string({ required: true }), + seed: t.string({ required: true }), }), } ); @@ -70,7 +71,6 @@ builder.mutationField("updateSquiggleSnippetModel", (t) => required: true, }), comment: t.input.string(), - seed: t.input.string({ required: true }), }, resolve: async (_, { input }, { session }) => { const existingModel = await getWriteableModel({ @@ -145,11 +145,11 @@ builder.mutationField("updateSquiggleSnippetModel", (t) => create: { code: input.content.code, version: input.content.version, + seed: input.content.seed, }, }, contentType: "SquiggleSnippet", comment: input.comment ?? "", - seed: input.seed, model: { connect: { id: existingModel.id }, }, diff --git a/packages/hub/src/graphql/types/ModelRevision.ts b/packages/hub/src/graphql/types/ModelRevision.ts index 7bffd3d7a9..2155cd27f5 100644 --- a/packages/hub/src/graphql/types/ModelRevision.ts +++ b/packages/hub/src/graphql/types/ModelRevision.ts @@ -1,3 +1,5 @@ +import { UnionRef } from "@pothos/core"; + import { builder } from "@/graphql/builder"; import { prisma } from "@/prisma"; @@ -9,11 +11,25 @@ export const SquiggleSnippet = builder.prismaNode("SquiggleSnippet", { fields: (t) => ({ code: t.exposeString("code"), version: t.exposeString("version"), + seed: t.exposeString("seed"), }), }); // TODO - turn into interface? -export const ModelContent = builder.unionType("ModelContent", { +export const ModelContent: UnionRef< + { + id: string; + code: string; + version: string; + seed: string; + }, + { + id: string; + code: string; + version: string; + seed: string; + } +> = builder.unionType("ModelContent", { types: [SquiggleSnippet], resolveType: () => SquiggleSnippet, }); @@ -42,7 +58,6 @@ export const ModelRevision = builder.prismaNode("ModelRevision", { model: t.relation("model"), author: t.relation("author", { nullable: true }), comment: t.exposeString("comment"), - seed: t.exposeString("seed"), content: t.field({ type: ModelContent, select: { squiggleSnippet: true }, From f79cee265aed1b5392fce6bcb1a573848ecbb455 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 20 Feb 2024 08:54:43 -0500 Subject: [PATCH 7/8] Updated updateModelSeeds fn --- .../hub/src/app/api/updateModelSeeds/route.ts | 39 ++++++++++++------- .../mutations/adminUpdateModelVersion.ts | 2 +- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/hub/src/app/api/updateModelSeeds/route.ts b/packages/hub/src/app/api/updateModelSeeds/route.ts index 9affa1d423..b454ccc1dd 100644 --- a/packages/hub/src/app/api/updateModelSeeds/route.ts +++ b/packages/hub/src/app/api/updateModelSeeds/route.ts @@ -3,19 +3,20 @@ import { NextRequest, NextResponse } from "next/server"; import { generateSeed } from "@quri/squiggle-lang"; -import { DEFAULT_SEED } from "@/constants"; - const prisma = new PrismaClient(); -async function generateAndSetNewSeedForModels() { - // Find all models +async function updateSquiggleSnippetsSeedForModels() { + // Retrieve all models const models = await prisma.model.findMany({ include: { revisions: { + include: { + squiggleSnippet: true, + }, orderBy: { createdAt: "desc", }, - take: 1, // Only include the last revision + take: 1, }, }, }); @@ -23,16 +24,26 @@ async function generateAndSetNewSeedForModels() { for (const model of models) { const lastRevision = model.revisions[0]; - // Check if the last revision has the DEFAULT_SEED - if (lastRevision && lastRevision.seed === DEFAULT_SEED) { - // Generate a random seed for the model + // Check if the last revision's SquiggleSnippet has the DEFAULT_SEED + if ( + lastRevision.squiggleSnippet && + lastRevision.squiggleSnippet.seed === "DEFAULT_SEED" + ) { const newSeed = generateSeed(); - // Update seed for all revisions of the current model - await prisma.modelRevision.updateMany({ - where: { modelId: model.id }, - data: { seed: newSeed }, - }); + // Update all SquiggleSnippets for all revisions of the current model + for (const revision of model.revisions) { + if (revision.squiggleSnippet) { + await prisma.squiggleSnippet.update({ + where: { + id: revision.squiggleSnippet.id, + }, + data: { + seed: newSeed, + }, + }); + } + } } } } @@ -49,7 +60,7 @@ export async function POST(req: NextRequest) { } try { - await generateAndSetNewSeedForModels(); + await updateSquiggleSnippetsSeedForModels(); return new NextResponse( JSON.stringify({ message: diff --git a/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts b/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts index 0d28cb1133..b7fdbd75d7 100644 --- a/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts +++ b/packages/hub/src/graphql/mutations/adminUpdateModelVersion.ts @@ -54,6 +54,7 @@ builder.mutationField("adminUpdateModelVersion", (t) => create: { code: model.currentRevision.squiggleSnippet.code, version: input.version, + seed: model.currentRevision.squiggleSnippet.seed, }, }, contentType: "SquiggleSnippet", @@ -64,7 +65,6 @@ builder.mutationField("adminUpdateModelVersion", (t) => connect: { email: self.email! }, }, comment: `Automated upgrade from ${model.currentRevision.squiggleSnippet.version} to ${input.version}`, - seed: model.currentRevision.seed, relativeValuesExports: { createMany: { data: model.currentRevision.relativeValuesExports.map( From 56ea454b4baa252b23fee6d94a2f5666a6d5d231 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Mon, 26 Feb 2024 15:22:23 -0800 Subject: [PATCH 8/8] Undid UnionRef type --- packages/hub/src/graphql/types/ModelRevision.ts | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/packages/hub/src/graphql/types/ModelRevision.ts b/packages/hub/src/graphql/types/ModelRevision.ts index 2155cd27f5..7baed3f336 100644 --- a/packages/hub/src/graphql/types/ModelRevision.ts +++ b/packages/hub/src/graphql/types/ModelRevision.ts @@ -1,5 +1,3 @@ -import { UnionRef } from "@pothos/core"; - import { builder } from "@/graphql/builder"; import { prisma } from "@/prisma"; @@ -16,20 +14,7 @@ export const SquiggleSnippet = builder.prismaNode("SquiggleSnippet", { }); // TODO - turn into interface? -export const ModelContent: UnionRef< - { - id: string; - code: string; - version: string; - seed: string; - }, - { - id: string; - code: string; - version: string; - seed: string; - } -> = builder.unionType("ModelContent", { +export const ModelContent = builder.unionType("ModelContent", { types: [SquiggleSnippet], resolveType: () => SquiggleSnippet, });