Sign inSign up

jeffersonlab/btm

By jeffersonlab

•Updated 3 months ago

Beam time manager app

Image
0

7.2K

jeffersonlab/btm repository overview

⁠btm CI Docker

A Jakarta EE 10⁠ web application for managing beam time at Jefferson Lab built with the Smoothness⁠ web template.

Screenshot



⁠Overview

The Beam Time Manager application allows crew chiefs and experimenters to track machine time accounting while allowing management to review reports. The app prompts crew chiefs and experimenters with shift timesheets pre-filled with data estimated via beam position sensor measurements. The app also holds a database view of the NPES schedule, exposes programmatic access via a JSON REST service, and integrates with Program Deputy shift plans⁠ and DTM⁠ to enable prompting timekeepers with the expected plan as well. The timesheets therefore consist of Planned, Measured, and Reported values.

⁠State Timeline

The accelerator program (Physics, Studies, NPES Restore, ACC or Off) is kept as a timeline of intervals, shown on the State Timeline tab with the current program. The app records a program change when the PV named by BTM_PROGRAM_PV changes, and Crew Chiefs can add, change and remove intervals to correct mistakes. Each interval runs until the next one starts, so the timeline has no gaps or overlaps.

Downtime is not part of the timeline: it is recorded in DTM⁠ only. The Measured accelerator program time of a Crew Chief timesheet is calculated from the timeline, and the time DTM has the machine down (blocked events) during Studies, NPES Restore or ACC is counted as Internal Down. Hours that the timeline does not cover, such as those before it was first recorded, are as BOOM measured them. Changing the timeline changes the Measured values of the timesheets it overlaps, but not the Reported values that were already saved.

⁠Quick Start with Compose

  1. Grab project
git clone https://github.com/JeffersonLab/btm
cd btm
  1. Launch Compose⁠
docker compose up
  1. Navigate to page
http://localhost:8080/btm

Note: Login with demo username "jdoe" and password "password".

⁠Ports

The containers publish these ports on the host, listening only on its local address (127.0.0.1), so other computers can't reach the demo database, accounts, and management consoles. To use them from another computer, forward them over SSH, such as ssh -N -L 8443:localhost:8443 -L 8081:localhost:8081 <host> for the app and Keycloak. If another project already uses some of them, or you run a second copy of the demo, set other ports in a .env file next to compose.yaml, which Compose reads, or in the environment:

VariableDefaultPort of
BTM_HTTPS_PORT8443app (HTTPS)
BTM_HTTP_PORT8080app (HTTP)
BTM_MANAGEMENT_PORT9990Wildfly management
BTM_KEYCLOAK_PORT8081Keycloak
BTM_KEYCLOAK_MANAGEMENT_PORT9991Keycloak management
BTM_ORACLE_PORT1521Oracle
BTM_ORACLE_EM_PORT5500Oracle Enterprise Manager
BTM_PUPPET_PORT3000Puppet Show
BTM_SMTP_PORT1025MailHog SMTP
BTM_MAILHOG_PORT8025MailHog web UI
BTM_SOFTIOC_PORT5064soft IOC Channel Access (TCP and UDP)
BTM_SOFTIOC_REPEATER_PORT5065soft IOC CA repeater (TCP and UDP)

The app and Keycloak are set up for the ports you choose, so log in at https://localhost:<BTM_HTTPS_PORT>/btm. The app reaches the soft IOC over the Compose network whatever its host ports are, but a Channel Access client on the host only works with the default soft IOC ports, since the IOC's search replies name port 5064.

Compose names the containers, network, and images after the project's directory, such as btm-oracle-1, so a copy in another directory, such as a git worktree, gets its own.

See: Docker Compose Strategy⁠

⁠Install

This application requires a Java 17+ JVM and standard library to run, plus a Jakarta EE 10 application server (developed with Wildfly).

  1. Install service dependencies⁠
  2. Download Wildfly 37.0.1⁠
  3. Configure⁠ Wildfly and start it
  4. Download btm.war⁠ and deploy it to Wildfly
  5. Navigate your web browser to localhost:8080/btm⁠

⁠Configure

⁠Configtime

Wildfly must be pre-configured before the first deployment of the app. The wildfly bash scripts⁠ can be used to accomplish this. See the Dockerfile⁠ for an example.

Note: In production users often leave multiple instances of the app open per counting house and concurrent hourly refreshes may result in concurrent DB request contention for the BTM connection pool. Bumping up the max allowed concurrent⁠ DB connections can ameliorate this. See Also: https://github.com/JeffersonLab/btm/issues/9#issuecomment-2819393849⁠

⁠Runtime

Uses the Smoothness Environment Variables⁠ plus the following application specific:

NameDescription
LOGBOOK_DEBUGIf set to "true" then TLOG is used as logbook
BTM_EPICS_ADDR_LISTEPICS CA Address List for obtaining time keeping measurements.
BTM_PROGRAM_PVOptional name of the PV with the current accelerator program, which the State Timeline is recorded from. If not set the timeline is only kept by hand.

