Skip to content

Commit d40dfbe

Browse files
authored
Route to register aiModel (#8127)
* Route to register aiModel * update schema with new model categories. skip id taken check for the moment * bump schema version * add uniqueness checks for name + id. add sql evolution for enum values * no transaction block in evolution * delete incompatible models in reversion
1 parent 684a588 commit d40dfbe

File tree

9 files changed

+67
-4
lines changed

9 files changed

+67
-4
lines changed

MIGRATIONS.unreleased.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ User-facing changes are documented in the [changelog](CHANGELOG.released.md).
1212

1313
- [121-worker-name.sql](conf/evolutions/121-worker-name.sql)
1414
- [122-resolution-to-mag.sql](conf/evolutions/122-resolution-to-mag.sql)
15+
- [123-more-model-categories.sql](conf/evolutions/123-more-model-categories.sql)

app/controllers/AiModelController.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ object UpdateAiModelParameters {
5757
implicit val jsonFormat: OFormat[UpdateAiModelParameters] = Json.format[UpdateAiModelParameters]
5858
}
5959

60+
case class RegisterAiModelParameters(id: ObjectId, // must be a valid MongoDB ObjectId
61+
dataStoreName: String,
62+
name: String,
63+
comment: Option[String],
64+
category: Option[AiModelCategory])
65+
66+
object RegisterAiModelParameters {
67+
implicit val jsonFormat: OFormat[RegisterAiModelParameters] = Json.format[RegisterAiModelParameters]
68+
}
69+
6070
class AiModelController @Inject()(
6171
aiModelDAO: AiModelDAO,
6272
aiModelService: AiModelService,
@@ -209,6 +219,28 @@ class AiModelController @Inject()(
209219
} yield Ok(jsResult)
210220
}
211221

222+
def registerAiModel: Action[RegisterAiModelParameters] =
223+
sil.SecuredAction.async(validateJson[RegisterAiModelParameters]) { implicit request =>
224+
for {
225+
_ <- userService.assertIsSuperUser(request.identity)
226+
_ <- dataStoreDAO.findOneByName(request.body.dataStoreName) ?~> "dataStore.notFound"
227+
_ <- aiModelDAO.findOne(request.body.id).reverse ?~> "aiModel.id.taken"
228+
_ <- aiModelDAO.findOneByName(request.body.name).reverse ?~> "aiModel.name.taken"
229+
_ <- aiModelDAO.insertOne(
230+
AiModel(
231+
request.body.id,
232+
_organization = request.identity._organization,
233+
request.body.dataStoreName,
234+
request.identity._id,
235+
None,
236+
List.empty,
237+
request.body.name,
238+
request.body.comment,
239+
request.body.category
240+
))
241+
} yield Ok
242+
}
243+
212244
def deleteAiModel(aiModelId: String): Action[AnyContent] =
213245
sil.SecuredAction.async { implicit request =>
214246
for {

app/models/aimodels/AiModel.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,11 @@ class AiModelDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContext)
144144
q"UPDATE webknossos.aiModels SET name = ${a.name}, comment = ${a.comment}, modified = ${a.modified} WHERE _id = ${a._id}".asUpdate)
145145
} yield ()
146146

147+
def findOneByName(name: String)(implicit ctx: DBAccessContext): Fox[AiModel] =
148+
for {
149+
accessQuery <- readAccessQuery
150+
r <- run(q"SELECT $columns FROM $existingCollectionName WHERE name = $name AND $accessQuery".as[AimodelsRow])
151+
parsed <- parseFirst(r, name)
152+
} yield parsed
153+
147154
}

app/models/aimodels/AiModelCategory.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import com.scalableminds.util.enumeration.ExtendedEnumeration
44

55
object AiModelCategory extends ExtendedEnumeration {
66
type AiModelCategory = Value
7-
val em_neurons, em_nuclei = Value
7+
val em_neurons, em_nuclei, em_synapses, em_neuron_types, em_cell_organelles = Value
88
}

app/utils/sql/SQLDAO.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ abstract class SQLDAO[C, R, X <: AbstractTable[R]] @Inject()(sqlClient: SqlClien
4747
case Some(r) =>
4848
parse(r) ?~> ("sql: could not parse database row for object" + id)
4949
case _ =>
50-
Fox.failure("sql: could not find object " + id)
50+
Fox.empty
5151
}.flatten
5252

5353
@nowarn // suppress warning about unused implicit ctx, as it is used in subclasses
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
-- no transaction here, since ALTER TYPE ... ADD cannot run inside a transaction block
3+
4+
do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 122, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql;
5+
6+
ALTER TYPE webknossos.AI_MODEL_CATEGORY ADD VALUE 'em_synapses';
7+
ALTER TYPE webknossos.AI_MODEL_CATEGORY ADD VALUE 'em_neuron_types';
8+
ALTER TYPE webknossos.AI_MODEL_CATEGORY ADD VALUE 'em_cell_organelles';
9+
10+
UPDATE webknossos.releaseInformation SET schemaVersion = 123;
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
START TRANSACTION;
2+
3+
do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 123, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql;
4+
5+
-- removing enum values is not supported in postgres, see https://www.postgresql.org/docs/current/datatype-enum.html#DATATYPE-ENUM-IMPLEMENTATION-DETAILS
6+
7+
UPDATE webknossos.aiModels SET isDeleted = TRUE WHERE category IN ('em_synapses', 'em_neuron_types', 'em_cell_organelles');
8+
9+
UPDATE webknossos.releaseInformation SET schemaVersion = 122;
10+
11+
COMMIT TRANSACTION;

conf/webknossos.latest.routes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ POST /aiModels/inferences/runInference
283283
GET /aiModels/inferences/:id controllers.AiModelController.readAiInferenceInfo(id: String)
284284
GET /aiModels/inferences controllers.AiModelController.listAiInferences
285285
GET /aiModels controllers.AiModelController.listAiModels
286+
POST /aiModels/register controllers.AiModelController.registerAiModel
286287
GET /aiModels/:id controllers.AiModelController.readAiModelInfo(id: String)
287288
PUT /aiModels/:id controllers.AiModelController.updateAiModelInfo(id: String)
288289
DELETE /aiModels/:id controllers.AiModelController.deleteAiModel(id: String)

tools/postgres/schema.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ CREATE TABLE webknossos.releaseInformation (
2020
schemaVersion BIGINT NOT NULL
2121
);
2222

23-
INSERT INTO webknossos.releaseInformation(schemaVersion) values(122);
23+
INSERT INTO webknossos.releaseInformation(schemaVersion) values(123);
2424
COMMIT TRANSACTION;
2525

2626

@@ -546,7 +546,7 @@ CREATE TABLE webknossos.emailVerificationKeys(
546546
isUsed BOOLEAN NOT NULL DEFAULT false
547547
);
548548

549-
CREATE TYPE webknossos.AI_MODEL_CATEGORY AS ENUM ('em_neurons', 'em_nuclei');
549+
CREATE TYPE webknossos.AI_MODEL_CATEGORY AS ENUM ('em_neurons', 'em_nuclei', 'em_synapses', 'em_neuron_types', 'em_cell_organelles');
550550

551551
CREATE TABLE webknossos.aiModels(
552552
_id CHAR(24) PRIMARY KEY,

0 commit comments

Comments
 (0)