Files
rfcp/docs/RFCP-Native-Backend-Research.md

234 lines
6.2 KiB
Markdown

# RFCP Native Backend Research
## Executive Summary
**Finding:** The production Electron app already supports native Windows operation without WSL2.
The production build uses PyInstaller to bundle the Python backend as a standalone Windows executable (`rfcp-server.exe`). WSL2 is only used during development. No migration is needed for end users.
---
## Current Architecture
### Development Mode
```
RFCP (Electron dev)
└── Spawns: python -m uvicorn app.main:app --host 127.0.0.1 --port 8090
└── Uses system Python (Windows or WSL2)
└── Requires venv with dependencies
```
### Production Mode (Already Implemented)
```
RFCP.exe (Electron packaged)
└── Spawns: rfcp-server.exe (bundled PyInstaller binary)
└── Self-contained Python + all dependencies
└── No WSL2 required
└── No system Python required
```
---
## Evidence from Codebase
### desktop/main.js (Lines 120-145)
```javascript
function startBackend() {
// Production: use bundled executable
if (isProduction) {
const serverPath = path.join(process.resourcesPath, 'rfcp-server.exe');
if (fs.existsSync(serverPath)) {
backendProcess = spawn(serverPath, [], { ... });
return;
}
}
// Development: use system Python
backendProcess = spawn('python', ['-m', 'uvicorn', 'app.main:app', ...]);
}
```
### installer/rfcp-server.spec (PyInstaller Config)
```python
# Key configuration
a = Analysis(
['run_server.py'],
pathex=[backend_path],
binaries=[],
datas=[
('data/terrain', 'data/terrain'), # Terrain data bundled
],
hiddenimports=[
'uvicorn.logging', 'uvicorn.loops', 'uvicorn.protocols',
'motor', 'pymongo', 'numpy', 'scipy', 'shapely',
# Full list of dependencies
],
)
exe = EXE(
pyz,
a.scripts,
name='rfcp-server',
console=True, # Shows console for debugging
icon='rfcp.ico',
)
```
---
## GPU Acceleration in Production
### Current Status
The PyInstaller bundle **does not include CuPy** by default because:
1. CuPy requires CUDA runtime (large, ~500MB)
2. Not all users have NVIDIA GPUs
3. Binary would be too large for distribution
### Solution Options
**Option A: Ship CPU-only (Current)**
- Production build uses NumPy (CPU) for calculations
- GPU acceleration available only in dev mode or manual install
- Smallest download size (~100MB)
**Option B: Separate GPU Installer**
- Main installer: CPU-only (~100MB)
- Optional GPU addon: Downloads CuPy + CUDA runtime (~600MB)
- Implemented via install_rfcp.py dependency installer
**Option C: CUDA Toolkit Detection**
- Detect if CUDA is already installed on user's system
- If yes, attempt to load CuPy dynamically
- Graceful fallback to NumPy if not available
### Recommendation
Keep Option A (CPU-only production) with Option B available for power users:
1. Default production build works everywhere
2. Users with NVIDIA GPUs can run `install_rfcp.py` to enable GPU acceleration
3. No WSL2 required for either path
---
## Terrain Data Handling
### Current Implementation
Terrain data (SRTM .hgt files) is bundled inside the PyInstaller executable:
```python
datas=[
('data/terrain', 'data/terrain'),
]
```
### Considerations
- Bundled terrain data increases exe size significantly
- Alternative: Download terrain on first use (like current region download system)
- For initial release, bundling common regions is acceptable
---
## Database (MongoDB)
### Production Architecture
The Electron app embeds MongoDB or requires MongoDB to be installed separately.
Options:
1. **Embedded MongoDB** - Ships mongod.exe with the app
2. **MongoDB Atlas** - Cloud database (requires internet)
3. **SQLite** - Switch to file-based database (significant refactor)
4. **In-memory + file persistence** - No MongoDB required (significant refactor)
Current implementation uses Motor (async MongoDB driver). For true standalone operation, consider SQLite migration in future iteration.
---
## Build Process
### Current Build Commands
```bash
# Build backend executable
cd /mnt/d/root/rfcp/backend
pyinstaller ../installer/rfcp-server.spec
# Build Electron app with bundled backend
cd /mnt/d/root/rfcp/installer
./build-win.sh
```
### Output
- `rfcp-server.exe` - Standalone backend (~80MB)
- `RFCP-Setup-{version}.exe` - Full installer with Electron + backend (~150MB)
---
## Testing Native Build
### Test Procedure
1. Build `rfcp-server.exe` via PyInstaller
2. Run directly: `./rfcp-server.exe`
3. Verify API responds: `curl http://localhost:8090/api/health`
4. Verify coverage calculation works
5. Check GPU detection in logs
### Known Issues
1. **First launch slow**: PyInstaller extracts on first run (~5-10 seconds)
2. **Antivirus false positives**: Some AV flags PyInstaller executables
3. **Console window**: Shows black console (use `console=False` for windowless)
---
## Conclusions
### No Migration Needed
The production Electron app already works without WSL2. The current architecture is:
- ✅ Native Windows executable
- ✅ No Python installation required
- ✅ No WSL2 required
- ✅ Self-contained dependencies
### Development vs Production
| Aspect | Development | Production |
|--------|-------------|------------|
| Python | System Python / venv | Bundled via PyInstaller |
| WSL2 | Optional (for testing) | Not required |
| GPU | CuPy if installed | CPU-only (NumPy) |
| MongoDB | Local instance | Embedded or Atlas |
| Terrain | Local data/ folder | Bundled in exe |
### Remaining Work
1. **GPU for production**: Implement Optional GPU addon installer
2. **Smaller package**: On-demand terrain download instead of bundling
3. **Database portability**: Consider SQLite migration for offline-first
4. **Installer polish**: Signed executables, auto-update support
---
## Appendix: Full PyInstaller Hidden Imports
From `installer/rfcp-server.spec`:
```python
hiddenimports=[
'uvicorn.logging',
'uvicorn.loops',
'uvicorn.loops.auto',
'uvicorn.protocols',
'uvicorn.protocols.http',
'uvicorn.protocols.http.auto',
'uvicorn.protocols.websockets',
'uvicorn.protocols.websockets.auto',
'uvicorn.lifespan',
'uvicorn.lifespan.on',
'motor',
'pymongo',
'numpy',
'scipy',
'shapely',
'shapely.geometry',
'shapely.ops',
# ... additional imports
]
```