You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@submarine.apache.org by pi...@apache.org on 2022/06/10 14:38:20 UTC

[submarine] branch master updated: SUBMARINE-1277. Refactor rest logic

This is an automated email from the ASF dual-hosted git repository.

pingsutw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git


The following commit(s) were added to refs/heads/master by this push:
     new 595ff75d SUBMARINE-1277. Refactor rest logic
595ff75d is described below

commit 595ff75d781bb27aea3ee03c8f597c9db4e2cc78
Author: jeff-901 <b0...@ntu.edu.tw>
AuthorDate: Tue May 24 11:54:54 2022 +0800

    SUBMARINE-1277. Refactor rest logic
    
    ### What is this PR for?
    Move logic of rest to manager
    
    ### What type of PR is it?
    Refactoring
    
    ### Todos
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-1277
    
    ### How should this be tested?
    
    ### Screenshots (if appropriate)
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? No
    
    Author: jeff-901 <b0...@ntu.edu.tw>
    
    Signed-off-by: Kevin <pi...@apache.org>
    
    Closes #962 from jeff-901/SUBMARINE-1277 and squashes the following commits:
    
    3593e146 [jeff-901] fix logic
    03c09516 [jeff-901] refactor rest logic
---
 .../server/manager/ModelVersionManager.java        | 257 +++++++++++++++++++++
 .../server/manager/RegisteredModelManager.java     | 227 ++++++++++++++++++
 .../submarine/server/rest/ModelVersionRestApi.java | 127 +---------
 .../server/rest/RegisteredModelRestApi.java        | 119 +---------
 4 files changed, 506 insertions(+), 224 deletions(-)

diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/manager/ModelVersionManager.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/manager/ModelVersionManager.java
new file mode 100644
index 00000000..e25ab284
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/manager/ModelVersionManager.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.manager;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.json.JSONObject;
+import java.util.List;
+import javax.ws.rs.core.Response;
+
+import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.database.model.entities.ModelVersionEntity;
+import org.apache.submarine.server.database.model.entities.ModelVersionTagEntity;
+import org.apache.submarine.server.database.model.service.ModelVersionService;
+import org.apache.submarine.server.database.model.service.ModelVersionTagService;
+import org.apache.submarine.server.s3.Client;
+
+/**
+ * ModelVersion manager.
+ */
+public class ModelVersionManager {
+  private static volatile ModelVersionManager manager;
+
+  /* Model version service */
+  private final ModelVersionService modelVersionService;
+
+  /* Model version tag service */
+  private final ModelVersionTagService modelVersionTagService;
+
+  private final Client s3Client;
+
+  /**
+   * Get the singleton instance.
+   *
+   * @return object
+   */
+  public static ModelVersionManager getInstance() {
+    if (manager == null) {
+      synchronized (ModelVersionManager.class) {
+        if (manager == null) {
+          manager = new ModelVersionManager(new ModelVersionService(), new ModelVersionTagService(),
+            new Client());
+        }
+      }
+    }
+    return manager;
+  }
+
+  @VisibleForTesting
+  protected ModelVersionManager(ModelVersionService modelVersionService,
+                                ModelVersionTagService modelVersionTagService, Client s3Client) {
+    this.modelVersionService = modelVersionService;
+    this.modelVersionTagService = modelVersionTagService;
+    this.s3Client = s3Client;
+  }
+
+  /**
+   * Create a model version.
+   *
+   * @param entity registered model entity
+   * example: {
+   *   "name": "example_name"
+   *   "experimentId" : "4d4d02f06f6f437fa29e1ee8a9276d87"
+   *   "userId": ""
+   *   "description" : "example_description"
+   *   "tags": ["123", "456"]
+   * }
+   * @param baseDir artifact base directory
+   * example: "experiment/experiment-1643015349312-0001/1"
+   */
+  public void createModelVersion(ModelVersionEntity entity, String baseDir) throws SubmarineRuntimeException {
+    String res = new String(s3Client.downloadArtifact(
+        String.format("%s/description.json", baseDir)));
+    JSONObject description = new JSONObject(res);
+    String modelType =  description.get("model_type").toString();
+    String id = description.get("id").toString();
+    entity.setId(id);
+    entity.setModelType(modelType);
+
+    int version = modelVersionService.selectAllVersions(entity.getName()).stream().mapToInt(
+        ModelVersionEntity::getVersion
+    ).max().orElse(0) + 1;
+
+    entity.setVersion(version);
+    modelVersionService.insert(entity);
+
+    // the directory of storing a single model must be unique for serving
+    String uniqueModelPath = String.format("%s-%d-%s", entity.getName(), version, id);
+
+    // copy artifacts
+    s3Client.listAllObjects(baseDir).forEach(s -> {
+      String relativePath = s.substring(String.format("%s/", baseDir).length());
+      s3Client.copyArtifact(String.format("registry/%s/%s/%d/%s", uniqueModelPath,
+          entity.getName(), entity.getVersion(), relativePath), s);
+    });
+  }
+
+  /**
+   * Get detailed info about the model version by name and version.
+   *
+   * @param name    model version's name
+   * @param version model version's version
+   * @return detailed info about the model version
+   */
+  public ModelVersionEntity getModelVersion(String name, Integer version) throws SubmarineRuntimeException {
+    return modelVersionService.selectWithTag(name, version);
+  }
+
+  /**
+   * List all model versions under same registered model name.
+   *
+   * @param name registered model name
+   * @return model version list
+   */
+  public List<ModelVersionEntity> listModelVersions(String name) throws SubmarineRuntimeException {
+    return modelVersionService.selectAllVersions(name);
+  }
+
+  /**
+   * Update the model version.
+   *
+   * @param entity model version entity
+   * example: {
+   *   'name': 'example_name',
+   *   'version': 1,
+   *   'description': 'new_description',
+   *   'currentStage': 'production',
+   *   'dataset': 'new_dataset'
+   * }
+   */
+  public void updateModelVersion(ModelVersionEntity entity) throws SubmarineRuntimeException {
+    checkModelVersion(entity);
+    modelVersionService.update(entity);
+  }
+
+  /**
+   * Delete the model version with model version name and version.
+   *
+   * @param name    model version's name
+   * @param version model version's version
+   */
+  public void deleteModelVersion(String name, Integer version) throws SubmarineRuntimeException {
+    ModelVersionEntity spec = modelVersionService.select(name, version);
+    s3Client.deleteArtifactsByModelVersion(name, version, spec.getId());
+    modelVersionService.delete(name, version);
+  }
+
+
+  /**
+   * Create a model version tag.
+   *
+   * @param name    model version's name
+   * @param version model version's version
+   * @param tag     tag name
+   */
+  public void createModelVersionTag(String name, String version, String tag)
+      throws SubmarineRuntimeException {
+    checkModelVersionTag(name, version, tag);
+    ModelVersionTagEntity modelVersionTag = new ModelVersionTagEntity();
+    modelVersionTag.setName(name);
+    modelVersionTag.setVersion(Integer.parseInt(version));
+    modelVersionTag.setTag(tag);
+    modelVersionTagService.insert(modelVersionTag);
+  }
+
+  /**
+   * Delete a model version tag.
+   *
+   * @param name    model version's name
+   * @param version model version's version
+   * @param tag     tag name
+   */
+  public void deleteModelVersionTag(String name, String version, String tag)
+      throws SubmarineRuntimeException {
+    checkModelVersionTag(name, version, tag);
+    ModelVersionTagEntity modelVersionTag = new ModelVersionTagEntity();
+    modelVersionTag.setName(name);
+    modelVersionTag.setVersion(Integer.parseInt(version));
+    modelVersionTag.setTag(tag);
+    modelVersionTagService.delete(modelVersionTag);
+  }
+
+  /**
+   * Check if model version tag is valid.
+   *
+   * @param name    model version's name
+   * @param version model version's version
+   * @param tag     tag name
+   */
+  private void checkModelVersionTag(String name, String version, String tag) {
+    if (name.equals("")){
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Model version's name is null.");
+    }
+    if (version.equals("")) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Model version's version is null.");
+    }
+    int versionNum;
+    try {
+      versionNum = Integer.parseInt(version);
+      if (versionNum < 1){
+        throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+            "Invalid. Model version's version must be bigger than 0.");
+      }
+    } catch (NumberFormatException e){
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Model version's version must be an integer.");
+    }
+    if (tag.equals("")) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Tag name is null.");
+    }
+    ModelVersionEntity modelVersion = modelVersionService.select(name,
+        versionNum);
+    if (modelVersion == null){
+      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
+          "Invalid. Model version " + name + " version " + versionNum + " is not existed.");
+    }
+  }
+
+  private void checkModelVersion(ModelVersionEntity entity) {
+    if (entity == null) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Model version entity object is null.");
+    }
+    if (entity.getName() == null || entity.getName().equals("")) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Model version's name is null.");
+    }
+    if (entity.getVersion() == null) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Model version's version is null.");
+    }
+    ModelVersionEntity modelVersion = modelVersionService.select(entity.getName(), entity.getVersion());
+    if (modelVersion == null) {
+      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
+          "Invalid. Model version entity with same name and version is not existed.");
+    }
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/manager/RegisteredModelManager.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/manager/RegisteredModelManager.java
new file mode 100644
index 00000000..d2d5890d
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/manager/RegisteredModelManager.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.manager;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.util.List;
+import javax.ws.rs.core.Response;
+
+import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.database.model.entities.ModelVersionEntity;
+import org.apache.submarine.server.database.model.entities.RegisteredModelEntity;
+import org.apache.submarine.server.database.model.entities.RegisteredModelTagEntity;
+import org.apache.submarine.server.database.model.service.ModelVersionService;
+import org.apache.submarine.server.database.model.service.RegisteredModelService;
+
+import org.apache.submarine.server.database.model.service.RegisteredModelTagService;
+import org.apache.submarine.server.s3.Client;
+
+/**
+ * Registered model manager.
+ */
+public class RegisteredModelManager {
+  private static volatile RegisteredModelManager manager;
+  /* Registered model service */
+  private final RegisteredModelService registeredModelService;
+
+  /* Model version service */
+  private final ModelVersionService modelVersionService;
+
+  /* Registered model tag service */
+  private final RegisteredModelTagService registeredModelTagService;
+
+  private final Client s3Client;
+
+  /**
+   * Get the singleton instance.
+   *
+   * @return object
+   */
+  public static RegisteredModelManager getInstance() {
+    if (manager == null) {
+      synchronized (RegisteredModelManager.class) {
+        if (manager == null) {
+          manager = new RegisteredModelManager(new RegisteredModelService(), new ModelVersionService(),
+              new RegisteredModelTagService(), new Client());
+        }
+      }
+    }
+    return manager;
+  }
+
+  @VisibleForTesting
+  protected RegisteredModelManager(RegisteredModelService registeredModelService,
+      ModelVersionService modelVersionService, RegisteredModelTagService registeredModelTagService,
+      Client s3Client) {
+    this.registeredModelService = registeredModelService;
+    this.modelVersionService = modelVersionService;
+    this.registeredModelTagService = registeredModelTagService;
+    this.s3Client = s3Client;
+  }
+
+  /**
+   * Create registered model.
+   *
+   * @param entity spec
+   */
+
+  public void createRegisteredModel(RegisteredModelEntity entity) throws SubmarineRuntimeException {
+    checkRegisteredModel(entity);
+    registeredModelService.insert(entity);
+  }
+
+  /**
+   * Get detailed info about the registered model by registered model name.
+   *
+   * @param name registered model name
+   * @return detailed info about the registered model
+   */
+  public RegisteredModelEntity getRegisteredModel(String name) throws SubmarineRuntimeException {
+    return registeredModelService.selectWithTag(name);
+  }
+
+  /**
+   * List registered models.
+   *
+   * @return list
+   */
+  public List<RegisteredModelEntity> listRegisteredModels() throws SubmarineRuntimeException {
+    return registeredModelService.selectAll();
+  }
+
+  /**
+   * Update the registered model with registered model name.
+   *
+   * @param name   old registered model name
+   * @param entity registered model entity
+   */
+  public void updateRegisteredModel(String name, RegisteredModelEntity entity)
+      throws SubmarineRuntimeException {
+    RegisteredModelEntity oldRegisteredModelEntity = registeredModelService.select(name);
+    if (oldRegisteredModelEntity == null) {
+      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
+        "Invalid. Registered model " + name + " is not existed.");
+    }
+    checkRegisteredModel(entity);
+    if (!name.equals(entity.getName())) {
+      registeredModelService.rename(name, entity.getName());
+    }
+    registeredModelService.update(entity);
+  }
+
+  /**
+   * Delete the registered model with registered model name.
+   *
+   * @param name registered model name
+   */
+  public void deleteRegisteredModel(String name) throws SubmarineRuntimeException {
+    List<ModelVersionEntity> modelVersions = modelVersionService.selectAllVersions(name);
+    modelVersions.forEach(modelVersion -> {
+      String stage = modelVersion.getCurrentStage();
+      if (stage.equals("Production")) {
+        throw new SubmarineRuntimeException(Response.Status.NOT_ACCEPTABLE.getStatusCode(),
+            "Invalid. Some version of models are in the production stage");
+      }
+    });
+    deleteModelInS3(modelVersions);
+    registeredModelService.delete(name);
+  }
+
+  /**
+   * Create a registered model tag.
+   *
+   * @param name registered model name
+   * @param tag  tag name
+   */
+  public void createRegisteredModelTag(String name, String tag) throws SubmarineRuntimeException {
+    checkRegisteredModelTag(name, tag);
+    RegisteredModelTagEntity registeredModelTag = new RegisteredModelTagEntity();
+    registeredModelTag.setName(name);
+    registeredModelTag.setTag(tag);
+    registeredModelTagService.insert(registeredModelTag);
+  }
+
+  /**
+   * Delete a registered model tag.
+   *
+   * @param name registered model name
+   * @param tag  tag name
+   */
+  public void deleteRegisteredModelTag(String name, String tag) throws SubmarineRuntimeException {
+    checkRegisteredModelTag(name, tag);
+    RegisteredModelTagEntity registeredModelTag = new RegisteredModelTagEntity();
+    registeredModelTag.setName(name);
+    registeredModelTag.setTag(tag);
+    registeredModelTagService.delete(registeredModelTag);
+  }
+
+  /**
+   * Check if registered model spec is valid spec.
+   *
+   * @param entity registered model entity
+   */
+  private void checkRegisteredModel(RegisteredModelEntity entity) {
+    if (entity == null) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Registered model entity object is null.");
+    }
+    if (entity.getName() == null || entity.getName().equals("")) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Registered model name is null.");
+    }
+  }
+
+  private void deleteModelInS3(List<ModelVersionEntity> modelVersions) throws SubmarineRuntimeException {
+    try {
+      modelVersions.forEach(modelVersion -> s3Client.deleteArtifactsByModelVersion(
+          modelVersion.getName(),
+          modelVersion.getVersion(),
+          modelVersion.getId()
+      )
+      );
+    } catch (SubmarineRuntimeException e) {
+      throw new SubmarineRuntimeException(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
+            "Some error happen when deleting the model in s3 bucket.");
+    }
+  }
+
+  /**
+   * Check if registered model tag is valid spec.
+   *
+   * @param name registered model name
+   * @param tag  tag name
+   */
+  private void checkRegisteredModelTag(String name, String tag) {
+    if (name.equals("")) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Registered model name is null.");
+    }
+    if (tag.equals("")) {
+      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
+          "Invalid. Tag name is null.");
+    }
+    RegisteredModelEntity registeredModel = registeredModelService.select(name);
+    if (registeredModel == null){
+      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
+          "Invalid. Registered model " + name + " is not existed.");
+    }
+  }
+
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ModelVersionRestApi.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ModelVersionRestApi.java
index 98817f34..cec19478 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ModelVersionRestApi.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ModelVersionRestApi.java
@@ -19,8 +19,6 @@
 
 package org.apache.submarine.server.rest;
 
