Skip to content

Commit b16c6b7

Browse files
author
Andrei Neagu
committed
Merge remote-tracking branch 'upstream/master' into pr-osparc-add-posgres-tables-to-dyamic-scheduler
2 parents a352c4f + 1c003f5 commit b16c6b7

File tree

15 files changed

+100
-91
lines changed

15 files changed

+100
-91
lines changed

packages/aws-library/requirements/_base.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ typer==0.15.2
384384
# via
385385
# -r requirements/../../../packages/service-library/requirements/../../../packages/settings-library/requirements/_base.in
386386
# -r requirements/../../../packages/settings-library/requirements/_base.in
387-
types-aiobotocore==2.21.0
387+
types-aiobotocore==2.21.1
388388
# via -r requirements/_base.in
389389
types-aiobotocore-ec2==2.21.0
390390
# via types-aiobotocore

packages/aws-library/requirements/_test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,17 +280,17 @@ sympy==1.13.3
280280
# via cfn-lint
281281
termcolor==2.5.0
282282
# via pytest-sugar
283-
types-aioboto3==14.0.0
283+
types-aioboto3==14.1.0
284284
# via -r requirements/_test.in
285-
types-aiobotocore==2.21.0
285+
types-aiobotocore==2.21.1
286286
# via
287287
# -c requirements/_base.txt
288288
# types-aioboto3
289289
types-awscrt==0.23.10
290290
# via
291291
# -c requirements/_base.txt
292292
# botocore-stubs
293-
types-boto3==1.37.4
293+
types-boto3==1.38.2
294294
# via -r requirements/_test.in
295295
types-s3transfer==0.11.3
296296
# via

packages/aws-library/src/aws_library/s3/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
)
2323

2424
__all__: tuple[str, ...] = (
25-
"PRESIGNED_LINK_MAX_SIZE",
26-
"S3_MAX_FILE_SIZE",
2725
"CopiedBytesTransferredCallback",
2826
"MultiPartUploadLinks",
27+
"PRESIGNED_LINK_MAX_SIZE",
28+
"S3_MAX_FILE_SIZE",
2929
"S3AccessError",
3030
"S3BucketInvalidError",
3131
"S3DestinationNotEmptyError",
@@ -37,8 +37,8 @@
3737
"S3RuntimeError",
3838
"S3UploadNotFoundError",
3939
"SimcoreS3API",
40-
"UploadID",
4140
"UploadedBytesTransferredCallback",
41+
"UploadID",
4242
)
4343

4444
# nopycln: file

packages/aws-library/src/aws_library/s3/_client.py

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import functools
44
import logging
55
import urllib.parse
6-
import warnings
76
from collections.abc import AsyncGenerator, Sequence
87
from dataclasses import dataclass, field
98
from pathlib import Path
@@ -12,7 +11,6 @@
1211
import aioboto3
1312
from aiobotocore.session import ClientCreatorContext
1413
from boto3.s3.transfer import TransferConfig
15-
from botocore import __version__ as botocore_version
1614
from botocore import exceptions as botocore_exc
1715
from botocore.client import Config
1816
from models_library.api_schemas_storage.storage_schemas import (
@@ -22,7 +20,6 @@
2220
)
2321
from models_library.basic_types import SHA256Str
2422
from models_library.bytes_iters import BytesIter, DataSize
25-
from packaging import version
2623
from pydantic import AnyUrl, ByteSize, TypeAdapter
2724
from servicelib.bytes_iters import DEFAULT_READ_CHUNK_SIZE, BytesStreamer
2825
from servicelib.logging_utils import log_catch, log_context
@@ -54,22 +51,6 @@
5451
)
5552
from ._utils import compute_num_file_chunks, create_final_prefix
5653

57-
_BOTOCORE_VERSION: Final[version.Version] = version.parse(botocore_version)
58-
_MAX_BOTOCORE_VERSION_COMPATIBLE_WITH_CEPH_S3: Final[version.Version] = version.parse(
59-
"1.36.0"
60-
)
61-
62-
63-
def _check_botocore_version() -> None:
64-
if _BOTOCORE_VERSION >= _MAX_BOTOCORE_VERSION_COMPATIBLE_WITH_CEPH_S3:
65-
warnings.warn(
66-
f"Botocore version {botocore_version} is not supported for file uploads with CEPH S3 until CEPH is updated. "
67-
"Please use a version < 1.36.0. The upload operation will likely fail.",
68-
RuntimeWarning,
69-
stacklevel=2,
70-
)
71-
72-
7354
_logger = logging.getLogger(__name__)
7455

