Skip to content

Commit

Permalink
Feature/SK-1466 | Add Package DTO (#834)
Browse files Browse the repository at this point in the history
  • Loading branch information
carl-andersson authored Mar 5, 2025
1 parent a6a1df0 commit dfe7106
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 338 deletions.
2 changes: 1 addition & 1 deletion fedn/network/api/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def get_checksum(name: str = None) -> Tuple[bool, str, str]:
if active_package is None:
message = "No compute package uploaded"
return success, message, sum
name = active_package["storage_file_name"]
name = active_package.storage_file_name
file_path = safe_join(os.getcwd(), name)
try:
sum = str(sha(file_path))
Expand Down
2 changes: 1 addition & 1 deletion fedn/network/api/v1/client_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ def add_client():
"message": "No compute package found. Set package in controller.",
}
), 203
helper_type = package_object["helper"]
helper_type = package_object.helper
else:
helper_type = ""

Expand Down
2 changes: 1 addition & 1 deletion fedn/network/api/v1/helper_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_active_helper():
if active_package is None:
return jsonify({"message": "No active helper"}), 404

response = active_package["helper"]
response = active_package.helper

return jsonify(response), 200
except Exception as e:
Expand Down
37 changes: 22 additions & 15 deletions fedn/network/api/v1/package_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from fedn.network.api.shared import control, package_store, repository
from fedn.network.api.shared import get_checksum as _get_checksum
from fedn.network.api.v1.shared import api_version, get_post_data_to_kwargs, get_typed_list_headers
from fedn.network.storage.statestore.stores.dto.package import PackageDTO

bp = Blueprint("package", __name__, url_prefix=f"/api/{api_version}/packages")

Expand Down Expand Up @@ -122,7 +123,9 @@ def get_packages():
limit, skip, sort_key, sort_order = get_typed_list_headers(request.headers)
kwargs = request.args.to_dict()

response = package_store.list(limit, skip, sort_key, sort_order, **kwargs)
result = package_store.select(limit, skip, sort_key, sort_order, **kwargs)
count = package_store.count(**kwargs)
response = {"count": count, "result": [result.to_dict() for result in result]}

return jsonify(response), 200
except Exception as e:
Expand Down Expand Up @@ -207,7 +210,9 @@ def list_packages():
limit, skip, sort_key, sort_order = get_typed_list_headers(request.headers)
kwargs = get_post_data_to_kwargs(request)

response = package_store.list(limit, skip, sort_key, sort_order, **kwargs)
response = package_store.select(limit, skip, sort_key, sort_order, **kwargs)
count = package_store.count(**kwargs)
response = {"count": count, "result": [result.to_dict() for result in response]}

return jsonify(response), 200
except Exception as e:
Expand Down Expand Up @@ -375,11 +380,11 @@ def get_package(id: str):
type: string
"""
try:
response = package_store.get(id)
if response is None:
return jsonify({"message": f"Entity with id: {id} not found"}), 404
response = package_store.get(id)
if response is None:
return jsonify({"message": f"Entity with id: {id} not found"}), 404

return jsonify(response), 200
return jsonify(response.to_dict()), 200
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
return jsonify({"message": "An unexpected error occurred"}), 500
Expand Down Expand Up @@ -416,9 +421,9 @@ def get_active_package():
try:
response = package_store.get_active()
if response is None:
return jsonify({"message": "Entity not found"}), 404
return jsonify({"message": "Entity not found"}), 404

return jsonify(response), 200
return jsonify(response.to_dict()), 200
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
return jsonify({"message": "An unexpected error occurred"}), 500
Expand Down Expand Up @@ -496,7 +501,7 @@ def delete_active_package():
try:
result = package_store.delete_active()
if result is False:
return jsonify({"message": "Entity not found"}), 404
return jsonify({"message": "Entity not found"}), 404
return jsonify({"message": "Active package deleted"}), 200
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
Expand Down Expand Up @@ -557,12 +562,14 @@ def upload_package():

data["file_name"] = file_name

valid, response = package_store.add(data)
new_package = PackageDTO().populate_with(data)

valid, response = package_store.add(new_package)

if not valid:
return jsonify({"message": response}), 400

storage_file_name = response["storage_file_name"]
storage_file_name = response.storage_file_name
try:
file_path = safe_join(FEDN_COMPUTE_PACKAGE_DIR, storage_file_name)
if not os.path.exists(FEDN_COMPUTE_PACKAGE_DIR):
Expand All @@ -571,10 +578,10 @@ def upload_package():
repository.set_compute_package(storage_file_name, file_path)
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
package_store.delete(response["id"])
package_store.delete(response.id)
return jsonify({"message": "An unexpected error occurred"}), 500

package_store.set_active(response["id"])
package_store.set_active(response.id)
return jsonify({"message": "Package uploaded"}), 200
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
Expand Down Expand Up @@ -624,8 +631,8 @@ def download_package():
if name is None:
active_package = package_store.get_active()
if active_package is None:
return jsonify({"message": "No active package"}), 404
name = active_package["storage_file_name"]
return jsonify({"message": "No active package"}), 404
name = active_package.storage_file_name
try:
mutex = threading.Lock()
mutex.acquire()
Expand Down
2 changes: 1 addition & 1 deletion fedn/network/controller/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ def check_combiners_done_reporting():

try:
active_package = self.package_store.get_active()
helper_type = active_package["helper"]
helper_type = active_package.helper
except Exception:
logger.error("Failed to get active helper")

Expand Down
4 changes: 2 additions & 2 deletions fedn/network/controller/controlbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def get_helper(self):

try:
active_package = self.package_store.get_active()
helper_type = active_package["helper"]
helper_type = active_package.helper
except Exception:
logger.error("Failed to get active helper")

Expand Down Expand Up @@ -120,7 +120,7 @@ def get_compute_package_name(self):
definition = self.package_store.get_active()
if definition:
try:
package_name = definition["storage_file_name"]
package_name = definition.storage_file_name
return package_name
except (IndexError, KeyError):
logger.error("No context filename set for compute context definition")
Expand Down
3 changes: 2 additions & 1 deletion fedn/network/storage/statestore/stores/dto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from fedn.network.storage.statestore.stores.dto.client import ClientDTO
from fedn.network.storage.statestore.stores.dto.combiner import CombinerDTO
from fedn.network.storage.statestore.stores.dto.model import ModelDTO
from fedn.network.storage.statestore.stores.dto.package import PackageDTO
from fedn.network.storage.statestore.stores.dto.session import SessionConfigDTO, SessionDTO

__all__ = ["ClientDTO", "ModelDTO", "SessionConfigDTO", "SessionDTO", "CombinerDTO"]
__all__ = ["ClientDTO", "ModelDTO", "SessionConfigDTO", "SessionDTO", "CombinerDTO", "PackageDTO"]
15 changes: 15 additions & 0 deletions fedn/network/storage/statestore/stores/dto/package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Optional

from fedn.network.storage.statestore.stores.dto.shared import BaseDTO, Field, OptionalField


class PackageDTO(BaseDTO):
"""Package data transfer object."""

id: Optional[str] = OptionalField(None)
description: str = Field(None)
file_name: str = Field(None)
helper: str = Field(None)
name: str = Field(None)
storage_file_name: str = OptionalField(None)
active: bool = OptionalField(False)
Loading

0 comments on commit dfe7106

Please sign in to comment.