-import org.json.JSONObject;
-
 import java.util.List;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -41,11 +39,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
 
 import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
 import org.apache.submarine.server.database.model.entities.ModelVersionEntity;
-import org.apache.submarine.server.database.model.entities.ModelVersionTagEntity;
-import org.apache.submarine.server.database.model.service.ModelVersionService;
-
-import org.apache.submarine.server.database.model.service.ModelVersionTagService;
-import org.apache.submarine.server.s3.Client;
+import org.apache.submarine.server.manager.ModelVersionManager;
 import org.apache.submarine.server.utils.response.JsonResponse;
 
 /**
@@ -55,13 +49,8 @@ import org.apache.submarine.server.utils.response.JsonResponse;
 @Produces({ MediaType.APPLICATION_JSON + "; " + RestConstants.CHARSET_UTF8 })
 public class ModelVersionRestApi {
 
-  /* Model version service */
-  private final ModelVersionService modelVersionService = new ModelVersionService();
-
-  /* Model version tag service */
-  private final ModelVersionTagService modelVersionTagService = new ModelVersionTagService();
-
-  private final Client s3Client = new Client();
+  /* ModelVersion manager  */
+  private final ModelVersionManager modelVersionManager = ModelVersionManager.getInstance();
 
   /**
    * Return the Pong message for test the connectivity.
@@ -102,31 +91,7 @@ public class ModelVersionRestApi {
   public Response createModelVersion(ModelVersionEntity entity,
                                      @QueryParam("baseDir") String baseDir) {
     try {
-      String res = new String(s3Client.downloadArtifact(
-          String.format("%s/description.json", baseDir)));
-      JSONObject description = new JSONObject(res);
-      String modelType =  description.get("model_type").toString();
-      String id = description.get("id").toString();
-      entity.setId(id);
-      entity.setModelType(modelType);
-
-      int version = modelVersionService.selectAllVersions(entity.getName()).stream().mapToInt(
-          ModelVersionEntity::getVersion
-      ).max().orElse(0) + 1;
-
-      entity.setVersion(version);
-      modelVersionService.insert(entity);
-
-      // the directory of storing a single model must be unique for serving
-      String uniqueModelPath = String.format("%s-%d-%s", entity.getName(), version, id);
-
-      // copy artifacts
-      s3Client.listAllObjects(baseDir).forEach(s -> {
-        String relativePath = s.substring(String.format("%s/", baseDir).length());
-        s3Client.copyArtifact(String.format("registry/%s/%s/%d/%s", uniqueModelPath,
-            entity.getName(), entity.getVersion(), relativePath), s);
-      });
-
+      modelVersionManager.createModelVersion(entity, baseDir);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
         .message("Create a model version instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -147,7 +112,7 @@ public class ModelVersionRestApi {
           content = @Content(schema = @Schema(implementation = JsonResponse.class)))})
   public Response listModelVersions(@PathParam(RestConstants.MODEL_VERSION_NAME) String name) {
     try {
-      List<ModelVersionEntity> modelVersionList = modelVersionService.selectAllVersions(name);
+      List<ModelVersionEntity> modelVersionList = modelVersionManager.listModelVersions(name);
       return new JsonResponse.Builder<List<ModelVersionEntity>>(Response.Status.OK).success(true)
           .message("List all model version instances").result(modelVersionList).build();
     } catch (SubmarineRuntimeException e) {
@@ -171,7 +136,7 @@ public class ModelVersionRestApi {
   public Response getModelVersion(@PathParam(RestConstants.MODEL_VERSION_NAME) String name,
                                   @PathParam(RestConstants.MODEL_VERSION_VERSION) Integer version) {
     try {
-      ModelVersionEntity modelVersion = modelVersionService.selectWithTag(name, version);
+      ModelVersionEntity modelVersion = modelVersionManager.getModelVersion(name, version);
       return new JsonResponse.Builder<ModelVersionEntity>(Response.Status.OK).success(true)
           .message("Get the model version instance").result(modelVersion).build();
     } catch (SubmarineRuntimeException e) {
@@ -195,9 +160,7 @@ public class ModelVersionRestApi {
   public Response deleteModelVersion(@PathParam(RestConstants.MODEL_VERSION_NAME) String name,
                                      @PathParam(RestConstants.MODEL_VERSION_VERSION) Integer version) {
     try {
-      ModelVersionEntity spec = modelVersionService.select(name, version);
-      s3Client.deleteArtifactsByModelVersion(name, version, spec.getId());
-      modelVersionService.delete(name, version);
+      modelVersionManager.deleteModelVersion(name, version);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
           .message("Delete the model version instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -226,8 +189,7 @@ public class ModelVersionRestApi {
       @ApiResponse(responseCode = "404", description = "ModelVersionEntity not found")})
   public Response updateModelVersion(ModelVersionEntity entity) {
     try {
-      checkModelVersion(entity);
-      modelVersionService.update(entity);
+      modelVersionManager.updateModelVersion(entity);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
           .message("Update the model version instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -253,12 +215,7 @@ public class ModelVersionRestApi {
                                         @DefaultValue("") @QueryParam("version") String version,
                                         @DefaultValue("") @QueryParam("tag") String tag) {
     try {
-      checkModelVersionTag(name, version, tag);
-      ModelVersionTagEntity modelVersionTag = new ModelVersionTagEntity();
-      modelVersionTag.setName(name);
-      modelVersionTag.setVersion(Integer.parseInt(version));
-      modelVersionTag.setTag(tag);
-      modelVersionTagService.insert(modelVersionTag);
+      modelVersionManager.createModelVersionTag(name, version, tag);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
           .message("Create a model version tag instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -284,12 +241,7 @@ public class ModelVersionRestApi {
                                         @DefaultValue("") @QueryParam("version") String version,
                                         @DefaultValue("") @QueryParam("tag") String tag) {
     try {
-      checkModelVersionTag(name, version, tag);
-      ModelVersionTagEntity modelVersionTag = new ModelVersionTagEntity();
-      modelVersionTag.setName(name);
-      modelVersionTag.setVersion(Integer.parseInt(version));
-      modelVersionTag.setTag(tag);
-      modelVersionTagService.delete(modelVersionTag);
+      modelVersionManager.deleteModelVersionTag(name, version, tag);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
           .message("Delete a model version tag instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -300,63 +252,4 @@ public class ModelVersionRestApi {
   private Response parseModelVersionServiceException(SubmarineRuntimeException e) {
     return new JsonResponse.Builder<String>(e.getCode()).message(e.getMessage()).build();
   }
-
-  private void checkModelVersion(ModelVersionEntity entity) {
-    if (entity == null) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Model version entity object is null.");
-    }
-    if (entity.getName() == null || entity.getName().equals("")) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Model version's name is null.");
-    }
-    if (entity.getVersion() == null) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Model version's version is null.");
-    }
-    ModelVersionEntity modelVersion = modelVersionService.select(entity.getName(), entity.getVersion());
-    if (modelVersion == null) {
-      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
-          "Invalid. Model version entity with same name and version is not existed.");
-    }
-  }
-
-  /**
-   * Check if model version tag is valid.
-   *
-   * @param name    model version's name
-   * @param version model version's version
-   * @param tag     tag name
-   */
-  private void checkModelVersionTag(String name, String version, String tag) {
-    if (name.equals("")){
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Model version's name is null.");
-    }
-    if (version.equals("")) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Model version's version is null.");
-    }
-    int versionNum;
-    try {
-      versionNum = Integer.parseInt(version);
-      if (versionNum < 1){
-        throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-            "Invalid. Model version's version must be bigger than 0.");
-      }
-    } catch (NumberFormatException e){
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Model version's version must be an integer.");
-    }
-    if (tag.equals("")) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Tag name is null.");
-    }
-    ModelVersionEntity modelVersion = modelVersionService.select(name,
-        versionNum);
-    if (modelVersion == null){
-      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
-          "Invalid. Model version " + name + " version " + versionNum + " is not existed.");
-    }
-  }
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/RegisteredModelRestApi.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/RegisteredModelRestApi.java
index 8e7825e8..85767008 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/RegisteredModelRestApi.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/RegisteredModelRestApi.java
@@ -39,14 +39,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
 
 
 import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
