Skip to content

Commit 214fffb

Browse files
author
Sampsa Penna
committed
Merge branch 'feature/parallel-downloads' into 'devel'
New upload and download implementation Closes #931, #966, and #1137 See merge request sds-dev/sd-connect/swift-browser-ui!158
2 parents 2a43431 + e7704ba commit 214fffb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+3041
-1985
lines changed

.github/config/.finnishwords.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ pyyntö
441441
päivitä
442442
päänäkymään
443443
pääsy
444+
pääsyä
444445
päättyä
445446
rajan
446447
rajattu
@@ -585,6 +586,7 @@ toiminto
585586
toiseen
586587
toiselle
587588
toisen
589+
toisessa
588590
toisesta
589591
toista
590592
toteuttaa

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7171
- (GL #1047) Added redis and vault monitoring to `/health` endpoint
7272
- (GL #947) Added cypress tests for sharing folders
7373
- (GL #987) Added keyboard navigation for all modals in the UI
74+
- (GL #931) Added proper parallel upload and download support
75+
- Move tar archiving to frontend
76+
- Add frontend support for downloading arbitrary files as an archive
77+
- Use msgpack for parsing websocket data
78+
- Separate upload and download workers
79+
- Use direct file system writes if available on system
80+
- Move upload, download fetch calls to workers to reduce messaging overhead
7481

7582
### Changed
7683

@@ -185,6 +192,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
185192
- (GL #1078) Fix overwriting existing files with upload
186193
- (GL #1108) Fix deleting large amount of objects (~100 items) with long names
187194
- (GL #1140) Fix Sharing permissions swapping between options after sharing
195+
- (GL #1125) Remove shared containers if the owner container is deleted
196+
- (GL #966) Fix upload cancel/finish breaking upload and download functions due to `ServiceWorker` issues
197+
- (GL #1137) Fix upload repeatability and worker lifecycle issues leading to upload unavailability
188198

189199
### Removed
190200

dockerfiles/Dockerfile-build-crypt

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1-
# Build wasm encryption
1+
# Build encryption post-script
2+
FROM node:18-alpine3.17 AS WEBPACK_WASM_PREPROCESS
3+
4+
RUN --mount=type=cache,target=/var/cache/apk/ \
5+
apk add git python3
6+
7+
COPY swift_browser_ui_frontend/package.json /root/swift-browser-ui/swift_browser_ui_frontend/package.json
8+
COPY swift_browser_ui_frontend/pnpm-lock.yaml /root/swift-browser-ui/swift_browser_ui_frontend/pnpm-lock.yaml
9+
10+
RUN --mount=type=cache,target=/root/.pnpm-store \
11+
cd /root/swift-browser-ui/swift_browser_ui_frontend/ \
12+
&& npm install -g pnpm@8 \
13+
&& pnpm install --prod
14+
15+
COPY . /root/swift-browser-ui
16+
17+
RUN cd /root/swift-browser-ui/swift_browser_ui_frontend/wasm \
18+
&& mkdir build \
19+
&& npx webpack --config "./wasm-webpack.config.js"
20+
21+
# Build upworker and downworker WebAssembly contents
222
FROM ghcr.io/cscfi/docker-emscripten-crypt4gh:1.2.0 AS WASMCRYPT
323

4-
COPY swift_browser_ui_frontend/wasm/ /src/
24+
COPY --from=WEBPACK_WASM_PREPROCESS /root/swift-browser-ui/swift_browser_ui_frontend/wasm/ /src/
525

626
RUN bash /bin/build_wasm.sh all
727

@@ -20,6 +40,14 @@ RUN --mount=type=cache,target=/root/.pnpm-store \
2040

2141
COPY swift_browser_ui_frontend /root/swift_ui/swift_browser_ui_frontend
2242

43+
# Copy wasm files for build
44+
COPY --from=WASMCRYPT "/src/build/upworker.js" "/root/swift_ui/swift_browser_ui_frontend/public/upworker.js"
45+
COPY --from=WASMCRYPT "/src/build/downworker.js" "/root/swift_ui/swift_browser_ui_frontend/public/downworker.js"
46+
COPY --from=WASMCRYPT "/src/build/upworker-post.js.map" "/root/swift_ui/swift_browser_ui_frontend/public/upworker-post.js.map"
47+
COPY --from=WASMCRYPT "/src/build/downworker-post.js.map" "/root/swift_ui/swift_browser_ui_frontend/public/downworker-post.js.map"
48+
COPY --from=WASMCRYPT "/src/build/upworker.wasm" "/root/swift_ui/swift_browser_ui_frontend/public/upworker.wasm"
49+
COPY --from=WASMCRYPT "/src/build/downworker.wasm" "/root/swift_ui/swift_browser_ui_frontend/public/downworker.wasm"
50+
2351
RUN cd /root/swift_ui/swift_browser_ui_frontend \
2452
&& OIDC_ENABLED=$OIDC_ENABLED pnpm run build
2553

@@ -28,9 +56,13 @@ FROM python:3.11-alpine3.17 as BACKEND
2856
COPY pyproject.toml /root/swift_ui/pyproject.toml
2957
COPY README.md /root/swift_ui/README.md
3058
COPY swift_browser_ui /root/swift_ui/swift_browser_ui
31-
COPY --from=FRONTEND /root/swift_ui/swift_browser_ui_frontend/dist /root/swift_ui/swift_browser_ui_frontend/dist
32-
COPY --from=WASMCRYPT /src/src/libupload.js /root/swift_ui/swift_browser_ui_frontend/dist/libupload.js
33-
COPY --from=WASMCRYPT /src/src/libupload.wasm /root/swift_ui/swift_browser_ui_frontend/dist/libupload.wasm
59+
COPY --from=FRONTEND /root/swift_ui/swift_browser_ui_frontend/dist/ /root/swift_ui/swift_browser_ui_frontend/dist/
60+
COPY --from=WASMCRYPT "/src/build/downworker.wasm" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/downworker.wasm"
61+
COPY --from=WASMCRYPT "/src/build/downworker.js" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/downworker.js"
62+
COPY --from=WASMCRYPT "/src/build/upworker-post.js.map" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/upworker-post.js.map"
63+
COPY --from=WASMCRYPT "/src/build/downworker-post.js.map" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/downworker-post.js.map"
64+
COPY --from=WASMCRYPT "/src/build/upworker.wasm" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/upworker.wasm"
65+
COPY --from=WASMCRYPT "/src/build/upworker.js" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/upworker.js"
3466

3567
RUN --mount=type=cache,target=/root/.cache/pip \
3668
pip install --upgrade pip \

dockerfiles/Dockerfile-build-crypt-devel

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1-
# Build wasm encryption
1+
# Build encryption post-script
2+
FROM node:18-alpine3.17 AS WEBPACK_WASM_PREPROCESS
3+
4+
RUN --mount=type=cache,target=/var/cache/apk/ \
5+
apk add git python3
6+
7+
COPY swift_browser_ui_frontend/package.json /root/swift-browser-ui/swift_browser_ui_frontend/package.json
8+
COPY swift_browser_ui_frontend/pnpm-lock.yaml /root/swift-browser-ui/swift_browser_ui_frontend/pnpm-lock.yaml
9+
10+
RUN --mount=type=cache,target=/root/.pnpm-store \
11+
cd /root/swift-browser-ui/swift_browser_ui_frontend/ \
12+
&& npm install -g pnpm@8 \
13+
&& pnpm install
14+
15+
COPY . /root/swift-browser-ui
16+
17+
RUN cd /root/swift-browser-ui/swift_browser_ui_frontend/wasm \
18+
&& mkdir build \
19+
&& npx webpack --config "./wasm-webpack.config.js"
20+
21+
# Build upworker and downworker WebAssembly contents
222
FROM ghcr.io/cscfi/docker-emscripten-crypt4gh:1.2.0 AS WASMCRYPT
323

4-
COPY swift_browser_ui_frontend/wasm/ /src/
24+
COPY --from=WEBPACK_WASM_PREPROCESS /root/swift-browser-ui/swift_browser_ui_frontend/wasm/ /src/
525

626
RUN bash /bin/build_wasm.sh all
727

@@ -16,10 +36,18 @@ COPY swift_browser_ui_frontend/pnpm-lock.yaml /root/swift_ui/swift_browser_ui_fr
1636
RUN --mount=type=cache,target=/root/.pnpm-store \
1737
cd /root/swift_ui/swift_browser_ui_frontend \
1838
&& npm install -g pnpm@8 \
19-
&& pnpm install --prod
39+
&& pnpm install
2040

2141
COPY . /root/swift_ui/
2242

43+
# Copy wasm files for build
44+
COPY --from=WASMCRYPT "/src/build/upworker.js" "/root/swift_ui/swift_browser_ui_frontend/public/upworker.js"
45+
COPY --from=WASMCRYPT "/src/build/downworker.js" "/root/swift_ui/swift_browser_ui_frontend/public/downworker.js"
46+
COPY --from=WASMCRYPT "/src/build/upworker-post.js.map" "/root/swift_ui/swift_browser_ui_frontend/public/upworker-post.js.map"
47+
COPY --from=WASMCRYPT "/src/build/downworker-post.js.map" "/root/swift_ui/swift_browser_ui_frontend/public/downworker-post.js.map"
48+
COPY --from=WASMCRYPT "/src/build/upworker.wasm" "/root/swift_ui/swift_browser_ui_frontend/public/upworker.wasm"
49+
COPY --from=WASMCRYPT "/src/build/downworker.wasm" "/root/swift_ui/swift_browser_ui_frontend/public/downworker.wasm"
50+
2351
RUN cd /root/swift_ui/swift_browser_ui_frontend \
2452
&& OIDC_ENABLED=$OIDC_ENABLED pnpm run build-devel
2553

@@ -28,9 +56,13 @@ FROM python:3.11-alpine3.17 as BACKEND
2856
COPY pyproject.toml /root/swift_ui/pyproject.toml
2957
COPY README.md /root/swift_ui/README.md
3058
COPY swift_browser_ui /root/swift_ui/swift_browser_ui
31-
COPY --from=FRONTEND /root/swift_ui/swift_browser_ui_frontend/dist /root/swift_ui/swift_browser_ui_frontend/dist
32-
COPY --from=WASMCRYPT /src/src/libupload.js /root/swift_ui/swift_browser_ui_frontend/dist/libupload.js
33-
COPY --from=WASMCRYPT /src/src/libupload.wasm /root/swift_ui/swift_browser_ui_frontend/dist/libupload.wasm
59+
COPY --from=FRONTEND /root/swift_ui/swift_browser_ui_frontend/dist/ /root/swift_ui/swift_browser_ui_frontend/dist/
60+
COPY --from=WASMCRYPT "/src/build/downworker.wasm" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/downworker.wasm"
61+
COPY --from=WASMCRYPT "/src/build/downworker.js" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/downworker.js"
62+
COPY --from=WASMCRYPT "/src/build/upworker-post.js.map" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/upworker-post.js.map"
63+
COPY --from=WASMCRYPT "/src/build/downworker-post.js.map" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/downworker-post.js.map"
64+
COPY --from=WASMCRYPT "/src/build/upworker.wasm" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/upworker.wasm"
65+
COPY --from=WASMCRYPT "/src/build/upworker.js" "/usr/local/lib/python3.11/site-packages/swift_browser_ui/ui/static/upworker.js"
3466

3567
RUN --mount=type=cache,target=/root/.cache/pip \
3668
pip install --upgrade pip \

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies = [
3434
"oidcrp==2.1.4",
3535
"python-swiftclient==4.4.0",
3636
"uvloop==0.18.0",
37+
"msgpack==1.0.5",
3738
]
3839

3940
[project.optional-dependencies]

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ keystoneauth1==5.3.0
1010
oidcrp==2.1.4
1111
python-swiftclient==4.4.0
1212
uvloop==0.18.0
13+
msgpack==1.0.5

scripts/vault.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ SWIFT_BROWSER_UI_DIR=${SWIFT_BROWSER_UI_DIR:-$ROOT}
2626
function initVault {
2727
cd "$SWIFT_BROWSER_UI_DIR"
2828
export VAULT_ADDR='http://127.0.0.1:8200'
29+
wget --retry-connrefused --waitretry=1 --timeout=60 --spider http://127.0.0.1:8200/v1/sys/health?standbyok=true
2930
vault login token=devroot
3031
vault auth enable approle
3132
vault secrets enable c4ghtransit
@@ -46,7 +47,7 @@ mkdir -p vault/plugins
4647
go build -v -o vault/plugins/c4ghtransit c4ghtransit/cmd/c4ghtransit/main.go
4748

4849
# setup vault for swift-browser-ui in the background, after the server is up
49-
(sleep 1; initVault) 2>&1 &
50+
initVault 2>&1 &
5051

5152
# start vault server in development mode
5253
VAULT_LOG_LEVEL=ERROR exec vault server -dev -dev-plugin-dir=vault/plugins -dev-root-token-id="devroot"

swift_browser_ui/common/vault_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ async def put_header(
382382
:param header: header as b64 encoded string
383383
:param owner: name of the project that owns the container
384384
"""
385+
LOGGER.info(f"Pushing header to vault: {header}")
386+
385387
if owner:
386388
await self._request(
387389
"POST",

swift_browser_ui/ui/api.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,34 @@ async def get_crypted_upload_session(
891891
)
892892

893893

894+
async def get_crypted_upload_socket_info(
895+
request: aiohttp.web.Request,
896+
) -> aiohttp.web.Response:
897+
"""Return a pre-signed upload socket for specified project."""
898+
session = await aiohttp_session.get_session(request)
899+
request.app["Log"].info(
900+
"API call for upload socket signature from "
901+
f"{request.remote}, sess: {session} :: {time.ctime()}"
902+
)
903+
904+
project = ""
905+
if "project" in request.query:
906+
project = request.query["project"]
907+
908+
runner_id = await open_upload_runner_session(request, project=project)
909+
path = f"/cryptic/{request.match_info['project']}"
910+
signature = await sign(28800, path)
911+
912+
return aiohttp.web.json_response(
913+
{
914+
"id": runner_id,
915+
"wsurl": f"{setd['upload_external_endpoint']}{path}".replace("https", "wss"),
916+
"host": setd["upload_external_endpoint"],
917+
"wssignature": signature,
918+
}
919+
)
920+
921+
894922
async def close_upload_session(
895923
request: aiohttp.web.Request,
896924
project: str = "",

swift_browser_ui/ui/front.py

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from swift_browser_ui.ui.settings import setd
1010

1111

12-
async def swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
12+
async def up_swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
1313
"""Serve worker js in worker scope."""
1414
return aiohttp.web.FileResponse(
15-
str(setd["static_directory"]) + "/libupload.js",
15+
str(setd["static_directory"]) + "/upworker.js",
1616
headers={
1717
"Cache-Control": "no-cache, no-store, must-revalidate",
1818
"Pragma": "no-cache",
@@ -22,10 +22,75 @@ async def swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
2222
)
2323

2424

25-
async def swasm(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
25+
async def up_swasm(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
2626
"""Serve worker wasm in worker scope."""
2727
return aiohttp.web.FileResponse(
28-
str(setd["static_directory"]) + "/libupload.wasm",
28+
str(setd["static_directory"]) + "/upworker.wasm",
29+
headers={
30+
"Cache-Control": "no-cache, no-store, must-revalidate",
31+
"Pragma": "no-cache",
32+
"Expires": "0",
33+
"Service-Worker-Allowed": "/",
34+
},
35+
)
36+
37+
38+
async def down_swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
39+
"""Serve worker js in worker scope."""
40+
return aiohttp.web.FileResponse(
41+
str(setd["static_directory"]) + "/downworker.js",
42+
headers={
43+
"Cache-Control": "no-cache, no-store, must-revalidate",
44+
"Pragma": "no-cache",
45+
"Expires": "0",
46+
"Service-Worker-Allowed": "/",
47+
},
48+
)
49+
50+
51+
async def down_swasm(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
52+
"""Serve worker wasm in worker scope."""
53+
return aiohttp.web.FileResponse(
54+
str(setd["static_directory"]) + "/downworker.wasm",
55+
headers={
56+
"Cache-Control": "no-cache, no-store, must-revalidate",
57+
"Pragma": "no-cache",
58+
"Expires": "0",
59+
"Service-Worker-Allowed": "/",
60+
},
61+
)
62+
63+
64+
async def map_down_swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
65+
"""Serve worker js in worker scope."""
66+
return aiohttp.web.FileResponse(
67+
str(setd["static_directory"]) + "/downworker-post.js.map",
68+
headers={
69+
"Cache-Control": "no-cache, no-store, must-revalidate",
70+
"Pragma": "no-cache",
71+
"Expires": "0",
72+
"Service-Worker-Allowed": "/",
73+
},
74+
)
75+
76+
77+
async def map_up_swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
78+
"""Serve worker js in worker scope."""
79+
return aiohttp.web.FileResponse(
80+
str(setd["static_directory"]) + "/upworker-post.js.map",
81+
headers={
82+
"Cache-Control": "no-cache, no-store, must-revalidate",
83+
"Pragma": "no-cache",
84+
"Expires": "0",
85+
"Service-Worker-Allowed": "/",
86+
},
87+
)
88+
89+
90+
async def agg_swjs(_: aiohttp.web.Request) -> aiohttp.web.FileResponse:
91+
"""Serve worker js in worker scope."""
92+
return aiohttp.web.FileResponse(
93+
str(setd["static_directory"]) + "/aggregatorsw.js",
2994
headers={
3095
"Cache-Control": "no-cache, no-store, must-revalidate",
3196
"Pragma": "no-cache",

0 commit comments

Comments
 (0)