Files
secs-gem/docker-compose.yml
raphael 99bfa794fc fix(daemon): honour declared SECS-II formats + make service thread-safe
Audit fixes for two real bugs in the gRPC service:

1. Format compliance: to_item() wrote F8/I8 regardless of the variable's
   declared wire format, so values contradicted the S1F11/S1F21 namelists
   (ChamberPressure is F4, WaferCounter U4; the interop trace showed <F8 2.5>
   on the wire). Conversion now targets the declared format — verified
   end-to-end: secsgem-py now receives <F4 2.5> in S6F11.

2. Thread safety: gRPC handler threads called resolve_variable/resolve_event,
   copying live store entries (including Item values) while the io thread
   mutates them. The service now snapshots the immutable name->id/format maps
   at construction (before run_async, per the documented ordering); all writes
   already post to the io thread. Remaining known narrow race (GetControlState
   enum read) documented in DAEMON_ROADMAP.

Also: drop a stale tools/run_interop.sh reference from docker-compose.yml.
Tests: daemon in-process 16/16 (new F4/U4 format assertions), core 459/459,
secsgem-py interop green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 18:35:53 +02:00

123 lines
3.4 KiB
YAML

# All build artifacts live in the named `build` volume (inside Docker), the
# host only provides the source tree mounted read-write at /app.
#
# docker compose build # build the toolchain image
# docker compose run --rm builder # configure + compile
# docker compose run --rm tests # run unit tests
# docker compose up server client # live HSMS demo
x-base: &base
build: .
volumes:
- .:/app
- build:/app/build
services:
builder:
<<: *base
# Put builder on the same network as server/client/equipment_py so
# one-off `docker compose run --rm builder /app/build/secs_interop_probe ...`
# commands can DNS-resolve peer services by their compose name.
networks: [secs]
command:
- bash
- -lc
- >
cmake -S /app -B /app/build -G Ninja -DCMAKE_BUILD_TYPE=Release &&
cmake --build /app/build
tests:
<<: *base
depends_on:
builder:
condition: service_completed_successfully
command: ["ctest", "--test-dir", "/app/build", "--output-on-failure"]
server:
<<: *base
depends_on:
builder:
condition: service_completed_successfully
command: ["/app/build/secs_server", "--port", "5000", "--device", "0"]
networks: [secs]
# No host port publish: the client reaches the server over the `secs`
# Docker network by service name. Uncomment to expose to the host.
# ports:
# - "5000:5000"
client:
<<: *base
depends_on:
builder:
condition: service_completed_successfully
server:
condition: service_started
command: ["/app/build/secs_client", "--host", "server", "--port", "5000", "--device", "0"]
networks: [secs]
# The gRPC daemon: passive HSMS equipment on :5000 plus the gRPC tool API
# on :50051. Used by interop/daemon_interop.py (a gRPC tool + a secsgem-py
# host both drive it) to prove the gRPC<->HSMS bridge against a real host.
gemd:
<<: *base
depends_on:
builder:
condition: service_completed_successfully
command:
- /app/build/secs_gemd
- --port
- "5000"
- --grpc
- "0.0.0.0:50051"
- --config-dir
- /app/data
networks: [secs]
# Python container preloaded with secsgem-py 0.3.0 for cross-validation
# of our C++ HSMS/SECS-II/GEM implementation against the reference library.
interop:
build: ./interop
volumes:
- .:/app
working_dir: /app/interop
networks: [secs]
# secsgem-py running as passive equipment so the C++ active host can
# connect to it (drive with `secs_interop_probe --host equipment_py`).
equipment_py:
build: ./interop
volumes:
- .:/app
working_dir: /app/interop
command: ["python3", "/app/interop/passive_equipment.py", "--port", "5000"]
networks: [secs]
# Server variant for the persistent-spool restart test. Identical to
# `server` but with --spool-dir pointed at a named volume so spooled
# messages survive `docker compose restart server-spool`.
server-spool:
<<: *base
depends_on:
builder:
condition: service_completed_successfully
command:
- /app/build/secs_server
- --port
- "5000"
- --device
- "0"
- --spool-dir
- /spool
volumes:
- .:/app
- build:/app/build
- spool:/spool
networks: [secs]
networks:
secs: {}
volumes:
build: {}
spool: {}