-import org.apache.submarine.server.database.model.entities.ModelVersionEntity;
 import org.apache.submarine.server.database.model.entities.RegisteredModelEntity;
-import org.apache.submarine.server.database.model.entities.RegisteredModelTagEntity;
-import org.apache.submarine.server.database.model.service.ModelVersionService;
-import org.apache.submarine.server.database.model.service.RegisteredModelService;
 
-import org.apache.submarine.server.database.model.service.RegisteredModelTagService;
-import org.apache.submarine.server.s3.Client;
+import org.apache.submarine.server.manager.RegisteredModelManager;
 import org.apache.submarine.server.utils.response.JsonResponse;
 
 
@@ -57,16 +52,8 @@ import org.apache.submarine.server.utils.response.JsonResponse;
 @Produces({ MediaType.APPLICATION_JSON + "; " + RestConstants.CHARSET_UTF8 })
 public class RegisteredModelRestApi {
 
-  /* Registered model service */
-  private final RegisteredModelService registeredModelService = new RegisteredModelService();
-
-  /* Model version service */
-  private final ModelVersionService modelVersionService = new ModelVersionService();
-
-  /* Registered model tag service */
-  private final RegisteredModelTagService registeredModelTagService = new RegisteredModelTagService();
-
-  private final Client s3Client = new Client();
+  /* Registered model manager  */
+  private final RegisteredModelManager registeredModelManager = RegisteredModelManager.getInstance();
 
   /**
    * Return the Pong message for test the connectivity.
@@ -102,8 +89,7 @@ public class RegisteredModelRestApi {
           content = @Content(schema = @Schema(implementation = JsonResponse.class))) })
   public Response createRegisteredModel(RegisteredModelEntity entity) {
     try {
-      checkRegisteredModel(entity);
-      registeredModelService.insert(entity);
+      registeredModelManager.createRegisteredModel(entity);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
         .message("Create a registered model instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -122,7 +108,7 @@ public class RegisteredModelRestApi {
       content = @Content(schema = @Schema(implementation = JsonResponse.class))) })
   public Response listRegisteredModels() {
     try {
-      List<RegisteredModelEntity> registeredModelList = registeredModelService.selectAll();
+      List<RegisteredModelEntity> registeredModelList = registeredModelManager.listRegisteredModels();
       return new JsonResponse.Builder<List<RegisteredModelEntity>>(Response.Status.OK).success(true)
         .message("List all registered model instances").result(registeredModelList).build();
     } catch (SubmarineRuntimeException e) {
@@ -145,7 +131,7 @@ public class RegisteredModelRestApi {
       @ApiResponse(responseCode = "404", description = "RegisteredModelEntity not found") })
   public Response getRegisteredModel(@PathParam(RestConstants.REGISTERED_MODEL_NAME) String name) {
     try {
-      RegisteredModelEntity registeredModel = registeredModelService.selectWithTag(name);
+      RegisteredModelEntity registeredModel = registeredModelManager.getRegisteredModel(name);
       return new JsonResponse.Builder<RegisteredModelEntity>(Response.Status.OK).success(true)
         .message("Get the registered model instance").result(registeredModel).build();
     } catch (SubmarineRuntimeException e) {
@@ -173,22 +159,12 @@ public class RegisteredModelRestApi {
   public Response updateRegisteredModel(
       @PathParam(RestConstants.REGISTERED_MODEL_NAME) String name, RegisteredModelEntity entity) {
     try {
-      RegisteredModelEntity oldRegisteredModelEntity = registeredModelService.select(name);
-      if (oldRegisteredModelEntity == null) {
-        throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
-            "Invalid. Registered model " + name + " is not existed.");
-      }
-      checkRegisteredModel(entity);
-      if (!name.equals(entity.getName())) {
-        registeredModelService.rename(name, entity.getName());
-      }
-      registeredModelService.update(entity);
+      registeredModelManager.updateRegisteredModel(name, entity);
+      return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
+        .message("Update the registered model instance").build();
     } catch (SubmarineRuntimeException e) {
       return parseRegisteredModelServiceException(e);
     }
-
-    return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
-        .message("Update the registered model instance").build();
   }
 
   /**
@@ -207,16 +183,7 @@ public class RegisteredModelRestApi {
       @ApiResponse(responseCode = "500", description = "Some error happen in server")})
   public Response deleteRegisteredModel(@PathParam(RestConstants.REGISTERED_MODEL_NAME) String name) {
     try {
-      List<ModelVersionEntity> modelVersions = modelVersionService.selectAllVersions(name);
-      modelVersions.forEach(modelVersion -> {
-        String stage = modelVersion.getCurrentStage();
-        if (stage.equals("Production")) {
-          throw new SubmarineRuntimeException(Response.Status.NOT_ACCEPTABLE.getStatusCode(),
-              "Invalid. Some version of models are in the production stage");
-        }
-      });
-      this.deleteModelInS3(modelVersions);
-      registeredModelService.delete(name);
+      registeredModelManager.deleteRegisteredModel(name);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
         .message("Delete the registered model instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -240,11 +207,7 @@ public class RegisteredModelRestApi {
   public Response createRegisteredModelTag(@DefaultValue("") @QueryParam("name") String name,
                                            @DefaultValue("") @QueryParam("tag") String tag) {
     try {
-      checkRegisteredModelTag(name, tag);
-      RegisteredModelTagEntity registeredModelTag = new RegisteredModelTagEntity();
-      registeredModelTag.setName(name);
-      registeredModelTag.setTag(tag);
-      registeredModelTagService.insert(registeredModelTag);
+      registeredModelManager.createRegisteredModelTag(name, tag);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
           .message("Create a registered model tag instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -268,11 +231,7 @@ public class RegisteredModelRestApi {
   public Response deleteRegisteredModelTag(@DefaultValue("") @QueryParam("name") String name,
                                            @DefaultValue("") @QueryParam("tag") String tag) {
     try {
-      checkRegisteredModelTag(name, tag);
-      RegisteredModelTagEntity registeredModelTag = new RegisteredModelTagEntity();
-      registeredModelTag.setName(name);
-      registeredModelTag.setTag(tag);
-      registeredModelTagService.delete(registeredModelTag);
+      registeredModelManager.deleteRegisteredModelTag(name, tag);
       return new JsonResponse.Builder<String>(Response.Status.OK).success(true)
           .message("Delete a registered model tag instance").build();
     } catch (SubmarineRuntimeException e) {
@@ -283,58 +242,4 @@ public class RegisteredModelRestApi {
   private Response parseRegisteredModelServiceException(SubmarineRuntimeException e) {
     return new JsonResponse.Builder<String>(e.getCode()).message(e.getMessage()).build();
   }
-
-  /**
-   * Check if registered model spec is valid spec.
-   *
-   * @param entity registered model entity
-   */
-  private void checkRegisteredModel(RegisteredModelEntity entity) {
-    if (entity == null) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Registered model entity object is null.");
-    }
-    if (entity.getName() == null || entity.getName().equals("")) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Registered model name is null.");
-    }
-  }
-
-
-  private void deleteModelInS3(List<ModelVersionEntity> modelVersions) throws SubmarineRuntimeException {
-    try {
-      modelVersions.forEach(modelVersion -> s3Client.deleteArtifactsByModelVersion(
-          modelVersion.getName(),
-          modelVersion.getVersion(),
-          modelVersion.getId()
-      )
-      );
-    } catch (SubmarineRuntimeException e) {
-      throw new SubmarineRuntimeException(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
-            "Some error happen when deleting the model in s3 bucket.");
-    }
-
-  }
-
-  /**
-   * Check if registered model tag is valid spec.
-   *
-   * @param name registered model name
-   * @param tag  tag name
-   */
-  private void checkRegisteredModelTag(String name, String tag) {
-    if (name.equals("")) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Registered model name is null.");
-    }
-    if (tag.equals("")) {
-      throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-          "Invalid. Tag name is null.");
-    }
-    RegisteredModelEntity registeredModel = registeredModelService.select(name);
-    if (registeredModel == null){
-      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
-          "Invalid. Registered model " + name + " is not existed.");
-    }
-  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@submarine.apache.org
For additional commands, e-mail: dev-help@submarine.apache.org