Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
122 changes: 47 additions & 75 deletions .github/workflows/python-examples.yml
Original file line number Diff line number Diff line change
@@ -1,97 +1,69 @@
# .github/workflows/verify_examples.yml
#
# CI for python/examples/01-03 select_values scripts.
# Strategy: download the daily HallD SQLite snapshot so the examples
# run against real data with a proper schema.

name: Python examples verification

on:
push:
branches:
- '*'
branches: ['*']
pull_request:
branches:
- main
branches: [main]

env:
# Single source of truth for the connection string
RCDB_CONNECTION: "sqlite:///${{ github.workspace }}/tmp/rcdb2.sqlite"

jobs:
run-examples:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9"]
# Don't fail the entire job if one example fails
fail-fast: false

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
python-version: "3.9"

- name: Install dependencies
- name: Install rcdb
run: |
python -m pip install --upgrade pip
# Install rcdb and dependencies from pyproject.toml
cd $GITHUB_WORKSPACE/python
pip install --editable .
# Install additional dependencies for examples
pip install jsonpickle
pip install jsonpickle # for writing object example

- name: Setup SQLite for testing
run: |
mkdir -p $GITHUB_WORKSPACE/tmp
touch $GITHUB_WORKSPACE/tmp/test.sqlite.db
echo "RCDB_CONNECTION=sqlite:///$GITHUB_WORKSPACE/tmp/test.sqlite.db" >> $GITHUB_ENV
# - name: Download HallD SQLite snapshot
# run: |
# mkdir -p $GITHUB_WORKSPACE/tmp
# # Future put db creation here

- name: Create database service (MySQL)
if: false # Disabled until we have a proper way to initialize the MySQL database
run: |
# This would be the place to set up an actual MySQL database if needed
# For now, we'll use SQLite for examples that accept a connection string parameter
echo "RCDB_MYSQL_CONNECTION=sqlite:///$GITHUB_WORKSPACE/tmp/test.sqlite.db" >> $GITHUB_ENV

- name: List example files
id: list-examples
run: |
cd $GITHUB_WORKSPACE/python/examples
echo "examples=$(ls -1 example_*.py | tr '\n' ' ')" >> $GITHUB_OUTPUT
# ── Run examples ──────────────────────────────────────────────
# Each example gets its own step so failures are visible per-script.
# continue-on-error keeps the workflow green while showing which
# script had problems (yellow badge instead of silent swallow).

- name: Run basic examples (with in-memory or SQLite DB)
run: |
cd $GITHUB_WORKSPACE/python/examples
echo "Running example_conditions_basic.py"
python example_conditions_basic.py

echo "Running example_conditions_store_array.py"
python example_conditions_store_array.py

echo "Running example_conditions_store_object.py"
python example_conditions_store_object.py

echo "Running example_sqlalchemy_query.py"
python example_sqlalchemy_query.py

echo "Running example_runs_by_date.py (with connection string)"
python example_runs_by_date.py $RCDB_CONNECTION || echo "Skipping - requires properly initialized database"

- name: Run query examples (with offline mode)
run: |
cd $GITHUB_WORKSPACE/python/examples
echo "Running example_simple_queries.py"
python example_simple_queries.py $RCDB_CONNECTION || echo "Skipping - requires properly initialized database"

# The following examples normally use the production database
# We'll try them with the test db, but expect some to fail gracefully
export RCDB_OFFLINE=true
echo "Running examples in offline mode (will show errors but not fail workflow)"

echo "Trying example_cdc_gas_pressure.py"
python example_cdc_gas_pressure.py || echo "Skipping - requires production database"

echo "Trying example_select_halld_values.py"
python example_select_halld_values.py || echo "Skipping - requires production database"

echo "Trying example_select_values.py"
python example_select_values.py || echo "Skipping - requires production database"

- name: Summary
run: |
echo "Examples testing completed. Check logs for any failures."
echo "Note: Some examples are expected to fail if they require a production database connection."
- name: "Example: 01_select_values_simple"
run: python $GITHUB_WORKSPACE/python/examples/01_select_values_simple.py
# Script must read RCDB_CONNECTION env var (see updated examples)

- name: "Example: 02_select_values_extended"
run: python $GITHUB_WORKSPACE/python/examples/02_select_values_extended.py

