Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
fc08d1f
Async Simulation endpoint
Yannicked May 12, 2026
1eb037c
Add migration
Yannicked May 12, 2026
aba96f5
Fix ty
Yannicked May 12, 2026
55d8e53
Remove automatic table creation
Yannicked May 12, 2026
795de15
Add Celery
Yannicked May 18, 2026
e6989d9
Copy files
Yannicked May 19, 2026
d6c654d
Cleanup tasks
Yannicked May 19, 2026
7f9678f
Add tests
Yannicked May 19, 2026
22f35ee
Handle exceptions
Yannicked May 20, 2026
1fbe188
Sanitize path
Yannicked May 20, 2026
dc05598
Cleanup simulations post endpoint
Yannicked May 21, 2026
3fbfea6
Merge branch 'develop' into feature/celery-tasks
Yannicked May 21, 2026
d4fbb52
Add celery documentation
Yannicked May 21, 2026
2fbd598
Update ingestion status migration
Yannicked May 21, 2026
d4e6ac4
Fix typing
Yannicked May 21, 2026
68938a1
Cleanup tests
Yannicked May 28, 2026
03d2abb
Fix issues
Yannicked Jun 2, 2026
af44d84
Test script
Yannicked Jun 2, 2026
a9ed16c
Fix issues with imas data
Yannicked Jun 2, 2026
b60af62
Update test script for IMAS
Yannicked Jun 2, 2026
36b4bfa
Update tests
Yannicked Jun 2, 2026
a7c992e
Merge branch 'develop' into feature/celery-tasks
Yannicked Jun 3, 2026
287d0e1
Update docker files
Yannicked Jun 4, 2026
015242c
Check for master.h5 in hdf5 imas
Yannicked Jun 5, 2026
14967aa
Fix imas backend detection
Yannicked Jun 8, 2026
c21c06c
Fix test
Yannicked Jun 8, 2026
05cf791
Temporarily comment celery worker and beat
Yannicked Jun 8, 2026
fc7c3ef
Add uv lockfile
Yannicked Jun 8, 2026
4fdab64
add docker-compose-pyver.yml, argument PYVER, with_workers profile
Louwrensth Jun 8, 2026
fe146c1
server.port as env/config option
Louwrensth Jun 8, 2026
7854b4d
Dockerfile: explicit uv lock
Louwrensth Jun 8, 2026
95c100b
Update revision string
Yannicked Jun 9, 2026
5b5eb9f
Make mdsplus check superset
Yannicked Jun 9, 2026
c748208
Remove unused model
Yannicked Jun 9, 2026
29935ce
Valiation tests for manifest class
Yannicked Jun 9, 2026
6aa3e6a
Move Manifest and URI to pydantic model
Yannicked Jun 10, 2026
b951b31
Fix issues
Yannicked Jun 10, 2026
febead4
Rename Type to DataType
Yannicked Jun 10, 2026
839f2d7
Ruff
Yannicked Jun 10, 2026
7a057ea
Cleanup
Yannicked Jun 10, 2026
0eb51a3
Remove UDA from template
Yannicked Jun 10, 2026
a99ffff
Remove required sections check
Yannicked Jun 10, 2026
bc00ff9
Fix issues
Yannicked Jun 11, 2026
1137c0e
Add support for netcdf
Yannicked Jun 11, 2026
061b769
Remove urllib dependency
Yannicked Jun 11, 2026
eacea55
Revert "Dockerfile: explicit uv lock"
Louwrensth Jun 12, 2026
5cc55f2
Ruff format
Yannicked Jun 12, 2026
38dabab
newline at end of file
Louwrensth Jun 12, 2026
4451edd
add ./validation path for compose server
Louwrensth Jun 12, 2026
b2a10df
bug: missing server.imas_remote_host
Louwrensth Jun 12, 2026
e05f725
Use SimDBUrl instead of AnyUrl
Yannicked Jun 15, 2026
c7719ff
fix: mock Config.load in task_environment test fixture to fix failing…
Yannicked Jun 16, 2026
83e60b9
style: remove unused imports and format remote_api.py
Yannicked Jun 16, 2026
b949940
Remove empty host=""
Yannicked Jun 18, 2026
efac8d7
Ruff
Yannicked Jun 18, 2026
277a3fb
Add deprecation warning for 'version' field
Yannicked Jun 18, 2026
758f09b
Fix minor nits
Yannicked Jun 18, 2026
ce722e6
Merge branch 'feature/pydantic-manifest' into feature/v1.3-local-push…
Yannicked Jun 18, 2026
0a98c16
Merge branch 'feature/celery-tasks' into feature/v1.3-local-push-clean
Yannicked Jun 18, 2026
d8578a4
Merge branch 'feature/docker-compose' into feature/v1.3-local-push-clean
Yannicked Jun 18, 2026
19a52bd
feat: local simulation push CLI command, netcdf support, and validati…
Yannicked Jun 18, 2026
23d9034
docs: add local_push feature guide and regenerate CLI documentation
Yannicked Jun 18, 2026
3708b76
docs: add partition configuration guide for push_local
Yannicked Jun 18, 2026
9c936aa
docs: add sdcc root partition mapping example
Yannicked Jun 18, 2026
8e07431
feat: add a vendored resumable HTTP upload client implementing the IE…
Yannicked Jun 18, 2026
f3a5c29
feat: add a server resumable upload endpoint that stages files into t…
Yannicked Jun 18, 2026
1535909
feat: resolve http-partition URIs during ingestion and remove staged …
Yannicked Jun 18, 2026
d6460bd
feat: add the 'simdb simulation push_http' command uploading files wi…
Yannicked Jun 18, 2026
a03b156
chore: configure the http partition and mount its staging directory f…
Yannicked Jun 18, 2026
9716fcf
test: cover the resumable upload client, the server endpoint, and htt…
Yannicked Jun 18, 2026
a5c9ea8
docs: document push_http and regenerate the CLI reference
Yannicked Jun 18, 2026
7969d94
Checksums
Yannicked Jun 19, 2026
31e8636
Ty fixes
Yannicked Jun 19, 2026
39114b1
Fix small issues
Yannicked Jun 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@ updates:
# Check for updates once a week
schedule:
interval: "weekly"
# Group actions version bumps into a single PR
groups:
actions-deps:
patterns:
- "*"

