Skip to content

Commit 240c0a2

Browse files
authored
Merge branch 'master' into handle_function_errors_api
2 parents 88d14b5 + 2f0a89d commit 240c0a2

File tree

15 files changed

+127
-162
lines changed

15 files changed

+127
-162
lines changed

packages/simcore-sdk/requirements/_base.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
aiocache
1414
aiofiles
1515
aiohttp
16+
httpx
1617
packaging
1718
pint
18-
sqlalchemy[asyncio]
1919
pydantic[email]
20+
sqlalchemy[asyncio]
2021
tenacity
2122
tqdm

packages/simcore-sdk/requirements/_base.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ anyio==4.8.0
4444
# via
4545
# fast-depends
4646
# faststream
47+
# httpx
4748
arrow==1.3.0
4849
# via
4950
# -r requirements/../../../packages/models-library/requirements/_base.in
@@ -72,6 +73,8 @@ certifi==2025.1.31
7273
# -c requirements/../../../packages/settings-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
7374
# -c requirements/../../../packages/settings-library/requirements/../../../requirements/constraints.txt
7475
# -c requirements/../../../requirements/constraints.txt
76+
# httpcore
77+
# httpx
7578
# requests
7679
charset-normalizer==3.4.1
7780
# via requests
@@ -109,10 +112,32 @@ greenlet==3.1.1
109112
# via sqlalchemy
110113
grpcio==1.70.0
111114
# via opentelemetry-exporter-otlp-proto-grpc
115+
h11==0.16.0
116+
# via httpcore
117+
httpcore==1.0.9
118+
# via httpx
119+
httpx==0.28.1
120+
# via
121+
# -c requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
122+
# -c requirements/../../../packages/models-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
123+
# -c requirements/../../../packages/models-library/requirements/../../../requirements/constraints.txt
124+
# -c requirements/../../../packages/postgres-database/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
125+
# -c requirements/../../../packages/postgres-database/requirements/../../../requirements/constraints.txt
126+
# -c requirements/../../../packages/service-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
127+
# -c requirements/../../../packages/service-library/requirements/../../../packages/models-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
128+
# -c requirements/../../../packages/service-library/requirements/../../../packages/models-library/requirements/../../../requirements/constraints.txt
129+
# -c requirements/../../../packages/service-library/requirements/../../../packages/settings-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
130+
# -c requirements/../../../packages/service-library/requirements/../../../packages/settings-library/requirements/../../../requirements/constraints.txt
131+
# -c requirements/../../../packages/service-library/requirements/../../../requirements/constraints.txt
132+
# -c requirements/../../../packages/settings-library/requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
133+
# -c requirements/../../../packages/settings-library/requirements/../../../requirements/constraints.txt
134+
# -c requirements/../../../requirements/constraints.txt
135+
# -r requirements/_base.in
112136
idna==3.10
113137
# via
114138
# anyio
115139
# email-validator
140+
# httpx
116141
# requests
117142
# yarl
118143
importlib-metadata==8.5.0

packages/simcore-sdk/src/simcore_sdk/node_ports_common/file_io_utils.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
from typing import IO, Any, Final, Protocol, runtime_checkable
88