- name: "Example: 03_select_values_custom_runs"
run: python $GITHUB_WORKSPACE/python/examples/03_select_values_custom_runs.py

- name: "Example: 10_create_conditions_basic"
run: python $GITHUB_WORKSPACE/python/examples/10_create_conditions_basic.py

- name: "Example: 11_crete_conditions_store_array"
run: python $GITHUB_WORKSPACE/python/examples/11_crete_conditions_store_array.py

- name: "Example: 12_create_conditions_store_object"
run: python $GITHUB_WORKSPACE/python/examples/12_create_conditions_store_object.py

- name: "Example: 90_advanced_sqlalchemy_query"
run: python $GITHUB_WORKSPACE/python/examples/90_advanced_sqlalchemy_query.py
2 changes: 1 addition & 1 deletion .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,7 @@ sql/schema.mwb.bak
reqvenv/

python/repomix-output.txt

python/uv.lock

.claude/
3 changes: 2 additions & 1 deletion docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
- [Development guide](development/development.md)
- [Migrate to RCDB2](development/rcdb2-migration.md)
- [DAQ Setup](daq/daq.md)
- [Website](web_site_setup.md)
- [Website install](website/install.md)
- [Muli-Database](website/database-selector.md)



6 changes: 6 additions & 0 deletions docs/development/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ https://github.com/JeffersonLab/rcdb
4. Run ```test_all_rcdb```


## Multi-Database Selector

The web interface supports switching between multiple databases from the browser.
See [Database Selector](development/database-selector.md) for configuration details.


## Publishing on pypi

```bash
Expand Down
3 changes: 3 additions & 0 deletions docs/development/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ Here is a python one-liner that makes the site running at `localhost:3000`
```bash
# assuming current working directoy is rcdb/docs
python3 -m http.server 3000

# Using uv from rcdb repository root
uv --project ./python --directory docs run -m http.server 3000
```

> On windows machines you may have to use `python` instead of `python3`
Expand Down
70 changes: 70 additions & 0 deletions docs/website/database-selector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Multi-Database Selector

The RCDB web interface supports switching between multiple databases from the browser.
When configured, a dropdown selector appears in the navbar allowing users to pick a database.
The selection is saved in a cookie and persists across sessions.

### How It Works

- The Flask app has two config keys: `AVAILABLE_DATABASES` (a dict of `name -> connection_string`)
and `DEFAULT_DATABASE` (the connection string to use when no cookie is set).
- On each request, `before_request()` checks `AVAILABLE_DATABASES`. If non-empty, it reads the
`rcdb_database` cookie to determine which database to connect to.
- If the cookie is missing or invalid, it falls back to `DEFAULT_DATABASE`. If `DEFAULT_DATABASE`
is not in the available list, it logs a warning and uses the first entry.
- When `AVAILABLE_DATABASES` is empty (the default), all behavior is identical to a single-database setup.


## CLI (`rcdb web`)

Use the `--add-db` flag (repeatable) to register named databases:

```bash
rcdb -c mysql+pymysql://rcdb@prodhost/rcdb web \
--add-db "Production=mysql+pymysql://rcdb@prodhost/rcdb" \
--add-db "Test=mysql+pymysql://rcdb@testhost/rcdb_test"
```

- Each `--add-db` value has the format `NAME=CONNECTION_STRING`.
- The `-c` / `--connection` / `RCDB_CONNECTION` value becomes the default database.
- If no `-c` is provided, the first `--add-db` entry is used as the default.


## Server Configuration

### WSGI

Set the config keys directly in the WSGI script:

```python
import rcdb.web

rcdb.web.app.config["AVAILABLE_DATABASES"] = {
"Production": "mysql+pymysql://rcdb@prodhost/rcdb",
"Test": "mysql+pymysql://rcdb@testhost/rcdb_test",
}
rcdb.web.app.config["DEFAULT_DATABASE"] = "mysql+pymysql://rcdb@prodhost/rcdb"