The value of the BTM_PROGRAM_PV PV must be a string or an enumeration whose label is PHYSICS, STUDIES, RESTORE, ACC or OFF, in any case; NULL is taken as PHYSICS and MD as STUDIES, as BOOM names them in its hourly PVs. Any other value, such as DOWN, is ignored and logged: the current program stays what it was. The demo's soft IOC has such a PV, BOOMCEBAPROGRAM, which you can change to see the timeline follow, for example with docker compose exec softioc caput BOOMCEBAPROGRAM STUDIES.

Host names in BTM_EPICS_ADDR_LIST are looked up when EPICS monitoring starts. While any PV is not connected they are looked up again every 30 seconds, and monitoring restarts if one resolves to an address it did not have before, so an IOC host that DNS did not know at startup, or whose address changed, is picked up without a CA reset.

⁠Database

This application requires an Oracle 19+ database with the following schema⁠ installed. The application server hosting this app must also be configured with a JNDI datasource.

⁠Build

This project is built with Java 21⁠ (compiled to Java 17 bytecode), and uses the Gradle 9⁠ build tool to automatically download dependencies and build the project from source (the full build also requires Docker for the integration tests):

git clone https://github.com/JeffersonLab/btm
cd btm
gradlew build

Note: If you do not already have Gradle installed, it will be installed automatically by the wrapper script included in the source

Note for JLab On-Site Users: Jefferson Lab has an intercepting proxy⁠

See: Docker Development Quick Reference⁠

⁠Test

Run the unit tests without external services:

./gradlew test

The EPICS monitor tests run a synthetic IOC, CAJ's Channel Access server, inside the test JVM, on loopback with free ports and made-up PV names; they contact no other IOC.

Run the database integration tests with Java 21 and a running Docker daemon:

./gradlew integrationTest

On this project's rootless Docker setup, expose the socket to Testcontainers:

DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock ./gradlew integrationTest

The suite under src/integrationTest/java starts a disposable Oracle XE 21.3.0 container with Testcontainers, using the same image as the demo. The first run may take several minutes to download and initialize Oracle. It creates BTM_OWNER and loads the project's Oracle DDL⁠, without Hibernate schema generation. Only synthetic test data is inserted; each test rolls back its transaction. Containers use random names and host ports, no shared volumes, and are removed automatically after the suite. No existing Compose services or external databases are needed.

Coverage includes monthly version ordering, published and tentative schedule selection, inclusive month ranges, schedule creation/publication, and Oracle's missing-day projection (including nulls, numeric/boolean conversion and a DST transition). It also includes the State Timeline's queries and changes, DTM downtime read as time spans, and the accelerator hours calculated from both (including the repeated hour when daylight saving time ends). The tests call services with a real Hibernate EntityManager; they do not exercise WildFly's EJB security/JTA or HTTP.

./gradlew build and ./gradlew check run both suites, including in CI, and therefore require Docker. A missing Docker daemon fails the integration suite instead of skipping it. Reports are written to build/reports/tests/test/index.html and build/reports/tests/integrationTest/index.html. To package the WAR without running checks, use ./gradlew assemble. The Docker image build excludes both test tasks because it runs inside the image builder without a Docker daemon.

⁠Develop

In order to iterate rapidly when making changes it's often useful to run the app directly on the local workstation, perhaps leveraging an IDE. In this scenario run the service dependencies with:

docker compose -f deps.yaml up

Note: The local install of Wildfly should be configured⁠ to proxy connections to services via localhost and therefore the environment variables should contain:

KEYCLOAK_BACKEND_SERVER_URL=http://localhost:8081
FRONTEND_SERVER_URL=https://localhost:8443
BTM_EPICS_ADDR_LIST=localhost

Further, the local DataSource must also leverage localhost port forwarding so the standalone.xml connection-url field should be: jdbc:oracle:thin:@//localhost:1521/xepdb1. These are the default ports⁠; use yours if you set others, except for the soft IOC, which a local Wildfly reaches only on the defaults.

The server⁠ and app⁠ setup scripts can be used to setup a local instance of Wildfly.

⁠Release

  1. Bump the version number in the VERSION file and commit and push to GitHub (using Semantic Versioning⁠).
  2. The CD⁠ GitHub Action should run automatically invoking:
    • The Create release⁠ GitHub Action to tag the source and create release notes summarizing any pull requests. Edit the release notes to add any missing details. A war file artifact is attached to the release.
    • The Publish docker image⁠ GitHub Action to create a new demo Docker image.
    • The Deploy to JLab⁠ GitHub Action to deploy to the JLab test environment.

⁠Deploy

The deploy to JLab's acctest is handled automatically via the release workflow.

At JLab this app is found at ace.jlab.org/btm⁠ and internally at acctest.acc.jlab.org/btm⁠. However, those servers are proxies for wildfly3.acc.jlab.org and wildflytest3.acc.jlab.org respectively. A deploy script⁠ is provided on each server to automate wget and deploy. Example:

/root/setup/deploy.sh btm v1.2.3

JLab Internal Docs: RHEL9 Wildfly⁠

⁠See Also

Tag summary

Content type

Image

Digest

sha256:2c654976a…

Size

1.2 GB

Last updated

3 months ago

docker pull jeffersonlab/btm