Clarify folder mounts in docker docs, check monitor paths exist in FileWatcher

This commit is contained in:
Yiorgis Gozadinos 2025-12-19 10:11:26 +02:00
parent fb1d3c97b3
commit 090be293d2
No known key found for this signature in database
6 changed files with 105 additions and 8 deletions

View file

@ -1,6 +1,15 @@
# Changelog
## [Unreleased]
### Fixed
- **File Monitor Path Validation**: Monitor now validates directories exist before watching ([#204](https://github.com/ggozad/haiku.rag/issues/204))
- Provides clear error message pointing to `haiku.rag.yaml` configuration
- Prevents cryptic `FileNotFoundError: No path was found` from watchfiles
- **Docker Documentation**: Improved Docker setup instructions
- Added volume mount examples for config file and documents directory
- Clarified that `monitor.directories` must use container paths, not host paths
## [0.21.0] - 2025-12-18
### Added

View file

@ -44,19 +44,35 @@ Mount your config file and data directory:
```bash
docker run -p 8001:8001 \
-v $(pwd)/haiku.rag.yaml:/app/haiku.rag.yaml \
-v $(pwd)/data:/data \
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
-v /path/to/data:/data \
haiku-rag
```
The container will automatically use the mounted `haiku.rag.yaml` configuration file.
To enable file monitoring, also mount a documents directory:
```bash
docker run -p 8001:8001 \
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
-v /path/to/data:/data \
-v /path/to/docs:/docs \
haiku-rag haiku-rag serve --mcp --monitor
```
Your `haiku.rag.yaml` must reference the **container path** for monitoring:
```yaml
monitor:
directories:
- /docs # Container path, not host path
```
For API keys (OpenAI, Anthropic, etc.), pass them as environment variables:
```bash
docker run -p 8001:8001 \
-v $(pwd)/haiku.rag.yaml:/app/haiku.rag.yaml \
-v $(pwd)/data:/data \
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
-v /path/to/data:/data \
-e OPENAI_API_KEY=your-key-here \
haiku-rag
```

View file

@ -93,7 +93,10 @@ Build locally to include all features and document processing without docling-se
```bash
docker build -f docker/Dockerfile -t haiku-rag .
docker run -p 8001:8001 -v $(pwd)/data:/data haiku-rag
docker run -p 8001:8001 \
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
-v /path/to/data:/data \
haiku-rag
```
See `docker/README.md` for complete build and configuration instructions.
See `docker/README.md` for complete build and configuration instructions, including how to enable file monitoring.

View file

@ -14,13 +14,36 @@ This setup showcases the minimal haiku.rag-slim image combined with external doc
## Quick Start
```bash
# Create required directories
mkdir -p data docs
cp haiku.rag.yaml.example haiku.rag.yaml # Edit as needed
# Create config file from example (required)
cp haiku.rag.yaml.example haiku.rag.yaml
# Start services
docker compose up -d
```
Place documents in `docs/` for automatic indexing.
## Volume Mounts
The docker-compose.yml mounts three volumes:
| Host Path | Container Path | Purpose |
|-----------|---------------|---------|
| `./data` | `/data` | Persistent LanceDB database |
| `./docs` | `/docs` | Documents to monitor and index |
| `./haiku.rag.yaml` | `/app/haiku.rag.yaml` | Configuration file |
**Important:** The `haiku.rag.yaml` config file must exist before running `docker compose up`. Copy it from the example:
```bash
cp haiku.rag.yaml.example haiku.rag.yaml
```
The example config sets `monitor.directories: [/docs]` - this is the **container path**, not your host path. Documents placed in `./docs` on your host will appear at `/docs` inside the container.
## Usage
```bash

View file

@ -90,6 +90,18 @@ class FileWatcher:
self.supported_extensions = get_converter(config).supported_extensions
async def observe(self):
if not self.paths:
logger.warning("No directories configured for monitoring")
return
# Validate all paths exist before attempting to watch
missing_paths = [p for p in self.paths if not Path(p).exists()]
if missing_paths:
raise FileNotFoundError(
f"Monitor directories do not exist: {missing_paths}. "
"Check your haiku.rag.yaml configuration."
)
logger.info(f"Watching files in {self.paths}")
filter = FileFilter(
ignore_patterns=self.ignore_patterns,

View file

@ -440,3 +440,37 @@ async def test_file_watcher_orphan_handles_spaces_in_filenames():
# Should NOT delete the document since file exists
mock_client.delete_document.assert_not_called()
@pytest.mark.asyncio
async def test_file_watcher_observe_raises_on_missing_paths():
"""Test observe() raises FileNotFoundError when directories don't exist."""
mock_client = AsyncMock(spec=HaikuRAG)
test_config = AppConfig(
monitor=MonitorConfig(
directories=[Path("/nonexistent/path/that/does/not/exist")]
)
)
watcher = FileWatcher(client=mock_client, config=test_config)
with pytest.raises(FileNotFoundError) as exc_info:
await watcher.observe()
assert "Monitor directories do not exist" in str(exc_info.value)
assert "haiku.rag.yaml" in str(exc_info.value)
@pytest.mark.asyncio
async def test_file_watcher_observe_returns_early_when_no_directories():
"""Test observe() returns early when no directories are configured."""
mock_client = AsyncMock(spec=HaikuRAG)
test_config = AppConfig(monitor=MonitorConfig(directories=[]))
watcher = FileWatcher(client=mock_client, config=test_config)
# Should return without error when no directories configured
await watcher.observe()
# No documents should have been processed
mock_client.create_document_from_source.assert_not_called()