99
import aiofiles
10+
import httpx
1011
from aiohttp import (
1112
ClientConnectionError,
1213
ClientError,
13-
ClientPayloadError,
1414
ClientResponse,
1515
ClientResponseError,
1616
ClientSession,
@@ -39,6 +39,7 @@
3939
from tqdm.contrib.logging import tqdm_logging_redirect
4040
from yarl import URL
4141

42+
from ..config.http_clients import client_request_settings
4243
from . import exceptions
4344
from .constants import CHUNK_SIZE
4445

@@ -148,13 +149,13 @@ async def __call__(self, log: str) -> None: ...
148149

149150
async def _file_chunk_writer(
150151
file: Path,
151-
response: ClientResponse,
152+
response: httpx.Response,
152153
pbar: tqdm,
153154
io_log_redirect_cb: LogRedirectCB | None,
154155
progress_bar: ProgressBarData,
155156
):
156157
async with aiofiles.open(file, "wb") as file_pointer:
157-
while chunk := await response.content.read(CHUNK_SIZE):
158+
async for chunk in response.aiter_bytes(CHUNK_SIZE):
158159
await file_pointer.write(chunk)
159160
if io_log_redirect_cb and pbar.update(len(chunk)):
160161
with log_catch(_logger, reraise=False):
@@ -172,7 +173,6 @@ async def _file_chunk_writer(
172173

173174

174175
async def download_link_to_file(
175-
session: ClientSession,
176176
url: URL,
177177
file_path: Path,
178178
*,
@@ -185,16 +185,25 @@ async def download_link_to_file(
185185
reraise=True,
186186
wait=wait_exponential(min=1, max=10),
187187
stop=stop_after_attempt(num_retries),
188-
retry=retry_if_exception_type(ClientConnectionError),
188+
retry=retry_if_exception_type(httpx.TransportError),
189189
before_sleep=before_sleep_log(_logger, logging.WARNING, exc_info=True),
190190
after=after_log(_logger, log_level=logging.ERROR),
191191
):
192192
with attempt:
193193
async with AsyncExitStack() as stack:
194-
response = await stack.enter_async_context(session.get(url))
195-
if response.status == status.HTTP_404_NOT_FOUND:
194+
client = await stack.enter_async_context(
195+
httpx.AsyncClient(
196+
timeout=httpx.Timeout(
197+
client_request_settings.HTTP_CLIENT_REQUEST_TOTAL_TIMEOUT
198+
)
199+
)
200+
)
201+
response = await stack.enter_async_context(
202+
client.stream("GET", f"{url}")
203+
)
204+
if response.status_code == status.HTTP_404_NOT_FOUND:
196205
raise exceptions.InvalidDownloadLinkError(url)
197-
if response.status > _VALID_HTTP_STATUS_CODES:
206+
if response.status_code > _VALID_HTTP_STATUS_CODES:
198207
raise exceptions.TransferError(url)
199208
file_path.parent.mkdir(parents=True, exist_ok=True)
200209
# SEE https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length
@@ -231,7 +240,7 @@ async def download_link_to_file(
231240
sub_progress,
232241
)
233242
_logger.debug("Download complete")
234-
except ClientPayloadError as exc:
243+
except httpx.HTTPError as exc:
235244
raise exceptions.TransferError(url) from exc
236245

237246

packages/simcore-sdk/src/simcore_sdk/node_ports_common/filemanager.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ async def download_path_from_s3(
217217
return await download_file_from_link(
218218
download_link,
219219
local_path,
220-
client_session=session,
221220
io_log_redirect_cb=io_log_redirect_cb,
222221
progress_bar=progress_bar,
223222
)
@@ -229,7 +228,6 @@ async def download_file_from_link(
229228
*,
230229
io_log_redirect_cb: LogRedirectCB | None,
231230
file_name: str | None = None,
232-
client_session: ClientSession | None = None,
233231
progress_bar: ProgressBarData,
234232
) -> Path:
235233
# a download link looks something like:
@@ -242,15 +240,14 @@ async def download_file_from_link(
242240

243241
if io_log_redirect_cb:
244242
await io_log_redirect_cb(f"downloading {local_file_path}, please wait...")
245-
async with ClientSessionContextManager(client_session) as session:
246-
await download_link_to_file(
247-
session,
248-
download_link,
249-
local_file_path,
250-
num_retries=NodePortsSettings.create_from_envs().NODE_PORTS_IO_NUM_RETRY_ATTEMPTS,
251-
io_log_redirect_cb=io_log_redirect_cb,
252-
progress_bar=progress_bar,
253-
)
243+
244+
await download_link_to_file(
245+
download_link,
246+
local_file_path,
247+
num_retries=NodePortsSettings.create_from_envs().NODE_PORTS_IO_NUM_RETRY_ATTEMPTS,
248+
io_log_redirect_cb=io_log_redirect_cb,
249+
progress_bar=progress_bar,
250+
)
254251
if io_log_redirect_cb:
255252
await io_log_redirect_cb(f"download of {local_file_path} complete.")
256253
return local_file_path

services/docker-compose.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,10 +1385,12 @@ services:
13851385
- "--metrics.prometheus.entryPoint=metrics"
13861386
- "--entryPoints.http.address=:80"
13871387
- "--entryPoints.http.forwardedHeaders.insecure"
1388-
- "--entryPoints.http.transport.respondingTimeouts.readTimeout=21600s" #6h, for https://github.com/traefik/traefik/issues/10805 - "--entryPoints.simcore_api.address=:10081"
1388+
- "--entryPoints.http.transport.respondingTimeouts.readTimeout=21600s" #6h, for https://github.com/traefik/traefik/issues/10805 large file uploads
1389+
- "--entryPoints.http.transport.respondingTimeouts.writeTimeout=21600s" #6h, for https://github.com/traefik/traefik/issues/10805 large file downloads
13891390
- "--entryPoints.simcore_api.address=:10081"
13901391
- "--entryPoints.simcore_api.forwardedHeaders.insecure"
1391-
- "--entryPoints.simcore_api.transport.respondingTimeouts.readTimeout=21600s" #6h, for https://github.com/traefik/traefik/issues/10805
1392+
- "--entryPoints.simcore_api.transport.respondingTimeouts.readTimeout=21600s" #6h, for https://github.com/traefik/traefik/issues/10805 large file uploads
1393+
- "--entryPoints.simcore_api.transport.respondingTimeouts.writeTimeout=21600s" #6h, for https://github.com/traefik/traefik/issues/10805 large file downloads
13921394
- "--entryPoints.traefik_monitor.address=:8080"
13931395
- "--entryPoints.traefik_monitor.forwardedHeaders.insecure"
13941396
- "--providers.swarm.endpoint=unix:///var/run/docker.sock"
@@ -1401,6 +1403,14 @@ services:
14011403
- "--tracing.addinternals"
14021404
- "--tracing.otlp=true"
14031405
- "--tracing.otlp.http=true"
1406+
healthcheck:
1407+
# NOTE: this healthcheck to check if traefik is up and running must be run on the ping entrypoint defined in command!
1408+
test: traefik healthcheck --ping --ping.entryPoint=ping --entryPoints.ping.address=:9082
1409+
interval: 10s
1410+
timeout: 5s
1411+
retries: 5
1412+
start_period: 10s
1413+
start_interval: 1s
14041414
volumes:
14051415
# So that Traefik can listen to the Docker events
14061416
- /var/run/docker.sock:/var/run/docker.sock

services/static-webserver/client/source/class/osparc/dashboard/CardBase.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ qx.Class.define("osparc.dashboard.CardBase", {
700700
}
701701

702702
// Block card
703-
const cantReadServices = osparc.study.Utils.getCantExecuteServices(services);
703+
const cantReadServices = osparc.study.Utils.getCantReadServices(services);
704704
if (cantReadServices.length) {
705705
this.setBlocked("UNKNOWN_SERVICES");
706706
const image = "@FontAwesome5Solid/ban/";
@@ -985,8 +985,17 @@ qx.Class.define("osparc.dashboard.CardBase", {
985985
throw new Error("Abstract method called!");
986986
},
987987

988-
_applyMenu: function(value, old) {
989-
throw new Error("Abstract method called!");
988+
_applyMenu: function(menu) {
989+
const menuButton = this.getChildControl("menu-button");
990+
if (menu) {
991+
menuButton.setMenu(menu).set({
992+
appearance: "menu-wider",
993+
position: "bottom-left",
994+
});
995+
osparc.utils.Utils.setIdToWidget(menu, "studyItemMenuMenu");
996+
menu.addListener("appear", () => this.evaluateMenuButtons());
997+
}
998+
menuButton.setVisibility(menu ? "visible" : "excluded");
990999
},
9911000

9921001
_setStudyPermissions: function(accessRights) {

services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -281,19 +281,5 @@ qx.Class.define("osparc.dashboard.GridButtonItem", {
281281
}
282282
}
283283
},
284-
285-
// overridden
286-
_applyMenu: function(menu, old) {
287-
const menuButton = this.getChildControl("menu-button");
288-
if (menu) {
289-
menuButton.setMenu(menu).set({
290-
appearance: "menu-wider",
291-
position: "bottom-left",
292-
});
293-
osparc.utils.Utils.setIdToWidget(menu, "studyItemMenuMenu");
294-
this.evaluateMenuButtons();
295-
}
296-
menuButton.setVisibility(menu ? "visible" : "excluded");
297-
}
298284
}
299285
});

services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -295,18 +295,5 @@ qx.Class.define("osparc.dashboard.ListButtonItem", {
295295
});
296296
});
297297
},
298-
299-
_applyMenu: function(menu, old) {
300-
const menuButton = this.getChildControl("menu-button");
301-
if (menu) {
302-
menuButton.setMenu(menu).set({
303-
appearance: "menu-wider",
304-
position: "bottom-left",
305-
});
306-
osparc.utils.Utils.setIdToWidget(menu, "studyItemMenuMenu");
307-
this.evaluateMenuButtons();
308-
}
309-
menuButton.setVisibility(menu ? "visible" : "excluded");
310-
}
311298
}
312299
});