34 changes: 25 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
FROM python:3.7
COPY ./ /tmp/simdb/
RUN cd /tmp/simdb/ && \
pip3 install . && \
pip3 install flask flask_caching flask_cors flask_restx gunicorn psycopg2-binary && \
rm -rf /tmp/simdb

ENTRYPOINT ["gunicorn", "--bind=0.0.0.0:5000", "--workers=1", "simdb.remote.wsgi:app"]
EXPOSE 5000
ARG PYVER=3.12
FROM ghcr.io/astral-sh/uv:python${PYVER}-trixie-slim

ENV UV_NO_DEV=1
ENV SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
libldap2-dev \
libsasl2-dev \
libmagic1 \
&& rm -rf /var/lib/apt/lists/*

COPY uv.lock pyproject.toml alembic.ini ./
COPY src/ ./src/
COPY alembic/ ./alembic/
RUN uv sync --locked --extra all

ENV SIMDB_SITE_CONFIG_PATH=/app/config/simdb.cfg

CMD ["uv", "run", "simdb_server"]

71 changes: 71 additions & 0 deletions alembic/versions/b2c52ee8ff12_add_ingestion_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Add ingestion status

Revision ID: b2c52ee8ff12
Revises: 9e9a4a7cd639
Create Date: 2026-05-11 16:16:03.768893

"""

from typing import Sequence, Union

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "b2c52ee8ff12"
down_revision: Union[str, Sequence[str], None] = "28bee3aa2429"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
conn = op.get_bind()
dialect = conn.dialect.name
if dialect == "postgresql":
op.execute(
"CREATE TYPE ingestionstatus AS ENUM ('QUEUED', 'COPYING', 'COPIED', "
"'VALIDATING', 'VALIDATED', 'COMPLETED', 'COPY_FAILED', "
"'VALIDATION_FAILED')"
)
with op.batch_alter_table("simulations", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"ingestion_status",
sa.Enum(
"QUEUED",
"COPYING",
"COPIED",
"VALIDATING",
"VALIDATED",
"COMPLETED",
"COPY_FAILED",
"VALIDATION_FAILED",
name="ingestionstatus",
),
nullable=True,
)
)
batch_op.add_column(sa.Column("ingestion_version", sa.Integer(), nullable=True))
op.execute(
"UPDATE simulations SET ingestion_status = 'COMPLETED' WHERE ingestion_status "
"IS NULL"
)
op.execute(
"UPDATE simulations SET ingestion_version = 0 WHERE ingestion_version IS NULL"
)
with op.batch_alter_table("simulations", schema=None) as batch_op:
batch_op.alter_column("ingestion_status", nullable=False)
batch_op.alter_column("ingestion_version", nullable=False)


def downgrade() -> None:
"""Downgrade schema."""
with op.batch_alter_table("simulations", schema=None) as batch_op:
batch_op.drop_column("ingestion_version")
batch_op.drop_column("ingestion_status")
conn = op.get_bind()
dialect = conn.dialect.name
if dialect == "postgresql":
op.execute("DROP TYPE ingestionstatus")
37 changes: 37 additions & 0 deletions config/simdb.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[flask]
flask_env = development
debug = True
testing = True
secret_key = CHANGE ME

[authentication]
type=none

[server]
upload_folder = /data/simdb/simulations
port = 5000
ssl_enabled = False
authentication_type = None
admin_password=CHANGE_ME
imas_remote_host = localhost

[database]
type = postgres
host = postgres
port = 5432
username = simdb
password = simdb
database = simdb

[validation]
path = ./validation
auto_validate = True
error_on_fail = True

[celery]
broker_url = redis://redis:6379/0
result_backend = redis://redis:6379/0

[partition]
data = /data/simdb/partition
http = /data/simdb/http
54 changes: 54 additions & 0 deletions docker-compose-pyver.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# This docker-compose-pyver.yml extends the base docker-compose.yml
# to run three web services for different PYVER (3.11 and 3.13, 3.12 is the default)
# but they all use the same redis and postgres service.
# Run `docker compose -f docker-compose-workers.yml up` to start it up.
include:
- docker-compose.yml

services:
migrations-311:
extends:
service: migrations
build:
args:
PYVER: "3.11"

migrations-313:
extends:
service: migrations
build:
args:
PYVER: "3.13"

web-311:
extends:
service: web
build:
args:
PYVER: "3.11"
ports: !override
- "5001:5000"
depends_on: !override
# !override is necessary to remove the original migrations from depends_on
redis:
condition: service_healthy
postgres:
condition: service_healthy
migrations-311:
condition: service_completed_successfully

web-313:
extends:
service: web
build:
args:
PYVER: "3.13"
ports: !override
- "5003:5000"
depends_on: !override
redis:
condition: service_healthy
postgres:
condition: service_healthy
migrations-313:
condition: service_completed_successfully
111 changes: 87 additions & 24 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,96 @@
version: "3.9"
services:
db:
image: postgres
migrations:
build: .
volumes:
- db_data:/var/lib/postgresql/data
- ./config:/app/config:ro
environment:
POSTGRES_DB: simdb
POSTGRES_USER: simdb
POSTGRES_PASSWORD: simdb
simdb:
DATABASE_URL: postgresql+psycopg2://simdb:simdb@postgres:5432/simdb
depends_on:
- postgres
command: uv run alembic upgrade head
restart: "no"

web:
build: .
environment:
SIMDB_DATABASE_TYPE: postgres
SIMDB_DATABASE_HOST: db
SIMDB_DATABASE_PORT: 5432
SIMDB_SERVER_UPLOAD_FOLDER: /simulations
ports:
- "5000:5000"
volumes:
- simulations:/simulations
- ./validation:/app/validation:ro
- ./config:/app/config:ro
- ./tmp/partition_data:/data/simdb/partition:ro
- ./tmp/http:/data/simdb/http
- ./upload_folder:/data/simdb/simulations
depends_on:
- db
nginx:
image: nginx
ports:
- 80:80
redis:
condition: service_healthy
postgres:
condition: service_healthy
migrations:
condition: service_completed_successfully
restart: unless-stopped

worker:
profiles: [with_workers]
# docker compose --profile with_workers enables this service
build: .
command: uv run simdb_worker
volumes:
- ./config:/app/config:ro
- ./tmp/partition_data:/data/simdb/partition:ro
- ./tmp/http:/data/simdb/http
- ./upload_folder:/data/simdb/simulations
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
migrations:
condition: service_completed_successfully
restart: unless-stopped

beat:
profiles: [with_workers]
# docker compose --profile with_workers enables this service
build: .
command: uv run simdb_beat
volumes:
- ./config:/app/config:ro
depends_on:
- simdb
redis:
condition: service_healthy
postgres:
condition: service_healthy
migrations:
condition: service_completed_successfully
restart: unless-stopped

redis:
image: redis:8-alpine
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 5s
retries: 5
restart: unless-stopped

postgres:
image: postgres:16-alpine
environment:
- POSTGRES_USER=simdb
- POSTGRES_PASSWORD=simdb
- POSTGRES_DB=simdb
volumes:
- ./docker/proxy_params:/etc/nginx/proxy_params
- ./docker/simdb.nginx:/etc/nginx/conf.d/default.conf
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U simdb"]
interval: 1s
timeout: 5s
retries: 5
restart: unless-stopped

volumes:
db_data: {}
simulations: {}
redis_data:
postgres_data:

8 changes: 1 addition & 7 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@ BUILDDIR = _build
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help html Makefile

# Copy source files from docs/ into sphinx/ before building (mirrors .readthedocs.yml)
html: Makefile
cp ../*.md $(SOURCEDIR)/ 2>/dev/null || true
cp ../*.svg $(SOURCEDIR)/ 2>/dev/null || true
@$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
Expand Down
Loading