Skip to content

Commit 53d0823

Browse files
author
Andrei Neagu
committed
added project and node ids repalcement with names
1 parent bb3b81c commit 53d0823

File tree

3 files changed

+99
-3
lines changed

3 files changed

+99
-3
lines changed

services/storage/src/simcore_service_storage/simcore_s3_dsm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ async def create_s3_export(
13111311
)
13121312

13131313
await create_and_upload_export(
1314-
get_s3_client(self.app),
1314+
self.app,
13151315
self.simcore_bucket_name,
13161316
source_object_keys=source_object_keys,
13171317
destination_object_keys=destination_object_key,

services/storage/src/simcore_service_storage/utils/simcore_s3_dsm_utils.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
from contextlib import suppress
23
from pathlib import Path
34
from typing import TypeAlias
@@ -7,6 +8,7 @@
78
from aws_library.s3 import S3MetaData, SimcoreS3API
89
from aws_library.s3._constants import STREAM_READER_CHUNK_SIZE
910
from aws_library.s3._models import S3ObjectKey
11+
from fastapi import FastAPI
1012
from models_library.api_schemas_storage.storage_schemas import S3BucketName
1113
from models_library.projects import ProjectID
1214
from models_library.projects_nodes_io import (
@@ -25,10 +27,15 @@
2527
from ..constants import EXPORTS_S3_PREFIX
2628
from ..exceptions.errors import FileMetaDataNotFoundError, ProjectAccessRightError
2729
from ..models import FileMetaData, FileMetaDataAtDB, GenericCursor, PathMetaData
30+
from ..modules.db import get_db_engine
2831
from ..modules.db.access_layer import AccessLayerRepository
2932
from ..modules.db.file_meta_data import FileMetaDataRepository, TotalChildren
33+
from ..modules.db.projects import NodeIDStr, ProjectIDStr, ProjectRepository
34+
from ..modules.s3 import get_s3_client
3035
from .utils import convert_db_to_model
3136

37+
_logger = logging.getLogger(__name__)
38+
3239

3340
async def _list_all_files_in_folder(
3441
*,
@@ -165,17 +172,58 @@ def _base_path_parent(base_path: UserSelectionStr, s3_object: S3ObjectKey) -> st
165172
return f"{result}"
166173

167174

175+
def _get_project_ids(user_selecton: set[UserSelectionStr]) -> list[ProjectID]:
176+
_logger.error("user_selection=%s", user_selecton)
177+
results = []
178+
for selected in user_selecton:
179+
project_id = ProjectID(Path(selected).parts[0])
180+
results.append(project_id)
181+
return results
182+
183+
184+
def _replace_node_id_project_id_in_path(
185+
ids_names_map: dict[ProjectID, dict[ProjectIDStr | NodeIDStr, str]], path: str
186+
) -> str:
187+
path_parts = Path(path).parts
188+
if len(path_parts) == 0:
189+
return path
190+
191+
if len(path_parts) == 1:
192+
return ids_names_map[ProjectID(path)][path].replace("/", "_")
193+
194+
project_id_str = path_parts[0]
195+
project_id = ProjectID(project_id_str)
196+
node_id_str = path_parts[1]
197+
return "/".join(
198+
(
199+
ids_names_map[project_id][project_id_str].replace("/", "_"),
200+
ids_names_map[project_id][node_id_str].replace("/", "_"),
201+
*path_parts[2:],
202+
)
203+
)
204+
205+
168206
async def create_and_upload_export(
169-
s3_client: SimcoreS3API,
207+
app: FastAPI,
170208
bucket: S3BucketName,
171209
*,
172210
source_object_keys: set[tuple[UserSelectionStr, StorageFileID]],
173211
destination_object_keys: StorageFileID,
174212
progress_bar: ProgressBarData,
175213
) -> None:
214+
s3_client = get_s3_client(app)
215+
ids_names_map = await ProjectRepository.instance(
216+
get_db_engine(app)
217+
).get_project_id_and_node_id_to_names_map(
218+
project_uuids=_get_project_ids(user_selecton={x[0] for x in source_object_keys})
219+
)
220+
176221
archive_entries: ArchiveEntries = [
177222
(
178-
_base_path_parent(selection, s3_object),
223+
_base_path_parent(
224+
_replace_node_id_project_id_in_path(ids_names_map, selection),
225+
_replace_node_id_project_id_in_path(ids_names_map, s3_object),
226+
),
179227
await s3_client.get_bytes_streamer_from_object(bucket, s3_object),
180228
)
181229
for (selection, s3_object) in source_object_keys

services/storage/tests/unit/test_simcore_s3_dsm_utils.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
from pathlib import Path
2+
from typing import Final
3+
from uuid import UUID
24

35
import pytest
46
from aws_library.s3._models import S3ObjectKey
7+
from models_library.projects import ProjectID, ProjectIDStr
8+
from models_library.projects_nodes_io import NodeIDStr
9+
from simcore_service_storage.models import NodeID
510
from simcore_service_storage.utils.simcore_s3_dsm_utils import (
611
UserSelectionStr,
712
_base_path_parent,
13+
_replace_node_id_project_id_in_path,
814
compute_file_id_prefix,
915
ensure_user_selection_from_same_base_directory,
1016
)
@@ -73,3 +79,45 @@ def test_ensure_user_selection_from_same_base_directory(
7379
ensure_user_selection_from_same_base_directory([f"{x}" for x in user_selection])
7480
== expected
7581
)
82+
83+
84+
_PID1: Final[ProjectID] = UUID(int=1)
85+
_PID2: Final[ProjectID] = UUID(int=2)
86+
_NID1: Final[NodeID] = UUID(int=3)
87+
_NID2: Final[NodeID] = UUID(int=4)
88+
_IDS_NAMES_MAP: Final[dict[ProjectID, dict[ProjectIDStr | NodeIDStr, str]]] = {
89+
_PID1: {
90+
f"{_PID1}": "project one",
91+
f"{_NID1}": "project one -> node one",
92+
f"{_NID2}": "project one -> node two",
93+
},
94+
_PID2: {
95+
f"{_PID2}": "/project/two/",
96+
f"{_NID1}": "/project/two/->/node/one/",
97+
f"{_NID2}": "/project/two/->/node/two/",
98+
},
99+
}
100+
101+
102+
@pytest.mark.parametrize(
103+
"path, expected",
104+
[
105+
("", ""),
106+
(f"{_PID1}", "project one"),
107+
(f"{_PID1}/{_NID1}", "project one/project one -> node one"),
108+
(f"{_PID1}/{_NID1}/something", "project one/project one -> node one/something"),
109+
(f"{_PID1}/{_NID1}/{_NID2}", f"project one/project one -> node one/{_NID2}"),
110+
(f"{_PID2}", "_project_two_"),
111+
(f"{_PID2}/{_NID1}", "_project_two_/_project_two_->_node_one_"),
112+
(
113+
f"{_PID2}/{_NID1}/something",
114+
"_project_two_/_project_two_->_node_one_/something",
115+
),
116+
(
117+
f"{_PID2}/{_NID1}/{_NID2}",
118+
f"_project_two_/_project_two_->_node_one_/{_NID2}",
119+
),
120+
],
121+
)
122+
def test__replace_node_id_project_id_in_path(path: str, expected: str):
123+
assert _replace_node_id_project_id_in_path(_IDS_NAMES_MAP, path) == expected

0 commit comments

Comments
 (0)