services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,10 +1598,12 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
15981598
const duplicateStudyButton = this.__getDuplicateMenuButton(studyData);
15991599
menu.add(duplicateStudyButton);
16001600

1601-
const convertToPipelineButton = this.__getConvertToPipelineMenuButton(studyData);
1602-
menu.add(convertToPipelineButton);
1601+
if (writeAccess && osparc.product.Utils.showConvertToPipeline()) {
1602+
const convertToPipelineButton = this.__getConvertToPipelineMenuButton(studyData);
1603+
menu.add(convertToPipelineButton);
1604+
}
16031605

1604-
if (osparc.product.Utils.hasExportCMisEnabled()) {
1606+
if (osparc.product.Utils.showExportCMis()) {
16051607
const exportStudyButton = this.__getExportCMisMenuButton(studyData);
16061608
menu.add(exportStudyButton);
16071609
}

services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
6060
osparc.store.Services.getStudyServices(this._studyData["uuid"])
6161
.then(resp => {
6262
const services = resp["services"];
63-
if (osparc.study.Utils.getCantExecuteServices(services).length) {
63+
if (osparc.study.Utils.getCantReadServices(services).length) {
6464
msg += this.tr("Some services are inaccessible. Please contact the service owner:");
6565
msg += "<br><br>";
6666
}

0 commit comments

Comments
 (0)