application = rcdb.web.app
```

When `AVAILABLE_DATABASES` is set, the `SQL_CONNECTION_STRING` key is not used
for connection selection (though it should still be set as a fallback).

## UI Behavior

The selector appears to the left of the "Run or min-max" search box in the navbar.
Each option shows the database name and a connection hint (e.g. `Production (rcdb@prodhost)`).

When the user selects a different database:

1. A cookie `rcdb_database` is set (1-year expiry, `SameSite=Lax`).
2. The current page reloads, now connected to the selected database.

## Key Files

| File | Role |
|------|------|
| `python/rcdb/web/__init__.py` | Config defaults, `before_request()` logic, `_connection_hint()` helper |
| `python/rcdb/web/templates/layouts/base.html` | Navbar `<select>` element and JS cookie handler |
| `python/rcdb/cli/web.py` | `--add-db` CLI option parsing |
5 changes: 5 additions & 0 deletions docs/website/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Website

[install.md](install.md ':include')

[database-selector.md](database-selector.md ':include')
40 changes: 22 additions & 18 deletions docs/web_site_setup.md → docs/website/install.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# Installing RCDB Website
# Install on server

Instruction on how to install central RCDB website.

We use RHEL9 + Apache Server + mod_wsgi as the example, as this is what usually is used at Jefferson Lab (now is 2025).
RHEL9 + Apache Server + mod_wsgi is used as the example,
as this is what usually is used at Jefferson Lab (now is 2025).

***Notes:***

- The RCDB web interface requires the proper database schema to be installed
- For production use, consider setting up HTTPS with SSL certificates
- Consider adjusting the number of threads in the WSGIDaemonProcess directive based on your server's capacity and expected load


### Preinstalled docker image
There is [a dockerfile with example Rocky Linux 9](https://github.com/JeffersonLab/rcdb/tree/main/docker/rocky)
(binary compatible with RHEL9) setup with config files. To build and run it:

Expand All @@ -17,15 +26,16 @@ docker run --rm -it --init -p 8888:80 rcdb-rocky:latest
http://localhost:8888/rcdb/
```


- RHEL9 (or compatible) server with Apache HTTP Server installed
- Root access or sudo privileges
- Python 3.9+ (default on RHEL9)
- `mod_wsgi` package for Apache

## Install Required Packages
## Requirements

First, install the necessary packages:
### System Packages

Required system packages:

```bash
# Install Apache and mod_wsgi
Expand All @@ -35,7 +45,7 @@ sudo dnf install httpd python3-mod_wsgi python3-pip python3-devel
sudo systemctl enable --now httpd
```

There are two ways of managing rcdb and dependencies:
There are two ways of managing python rcdb and dependencies:

- Install centrally on the server e.g. via RPM
- Install venv and use mod_wsgi with python and packages from venv
Expand Down Expand Up @@ -68,11 +78,11 @@ dnf install -y \
```


## Install RCDB Library
### Python dependencies

You have two options for installing the RCDB library:

### Option A: System-wide Installation
#### Option A: System-wide Installation

```bash
git clone --depth=1 https://github.com/JeffersonLab/rcdb.git /opt/rcdb
Expand All @@ -93,9 +103,9 @@ pip install rcdb
deactivate
```

## 3. Create the WSGI Script
## WSGI Script

Create a WSGI script at `/group/halld/www/halldwebdev/html/rcdb/rcdb_www.wsgi`:
Example HallD WSGI script is at `/group/halld/www/halldwebdev/html/rcdb/rcdb_www.wsgi`:

If RCDB is installed as a system-wide library:

Expand Down Expand Up @@ -131,7 +141,7 @@ rcdb.web.app.config["SQL_CONNECTION_STRING"] = "mysql://rcdb@hallddb.jlab.org/rc
application = rcdb.web.app
```

## 4. Configure Apache
## Apache Configuration

Create an Apache configuration file at `/etc/httpd/conf.d/rcdb.conf`:

Expand Down Expand Up @@ -164,16 +174,10 @@ Create an Apache configuration file at `/etc/httpd/conf.d/rcdb.conf`:
```


## 5. Restart Apache
**Restart Apache**

```bash
sudo systemctl restart httpd
```

## Additional Notes

- The RCDB web interface requires the proper database schema to be installed
- For production use, consider setting up HTTPS with SSL certificates
- Consider adjusting the number of threads in the WSGIDaemonProcess directive based on your server's capacity and expected load

Now your RCDB web interface should be up and running on your RHEL9 Apache server!
File renamed without changes.
12 changes: 0 additions & 12 deletions python/examples/example_cdc_gas_pressure.py

This file was deleted.

Loading
Loading