7556
_S3_MAX_CONCURRENCY_DEFAULT: Final[int] = 10
@@ -107,13 +88,21 @@ async def create(
10788
session_client = None
10889
exit_stack = contextlib.AsyncExitStack()
10990
try:
91+
config = Config(
92+
# This setting tells the S3 client to only calculate checksums when explicitly required
93+
# by the operation. This avoids unnecessary checksum calculations for operations that
94+
# don't need them, improving performance.
95+
# See: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3.html#calculating-checksums
96+
signature_version="s3v4",
97+
request_checksum_calculation="when_required", # type: ignore[call-arg]
98+
)
11099
session_client = session.client( # type: ignore[call-overload]
111100
"s3",
112101
endpoint_url=f"{settings.S3_ENDPOINT}",
113102
aws_access_key_id=settings.S3_ACCESS_KEY,
114103
aws_secret_access_key=settings.S3_SECRET_KEY,
115104
region_name=settings.S3_REGION,
116-
config=Config(signature_version="s3v4"),
105+
config=config,
117106
)
118107
assert isinstance(session_client, ClientCreatorContext) # nosec
119108

@@ -523,9 +512,6 @@ async def upload_file(
523512
bytes_transfered_cb: UploadedBytesTransferredCallback | None,
524513
) -> None:
525514
"""upload a file using aioboto3 transfer manager (e.g. works >5Gb and creates multiple threads)"""
526-
527-
_check_botocore_version()
528-
529515
upload_options: dict[str, Any] = {
530516
"Bucket": bucket,
531517
"Key": object_key,
@@ -550,9 +536,6 @@ async def copy_object(
550536
object_metadata: S3MetaData | None = None,
551537
) -> None:
552538
"""copy a file in S3 using aioboto3 transfer manager (e.g. works >5Gb and creates multiple threads)"""
553-
554-
_check_botocore_version()
555-
556539
copy_options: dict[str, Any] = {
557540
"CopySource": {"Bucket": bucket, "Key": src_object_key},
558541
"Bucket": bucket,
@@ -659,7 +642,6 @@ async def upload_object_from_file_like(
659642
file_like_reader: FileLikeReader,
660643
) -> None:
661644
"""streams write an object in S3 from an AsyncIterable[bytes]"""
662-
_check_botocore_version()
663645
await self._client.upload_fileobj(file_like_reader, bucket_name, object_key) # type: ignore[arg-type]
664646

665647
@staticmethod

packages/pytest-simcore/src/pytest_simcore/helpers/playwright.py

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -590,19 +590,28 @@ def expected_service_running(
590590
assertion_output_folder: Path,
591591
) -> Generator[ServiceRunning, None, None]:
592592
started = arrow.utcnow()
593-
with log_context(
594-
logging.INFO, msg=f"Waiting for node to run. Timeout: {timeout}"
595-
) as ctx:
596-
waiter = SocketIONodeProgressCompleteWaiter(
597-
node_id=node_id,
598-
logger=ctx.logger,
593+
with contextlib.ExitStack() as stack:
594+
ctx = stack.enter_context(
595+
log_context(
596+
logging.INFO,
597+
msg=f"Waiting for node to run. Timeout: {timeout}",
598+
)
599599
)
600+
if is_service_legacy:
601+
ctx.logger.info(
602+
"⚠️ Legacy service detected. We are skipping websocket messages in this case! ⚠️"
603+
)
604+
else:
605+
waiter = SocketIONodeProgressCompleteWaiter(
606+
node_id=node_id,
607+
logger=ctx.logger,
608+
)
609+
stack.enter_context(
610+
websocket.expect_event("framereceived", waiter, timeout=timeout)
611+
)
600612
service_running = ServiceRunning(iframe_locator=None)
601-
with websocket.expect_event("framereceived", waiter, timeout=timeout):
602-
if press_start_button:
603-
_trigger_service_start(page, node_id)
604-
605-
yield service_running
613+
if press_start_button:
614+
_trigger_service_start(page, node_id)
606615
elapsed_time = arrow.utcnow() - started
607616

608617
wait_for_service_endpoint_responding(
@@ -635,16 +644,27 @@ def wait_for_service_running(
635644
In which case this will need further adjutment"""
636645

637646
started = arrow.utcnow()
638-
with log_context(
639-
logging.INFO, msg=f"Waiting for node to run. Timeout: {timeout}"
640-
) as ctx:
641-
waiter = SocketIONodeProgressCompleteWaiter(
642-
node_id=node_id,
643-
logger=ctx.logger,
647+
with contextlib.ExitStack() as stack:
648+
ctx = stack.enter_context(
649+
log_context(
650+
logging.INFO,
651+
msg=f"Waiting for node to run. Timeout: {timeout}",
652+
)
644653
)
645-
with websocket.expect_event("framereceived", waiter, timeout=timeout):
646-
if press_start_button:
647-
_trigger_service_start(page, node_id)
654+
if is_service_legacy:
655+
ctx.logger.info(
656+
"⚠️ Legacy service detected. We are skipping websocket messages in this case! ⚠️"
657+
)
658+
else:
659+
waiter = SocketIONodeProgressCompleteWaiter(
660+
node_id=node_id,
661+
logger=ctx.logger,
662+
)
663+
stack.enter_context(
664+
websocket.expect_event("framereceived", waiter, timeout=timeout)
665+
)
666+
if press_start_button:
667+
_trigger_service_start(page, node_id)
648668
elapsed_time = arrow.utcnow() - started
649669
wait_for_service_endpoint_responding(
650670
node_id,

services/dask-sidecar/requirements/_base.txt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
aio-pika==9.5.3
22
# via -r requirements/../../../packages/service-library/requirements/_base.in
3-
aiobotocore==2.17.0
3+
aiobotocore==2.21.1
44
# via s3fs
55
aiocache==0.12.3
66
# via -r requirements/../../../packages/service-library/requirements/_base.in
@@ -67,10 +67,8 @@ blosc==1.11.2
6767
# via -r requirements/_base.in
6868
bokeh==3.6.2
6969
# via dask
70-
botocore==1.35.93
71-
# via
72-
# -c requirements/constraints.txt
73-
# aiobotocore
70+
botocore==1.37.1
71+
# via aiobotocore
7472
certifi==2024.8.30
7573
# via
7674
# -c requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
@@ -569,7 +567,6 @@ urllib3==2.2.3
569567
# -c requirements/../../../packages/settings-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
570568
# -c requirements/../../../packages/settings-library/requirements/../../../requirements/constraints.txt
571569
# -c requirements/../../../requirements/constraints.txt
572-
# aiobotocore
573570
# botocore
574571
# distributed
575572
# requests

services/dask-sidecar/requirements/_test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ aws-xray-sdk==2.14.0
1515
# via moto
1616
blinker==1.9.0
1717
# via flask
18-
boto3==1.35.93
18+
boto3==1.37.1
1919
# via
2020
# aws-sam-translator
2121
# moto
22-
botocore==1.35.93
22+
botocore==1.37.1
2323
# via
2424
# -c requirements/_base.txt
2525
# aws-xray-sdk
@@ -226,7 +226,7 @@ rpds-py==0.22.3
226226
# -c requirements/_base.txt
227227
# jsonschema
228228
# referencing
229-
s3transfer==0.10.4
229+
s3transfer==0.11.3
230230
# via boto3
231231
setuptools==75.8.2
232232
# via moto

services/dask-sidecar/requirements/constraints.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,3 @@ dask[distributed]>=2024.4.2 # issue with publish_dataset: https://github.com/das
1313
#
1414
# Compatibility/coordination
1515
#
16-
# botocore does not always add the checksums to the s3 object metadata leading to issues with CEPH S3
17-
# see https://github.com/ITISFoundation/osparc-simcore/issues/7585
18-
botocore<1.36.0

services/dask-sidecar/src/simcore_service_dask_sidecar/file_utils.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def _file_progress_cb(
3939
asyncio.run_coroutine_threadsafe(
4040
log_publishing_cb(
4141
f"{text_prefix}"
42-
f" {100.0 * float(value or 0)/float(size or 1):.1f}%"
42+
f" {100.0 * float(value or 0) / float(size or 1):.1f}%"
4343
f" ({ByteSize(value).human_readable() if value else 0} / {ByteSize(size).human_readable() if size else 'NaN'})",
4444
logging.DEBUG,
4545
),
@@ -59,6 +59,7 @@ class S3FsSettingsDict(TypedDict):
5959
key: str
6060
secret: str
6161
client_kwargs: ClientKWArgsDict
62+
config_kwargs: dict[str, str] # For botocore config options
6263

6364

6465
_DEFAULT_AWS_REGION: Final[str] = "us-east-1"
@@ -69,6 +70,14 @@ def _s3fs_settings_from_s3_settings(s3_settings: S3Settings) -> S3FsSettingsDict
6970
"key": s3_settings.S3_ACCESS_KEY,
7071
"secret": s3_settings.S3_SECRET_KEY,
7172
"client_kwargs": {},
73+
"config_kwargs": {
74+
# This setting tells the S3 client to only calculate checksums when explicitly required
75+
# by the operation. This avoids unnecessary checksum calculations for operations that
76+
# don't need them, improving performance.
77+
# See: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3.html#calculating-checksums
78+
"request_checksum_calculation": "when_required",
79+
"signature_version": "s3v4",
80+
},
7281
}
7382
if s3_settings.S3_REGION != _DEFAULT_AWS_REGION:
7483
# NOTE: see https://github.com/boto/boto3/issues/125 why this is so... (sic)
@@ -96,26 +105,30 @@ async def _copy_file(
96105
):
97106
src_storage_kwargs = src_storage_cfg or {}
98107
dst_storage_kwargs = dst_storage_cfg or {}
99-
with fsspec.open(
100-
f"{src_url}", mode="rb", **src_storage_kwargs
101-
) as src_fp, fsspec.open(f"{dst_url}", "wb", **dst_storage_kwargs) as dst_fp:
108+
with (
109+
fsspec.open(f"{src_url}", mode="rb", **src_storage_kwargs) as src_fp,
110+
fsspec.open(f"{dst_url}", mode="wb", **dst_storage_kwargs) as dst_fp,
111+
):
102112
assert isinstance(src_fp, IOBase) # nosec
103113
assert isinstance(dst_fp, IOBase) # nosec
104114
file_size = getattr(src_fp, "size", None)
105115
data_read = True
106116
total_data_written = 0
107117
t = time.process_time()
108118
while data_read:
109-
(data_read, data_written,) = await asyncio.get_event_loop().run_in_executor(
119+
(
120+
data_read,
121+
data_written,
122+
) = await asyncio.get_event_loop().run_in_executor(
110123
None, _file_chunk_streamer, src_fp, dst_fp
111124
)
112125
elapsed_time = time.process_time() - t
113126
total_data_written += data_written or 0
114127
await log_publishing_cb(
115128
f"{text_prefix}"
116-
f" {100.0 * float(total_data_written or 0)/float(file_size or 1):.1f}%"
129+
f" {100.0 * float(total_data_written or 0) / float(file_size or 1):.1f}%"
117130
f" ({ByteSize(total_data_written).human_readable() if total_data_written else 0} / {ByteSize(file_size).human_readable() if file_size else 'NaN'})"
118-
f" [{ByteSize(total_data_written).to('MB')/elapsed_time:.2f} MBytes/s (avg)]",
131+
f" [{ByteSize(total_data_written).to('MB') / elapsed_time:.2f} MBytes/s (avg)]",
119132
logging.DEBUG,
120133
)
121134

services/static-webserver/client/source/class/osparc/share/CollaboratorsService.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ qx.Class.define("osparc.share.CollaboratorsService", {
5454
return;
5555
}
5656

57-
const readAccessRole = osparc.data.Roles.SERVICE["read"];
57+
const readAccessRole = osparc.data.Roles.SERVICES["read"];
5858
const newAccessRights = this._serializedDataCopy["accessRights"];
5959
gids.forEach(gid => {
6060
newAccessRights[gid] = readAccessRole.accessRights;
@@ -111,7 +111,7 @@ qx.Class.define("osparc.share.CollaboratorsService", {
111111
},
112112

113113
_promoteToEditor: function(collaborator, item) {
114-
const writeAccessRole = osparc.data.Roles.SERVICE["write"];
114+
const writeAccessRole = osparc.data.Roles.SERVICES["write"];
115115
this.__make(
116116
collaborator["gid"],
117117
writeAccessRole.accessRights,
@@ -126,7 +126,7 @@ qx.Class.define("osparc.share.CollaboratorsService", {
126126
},
127127

128128
_demoteToUser: function(collaborator, item) {
129-
const readAccessRole = osparc.data.Roles.SERVICE["read"];
129+
const readAccessRole = osparc.data.Roles.SERVICES["read"];
130130
this.__make(
131131
collaborator["gid"],
132132
readAccessRole.accessRights,

0 commit comments

Comments
 (0)