-
Notifications
You must be signed in to change notification settings - Fork 29
Route to register aiModel #8127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1c23368
e6cc396
1633aa3
4aa7896
95bab3f
579f3d0
d41e7b1
3eb81d8
4987297
d29f0d6
03a4ea3
f76ec20
6ae4355
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,16 @@ object UpdateAiModelParameters { | |
implicit val jsonFormat: OFormat[UpdateAiModelParameters] = Json.format[UpdateAiModelParameters] | ||
} | ||
|
||
case class RegisterAiModelParameters(id: ObjectId, // must be a valid MongoDB ObjectId | ||
dataStoreName: String, | ||
name: String, | ||
comment: Option[String], | ||
category: Option[AiModelCategory]) | ||
|
||
object RegisterAiModelParameters { | ||
implicit val jsonFormat: OFormat[RegisterAiModelParameters] = Json.format[RegisterAiModelParameters] | ||
} | ||
|
||
class AiModelController @Inject()( | ||
aiModelDAO: AiModelDAO, | ||
aiModelService: AiModelService, | ||
|
@@ -209,6 +219,28 @@ class AiModelController @Inject()( | |
} yield Ok(jsResult) | ||
} | ||
|
||
def registerAiModel: Action[RegisterAiModelParameters] = | ||
sil.SecuredAction.async(validateJson[RegisterAiModelParameters]) { implicit request => | ||
for { | ||
_ <- userService.assertIsSuperUser(request.identity) | ||
_ <- dataStoreDAO.findOneByName(request.body.dataStoreName) ?~> "dataStore.notFound" | ||
_ <- aiModelDAO.findOne(request.body.id).reverse ?~> "aiModel.id.taken" | ||
_ <- aiModelDAO.findOneByName(request.body.name).reverse ?~> "aiModel.name.taken" | ||
_ <- aiModelDAO.insertOne( | ||
AiModel( | ||
request.body.id, | ||
_organization = request.identity._organization, | ||
request.body.dataStoreName, | ||
request.identity._id, | ||
None, | ||
List.empty, | ||
request.body.name, | ||
request.body.comment, | ||
request.body.category | ||
)) | ||
} yield Ok | ||
} | ||
Comment on lines
+241
to
+242
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Return the created model in the response. For consistency with other controller methods, return the created model instead of an empty Ok. - } yield Ok
+ newModel <- aiModelDAO.findOne(request.body.id) ?~> "aiModel.notFound"
+ jsResult <- aiModelService.publicWrites(newModel)
+ } yield Ok(jsResult)
Comment on lines
+222
to
+242
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add missing validations and improve error handling. The method should validate:
def registerAiModel: Action[RegisterAiModelParameters] =
sil.SecuredAction.async(validateJson[RegisterAiModelParameters]) { implicit request =>
for {
_ <- userService.assertIsSuperUser(request.identity)
+ _ <- bool2Fox(Set("localhost", "webknossos.org").contains(request.body.dataStoreName)) ?~> "dataStore.invalid"
+ _ <- request.body.category.traverse(cat => bool2Fox(AiModelCategory.isValidEMType(cat)) ?~> "category.invalid")
_ <- dataStoreDAO.findOneByName(request.body.dataStoreName) ?~> "dataStore.notFound"
|
||
|
||
def deleteAiModel(aiModelId: String): Action[AnyContent] = | ||
sil.SecuredAction.async { implicit request => | ||
for { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,7 @@ abstract class SQLDAO[C, R, X <: AbstractTable[R]] @Inject()(sqlClient: SqlClien | |
case Some(r) => | ||
parse(r) ?~> ("sql: could not parse database row for object" + id) | ||
case _ => | ||
Fox.failure("sql: could not find object " + id) | ||
Fox.empty | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We used Fox.empty already in many overwriting findOnes, but not this one in the superclass. I don’t think it will hurt, though, and this way I can distinguish between error and empty downstream. |
||
}.flatten | ||
|
||
@nowarn // suppress warning about unused implicit ctx, as it is used in subclasses | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,11 @@ | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
-- no transaction here, since ALTER TYPE ... ADD cannot run inside a transaction block | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 122, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql; | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Strengthen the schema version assertion. While the version check is good, it could be more robust by handling NULL values and providing a more descriptive error message. -do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 122, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql;
+do $$
+declare
+ current_version int;
+begin
+ SELECT schemaVersion INTO current_version FROM webknossos.releaseInformation;
+ ASSERT current_version IS NOT NULL AND current_version = 122,
+ 'Expected schema version 122, but found ' || COALESCE(current_version::text, 'NULL');
+end; $$ LANGUAGE plpgsql; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
ALTER TYPE webknossos.AI_MODEL_CATEGORY ADD VALUE 'em_synapses'; | ||||||||||||||||||||||||||||||||||
ALTER TYPE webknossos.AI_MODEL_CATEGORY ADD VALUE 'em_neuron_types'; | ||||||||||||||||||||||||||||||||||
ALTER TYPE webknossos.AI_MODEL_CATEGORY ADD VALUE 'em_cell_organelles'; | ||||||||||||||||||||||||||||||||||
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification These enum values already exist in schema.sql - migration will fail The values 'em_synapses', 'em_neuron_types', and 'em_cell_organelles' are already defined in
🔗 Analysis chainVerify enum values don't already exist and consider rollback strategy. The ALTER TYPE commands look correct, but we should verify these values don't already exist to prevent errors. Also, consider documenting the rollback strategy since enum values cannot be easily removed. Consider adding a comment block documenting the rollback strategy, as removing enum values requires careful handling: -- Rollback strategy:
-- 1. Create a new enum type without these values
-- 2. Update all columns to use the new type
-- 3. Drop the old type 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Check if any of the new enum values already exist in the database
# Test: Search for existing enum definitions or usage
rg -i "em_synapses|em_neuron_types|em_cell_organelles" --type sql
# Test: Look for any previous migrations that might have added these values
fd -e sql | xargs grep -l "ALTER TYPE.*AI_MODEL_CATEGORY.*ADD VALUE"
Length of output: 688 |
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
UPDATE webknossos.releaseInformation SET schemaVersion = 123; | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add verification for schema version update. The schema version update should verify that exactly one row was updated to ensure the migration completed successfully. -UPDATE webknossos.releaseInformation SET schemaVersion = 123;
+DO $$
+DECLARE
+ rows_affected int;
+BEGIN
+ WITH updated AS (
+ UPDATE webknossos.releaseInformation
+ SET schemaVersion = 123
+ WHERE schemaVersion = 122
+ RETURNING *
+ )
+ SELECT COUNT(*) INTO rows_affected FROM updated;
+
+ ASSERT rows_affected = 1,
+ 'Expected to update exactly one row, but updated ' || rows_affected || ' rows';
+END $$; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
START TRANSACTION; | ||
|
||
do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 123, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql; | ||
|
||
-- removing enum values is not supported in postgres, see https://www.postgresql.org/docs/current/datatype-enum.html#DATATYPE-ENUM-IMPLEMENTATION-DETAILS | ||
fm3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
UPDATE webknossos.aiModels SET isDeleted = TRUE WHERE category IN ('em_synapses', 'em_neuron_types', 'em_cell_organelles'); | ||
|
||
UPDATE webknossos.releaseInformation SET schemaVersion = 122; | ||
|
||
COMMIT TRANSACTION; |
Uh oh!
There was an error while loading. Please reload this page.