Skip to content

Commit 97ee27a

Browse files
committed
feat: add bluesky queue server and http service docker compose files
1 parent 83a4d9e commit 97ee27a

File tree

12 files changed

+4245
-0
lines changed

12 files changed

+4245
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Bluesky HTTP Server
2+
FROM python:3.11-slim
3+
4+
# Install system dependencies
5+
RUN apt-get update && apt-get install -y \
6+
git \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
# Install bluesky-httpserver and dependencies
10+
RUN pip install --no-cache-dir \
11+
bluesky-httpserver \
12+
uvicorn \
13+
fastapi \
14+
pandas
15+
16+
# Create working directory
17+
WORKDIR /app
18+
19+
# Expose HTTP port
20+
EXPOSE 60610
21+
22+
# Set environment variables
23+
ENV QSERVER_HTTP_SERVER_SINGLE_USER_API_KEY=a
24+
25+
CMD ["uvicorn", "--host", "0.0.0.0", "--port", "60610", "bluesky_httpserver.server:app"]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Bluesky Queue Server (RE Manager)
2+
FROM python:3.11-slim
3+
4+
# Install system dependencies
5+
RUN apt-get update && apt-get install -y \
6+
git \
7+
build-essential \
8+
&& rm -rf /var/lib/apt/lists/*
9+
10+
# Install bluesky-queueserver and dependencies
11+
RUN pip install --no-cache-dir \
12+
bluesky-queueserver \
13+
bluesky \
14+
ophyd \
15+
ipython \
16+
matplotlib \
17+
numpy
18+
19+
# Create working directory
20+
WORKDIR /app
21+
22+
# Copy IPython profile from local directory
23+
COPY ipython-profile/ /root/.ipython/
24+
25+
# Expose port for 0MQ communication
26+
EXPOSE 60615
27+
28+
CMD ["sh", "-c", "start-re-manager --use-ipython-kernel=ON --zmq-publish-console=ON --startup-profile collection_sim --redis-addr=${REDIS_HOST:-redis}:${REDIS_PORT:-6379}"]
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
gg# Bluesky Services Docker Setup
2+
3+
This directory contains Docker configurations for running Bluesky Queue Server and HTTP Server for the Phoebus queue-server application.
4+
5+
## Services
6+
7+
- **queue-server**: Bluesky Queue Server (RE Manager) - manages the execution queue
8+
- **http-server**: Bluesky HTTP Server - provides REST API interface for the Java client
9+
- **redis**: Redis database for queue persistence
10+
11+
## Quick Start
12+
13+
### Option 1: Use Host Redis (if you have Redis running)
14+
```bash
15+
cd services/bluesky-services
16+
docker-compose up -d queue-server http-server
17+
```
18+
19+
### Option 2: Use Container Redis (recommended)
20+
```bash
21+
cd services/bluesky-services
22+
docker-compose --profile container-redis up -d
23+
```
24+
25+
### Common Commands
26+
1. **Check service status:**
27+
```bash
28+
docker-compose ps
29+
```
30+
31+
2. **View logs:**
32+
```bash
33+
docker-compose logs -f
34+
# Or for specific service:
35+
docker-compose logs -f queue-server
36+
```
37+
38+
3. **Stop services:**
39+
```bash
40+
docker-compose down
41+
```
42+
43+
4. **Rebuild after changes:**
44+
```bash
45+
docker-compose build
46+
```
47+
48+
## Accessing Services
49+
50+
- **HTTP Server API**: http://localhost:60610
51+
- **Queue Server ZMQ**: tcp://localhost:60615
52+
- **Redis**: localhost:6380 (when using container Redis)
53+
54+
## API Authentication
55+
56+
The HTTP server uses API key `a` by default. Test the connection:
57+
58+
```bash
59+
# Test status endpoint
60+
curl "http://localhost:60610/api/status?api_key=a"
61+
62+
# Test plans endpoint
63+
curl "http://localhost:60610/api/plans/allowed?api_key=a"
64+
```
65+
66+
## Configuration Files
67+
68+
- **ipython-profile/**: Contains the IPython profile with startup scripts
69+
- **ipython-profile/profile_collection_sim/startup/**: Startup scripts loaded by the queue server
70+
- `00-ophyd.py`: Device definitions
71+
- `05-run-engine.py`: Run engine setup
72+
- `15-plans.py`: Plan definitions
73+
- `99-custom.py`: Custom configurations
74+
- `existing_plans_and_devices.yaml`: Plans and devices configuration
75+
- `user_group_permissions.yaml`: User permissions
76+
77+
## Using with Phoebus
78+
79+
1. Start the containers using the commands above
80+
2. In Phoebus, set the queue server URL to: `http://localhost:60610`
81+
3. Set the API key to: `a`
82+
4. The Java client will connect to the HTTP server, which communicates with the queue server
83+
84+
## Troubleshooting
85+
86+
**Connection timeouts:**
87+
- Ensure both containers are healthy: `docker-compose ps`
88+
- Check queue server logs: `docker-compose logs queue-server`
89+
- Check HTTP server logs: `docker-compose logs http-server`
90+
91+
**Port conflicts:**
92+
- If port 6379 is in use, the container Redis uses port 6380 externally
93+
- If ports 60610 or 60615 are in use, stop any existing bluesky processes
94+
95+
**Rebuild everything:**
96+
```bash
97+
docker-compose down
98+
docker-compose build --no-cache
99+
docker-compose --profile container-redis up -d
100+
```
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
services:
2+
# Optional Redis container - only used if host Redis is not available
3+
redis:
4+
image: redis:7-alpine
5+
container_name: bluesky-redis
6+
ports:
7+
- "6380:6379" # Use different external port to avoid conflicts
8+
command: redis-server --appendonly yes
9+
volumes:
10+
- redis_data:/data
11+
networks:
12+
- bluesky-network
13+
healthcheck:
14+
test: ["CMD", "redis-cli", "ping"]
15+
interval: 10s
16+
timeout: 5s
17+
retries: 5
18+
profiles:
19+
- container-redis # Only start when explicitly requested
20+
21+
queue-server:
22+
build:
23+
context: .
24+
dockerfile: Dockerfile.queue-server
25+
container_name: bluesky-queue-server
26+
ports:
27+
- "60615:60615"
28+
environment:
29+
- REDIS_HOST=redis
30+
- REDIS_PORT=6379
31+
extra_hosts:
32+
- "host.docker.internal:host-gateway" # Allow access to host services
33+
networks:
34+
- bluesky-network
35+
restart: unless-stopped
36+
healthcheck:
37+
test: ["CMD", "python", "-c", "import zmq; c = zmq.Context(); s = c.socket(zmq.REQ); s.connect('tcp://localhost:60615'); s.close(); c.term()"]
38+
interval: 30s
39+
timeout: 10s
40+
retries: 3
41+
start_period: 30s
42+
43+
http-server:
44+
build:
45+
context: .
46+
dockerfile: Dockerfile.http-server
47+
container_name: bluesky-http-server
48+
ports:
49+
- "60610:60610"
50+
environment:
51+
- QSERVER_HTTP_SERVER_SINGLE_USER_API_KEY=a
52+
- QSERVER_ZMQ_CONTROL_ADDRESS=tcp://queue-server:60615
53+
depends_on:
54+
queue-server:
55+
condition: service_healthy
56+
networks:
57+
- bluesky-network
58+
restart: unless-stopped
59+
healthcheck:
60+
test: ["CMD", "curl", "-f", "http://localhost:60610/api/status"]
61+
interval: 30s
62+
timeout: 10s
63+
retries: 3
64+
start_period: 30s
65+
66+
networks:
67+
bluesky-network:
68+
driver: bridge
69+
70+
volumes:
71+
redis_data:
72+
driver: local
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# IPython configuration for collection_sim profile
2+
c = get_config()
3+
4+
# Basic configuration
5+
c.InteractiveShellApp.exec_lines = []
6+
c.InteractiveShellApp.extensions = []
7+
c.TerminalIPythonApp.display_banner = False
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# flake8: noqa
2+
print(f"Loading file {__file__!r}")
3+
4+
# Import some built-in plans
5+
from bluesky.plan_stubs import mv, mvr, null
6+
from ophyd.sim import hw
7+
8+
# Import ALL simulated Ophyd objects in global namespace (borrowed from ophyd.sim)
9+
globals().update(hw().__dict__)
10+
del hw
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# flake8: noqa
2+
print(f"Loading file {__file__!r}")
3+
4+
from bluesky import RunEngine
5+
from bluesky.callbacks.best_effort import BestEffortCallback
6+
7+
from bluesky_queueserver import is_ipython_mode
8+
9+
# Detect if the code is executed in IPython environment and backend uses Qt
10+
ipython_matplotlib = False
11+
try:
12+
import matplotlib
13+
14+
if matplotlib.get_backend().startswith("qt"):
15+
ipython_matplotlib = True
16+
except Exception:
17+
pass
18+
19+
RE = RunEngine()
20+
21+
bec = BestEffortCallback()
22+
if not is_ipython_mode() or not ipython_matplotlib:
23+
bec.disable_plots()
24+
25+
RE.subscribe(bec)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# flake8: noqa
2+
print(f"Loading file {__file__!r}")
3+
4+
from typing import Any, Dict, List, Optional
5+
6+
from bluesky.plans import (
7+
adaptive_scan,
8+
count,
9+
fly,
10+
grid_scan,
11+
inner_product_scan,
12+
list_grid_scan,
13+
list_scan,
14+
log_scan,
15+
ramp_plan,
16+
rel_adaptive_scan,
17+
rel_grid_scan,
18+
rel_list_grid_scan,
19+
rel_list_scan,
20+
rel_log_scan,
21+
rel_scan,
22+
rel_spiral,
23+
rel_spiral_fermat,
24+
rel_spiral_square,
25+
relative_inner_product_scan,
26+
scan,
27+
scan_nd,
28+
spiral,
29+
spiral_fermat,
30+
spiral_square,
31+
tune_centroid,
32+
tweak,
33+
x2x_scan,
34+
)
35+
36+
37+
def marked_up_count(
38+
detectors: List[Any], num: int = 1, delay: Optional[float] = None, md: Optional[Dict[str, Any]] = None
39+
):
40+
return (yield from count(detectors, num=num, delay=delay, md=md))

0 commit comments

Comments
 (0)