syntaxis/docs/surrealdb-quick-start.md

689 lines
14 KiB
Markdown
Raw Permalink Normal View History

# SurrealDB 2.3 Quick Start Guide
**Status**: Production Ready ✅
**Version**: SurrealDB 2.3
**Updated**: November 15, 2025
This guide shows how to quickly get started with SurrealDB 2.3 in syntaxis with different deployment contexts.
---
## Quick Install & Run
### Option 1: Embedded In-Memory (Fastest, No Server)
```bash
# No installation needed - uses embedded library
# Update configs/database.toml:
[surrealdb]
url = "mem://" # In-memory database
namespace = "syntaxis"
database = "projects"
```
```rust
use workspace_core::SurrealDatabase;
#[tokio::main]
async fn main() -> Result<()> {
// Create in-memory database
let db = SurrealDatabase::new_memory().await?;
// Start using database immediately
let projects = db.list_projects().await?;
println!("Projects: {}", projects.len());
Ok(())
}
```
### Option 2: Embedded File-Based (Persistent, No Server)
```bash
# Update configs/database.toml:
[surrealdb]
url = "file:///tmp/surrealdb.db" # RocksDB persistent storage
namespace = "syntaxis"
database = "projects"
```
```rust
let db = SurrealDatabase::new_file("/tmp/surrealdb.db").await?;
```
### Option 3: Server Mode (Full Features, Requires Setup)
#### Install SurrealDB
```bash
# macOS
brew install surrealdb
# Linux/WSL
cargo install surreal
# Windows
choco install surrealdb
# Verify
surreal version
```
#### Start Server
```bash
# Simple in-memory server
surreal start --bind 127.0.0.1:8000 memory
# File-based with persistence
surreal start --bind 127.0.0.1:8000 file:///tmp/surrealdb.db
# With authentication
surreal start \
--bind 127.0.0.1:8000 \
--username admin \
--password your_password \
file:///tmp/surrealdb.db
```
#### Connect from Application
```rust
// Update configs/database.toml:
// [surrealdb]
// url = "ws://localhost:8000"
// username = "admin"
// password = "your_password"
use workspace_core::SurrealDatabase;
#[tokio::main]
async fn main() -> Result<()> {
let db = SurrealDatabase::new_server(
"ws://localhost:8000",
"syntaxis",
"projects",
Some("admin"),
Some("your_password"),
).await?;
Ok(())
}
```
---
## Core Operations
### 1. Create a Project
```rust
use workspace_core::{SurrealDatabase, DbProject};
use chrono::Utc;
use uuid::Uuid;
let db = SurrealDatabase::new_memory().await?;
let project = DbProject {
id: Uuid::new_v4().to_string(),
name: "My Project".to_string(),
version: "0.1.0".to_string(),
description: "A SurrealDB project".to_string(),
project_type: "MultiLang".to_string(),
current_phase: "Creation".to_string(),
created_at: Utc::now().to_rfc3339(),
updated_at: Utc::now().to_rfc3339(),
};
db.create_project(&project).await?;
println!("✓ Project created: {}", project.id);
```
### 2. Retrieve Projects
```rust
// Get all projects
let projects = db.list_projects().await?;
println!("Total projects: {}", projects.len());
// Get specific project
if let Some(project) = db.get_project(&project_id).await? {
println!("Project: {} (Phase: {})", project.name, project.current_phase);
} else {
println!("Project not found");
}
// Get projects by phase
for project in &projects {
if project.current_phase == "Development" {
println!(" - {} (in Development)", project.name);
}
}
```
### 3. Add Checklist Items
```rust
use workspace_core::DbChecklistItem;
let item = DbChecklistItem {
id: Uuid::new_v4().to_string(),
project_id: project.id.clone(),
phase: "Creation".to_string(),
task_id: "setup-1".to_string(),
description: "Initialize project structure".to_string(),
completed: false,
completed_at: None,
created_at: Utc::now().to_rfc3339(),
task_type: "Setup".to_string(),
task_priority: "High".to_string(),
task_due: Some("2025-12-31".to_string()),
task_estimation: Some("2d".to_string()),
task_deps: "[]".to_string(), // Comma-separated IDs
task_note: Some("Remember to test thoroughly".to_string()),
task_name: Some("Setup".to_string()),
};
db.create_checklist_item(&item).await?;
println!("✓ Added checklist item");
```
### 4. Track Progress
```rust
// Get checklist items for a phase
let items = db.get_checklist_items_by_phase(&project_id, "Creation").await?;
let completed = items.iter().filter(|i| i.completed).count();
println!("Progress: {}/{}", completed, items.len());
// Get completion percentage
let percentage = db.get_completion_percentage(&project_id, "Creation").await?;
println!("Phase completion: {:.1}%", percentage);
```
### 5. Record Phase Transition
```rust
use workspace_core::DbPhaseTransition;
let transition = DbPhaseTransition {
id: Uuid::new_v4().to_string(),
project_id: project.id.clone(),
from_phase: "Creation".to_string(),
to_phase: "Development".to_string(),
timestamp: Utc::now().to_rfc3339(),
reason: Some("Initial setup complete".to_string()),
};
db.record_phase_transition(&transition).await?;
println!("✓ Phase transitioned: Creation → Development");
```
### 6. Security Assessment
```rust
use workspace_core::DbSecurityAssessment;
let assessment = DbSecurityAssessment {
id: Uuid::new_v4().to_string(),
project_id: project.id.clone(),
profile: "OWASP".to_string(),
risk_level: "Medium".to_string(),
passed_rules: 45,
failed_rules: 5,
critical_issues: 0,
assessment_date: Utc::now().to_rfc3339(),
};
db.create_security_assessment(&assessment).await?;
println!("✓ Security assessment recorded");
```
---
## Deployment Modes
### Mode 1: Development (In-Memory)
```bash
# Perfect for: Testing, CI/CD, development without server
# In Rust:
let db = SurrealDatabase::new_memory().await?;
# No setup needed!
```
**Pros**:
- No server setup
- Very fast
- Perfect for testing
**Cons**:
- Data lost on restart
- Single process only
---
### Mode 2: Local Development (File-Based)
```bash
# For local development with persistence
# Start server
surreal start --bind 127.0.0.1:8000 file://~/.local/share/surrealdb.db
# In configuration
[surrealdb]
url = "ws://localhost:8000"
```
**Pros**:
- Persistent data
- Can run alongside multiple processes
- Full server features
**Cons**:
- Requires server running
- Single machine only
---
### Mode 3: Docker (Development/Testing)
```bash
# Start with Docker Compose
docker-compose -f docker-compose.surrealdb.yml up -d
# Check if running
docker-compose logs surrealdb
# Configuration
[surrealdb]
url = "ws://surrealdb:8000" # Container hostname
username = "admin"
password = "workspace_password_123"
```
**Pros**:
- Isolated environment
- Reproducible setup
- Matches production
**Cons**:
- Requires Docker
- Slightly more overhead
---
### Mode 4: Kubernetes (Production)
```bash
# Deploy to Kubernetes cluster
cd k8s && ./deploy.sh
# Configuration
[surrealdb]
url = "ws://surrealdb.workspace:8000" # K8s service DNS
username = "admin"
password = "${SURREALDB_PASSWORD}" # From k8s secret
tls_enabled = true
```
**Pros**:
- Production-grade
- Scalable
- Managed infrastructure
**Cons**:
- Complex setup
- Requires K8s knowledge
---
## Configuration Examples
### Example 1: Local Development
**File**: `configs/database.toml`
```toml
[database]
engine = "surrealdb"
[surrealdb]
url = "mem://" # In-memory, no server needed
namespace = "syntaxis"
database = "projects"
max_connections = 5
```
### Example 2: Docker Development
**File**: `configs/database.toml`
```toml
[database]
engine = "surrealdb"
[surrealdb]
url = "ws://surrealdb:8000"
username = "admin"
password = "dev_password"
namespace = "syntaxis"
database = "projects"
max_connections = 10
```
### Example 3: Production (Kubernetes)
**File**: `configs/database.toml`
```toml
[database]
engine = "surrealdb"
[surrealdb]
url = "ws://surrealdb.workspace:8000"
username = "admin"
password = "${SURREALDB_PASSWORD}" # Environment variable
namespace = "syntaxis"
database = "projects"
max_connections = 20
timeout_secs = 60
tls_enabled = true
tls_ca_cert = "/etc/surrealdb/ca.pem"
```
---
## Testing with SurrealDB
### In-Memory Tests
```rust
#[tokio::test]
async fn test_project_lifecycle() {
// No setup needed - in-memory database
let db = SurrealDatabase::new_memory().await.unwrap();
// Create project
let project = DbProject {
id: "test-1".to_string(),
name: "Test Project".to_string(),
// ... other fields ...
};
let created = db.create_project(&project).await.unwrap();
assert_eq!(created.name, "Test Project");
// Verify retrieval
let retrieved = db.get_project("test-1").await.unwrap();
assert!(retrieved.is_some());
}
```
### Server-Mode Tests
```rust
#[tokio::test]
async fn test_with_server() {
// Requires: surreal start --bind 127.0.0.1:8000 memory
let db = SurrealDatabase::new_server(
"ws://localhost:8000",
"syntaxis",
"projects",
None,
None,
).await.unwrap();
// Run your tests...
}
```
### File-Based Tests
```rust
#[tokio::test]
async fn test_persistence() {
let db_path = "/tmp/test_surrealdb.db";
let db = SurrealDatabase::new_file(db_path).await.unwrap();
// Create data
let project = DbProject { /* ... */ };
db.create_project(&project).await.unwrap();
// Reload and verify persistence
let db2 = SurrealDatabase::new_file(db_path).await.unwrap();
let retrieved = db2.get_project(&project.id).await.unwrap();
assert!(retrieved.is_some());
}
```
---
## Switching Between Backends
### SQLite to SurrealDB
```bash
# Step 1: Update configuration
# configs/database.toml - change engine from "sqlite" to "surrealdb"
# Step 2: Start SurrealDB server
surreal start --bind 127.0.0.1:8000 file:///data/surrealdb.db
# Step 3: Run application with new config
RUST_LOG=info cargo run
# Step 4: Migration (if needed)
# See: SURREALDB_2_3_MIGRATION.md
```
### Quick Switching Script
```bash
#!/bin/bash
# Switch between database backends
case "$1" in
sqlite)
echo "Switching to SQLite..."
cp configs/database.toml configs/database.toml.backup
cp configs/database-default.toml configs/database.toml
echo "✓ Using SQLite"
;;
surrealdb)
echo "Switching to SurrealDB..."
cp configs/database.toml configs/database.toml.backup
cp configs/database-surrealdb.toml configs/database.toml
echo "Starting SurrealDB server..."
surreal start --bind 127.0.0.1:8000 memory &
echo "✓ Using SurrealDB"
;;
*)
echo "Usage: $0 {sqlite|surrealdb}"
;;
esac
```
---
## Troubleshooting
### "Connection refused" Error
```bash
# Check if SurrealDB is running
ps aux | grep surreal
# If not, start it
surreal start --bind 127.0.0.1:8000 memory
# Test connection
curl http://localhost:8000/health
# Should return: {"status":"ok"}
```
### "Authentication failed" Error
```rust
// Make sure credentials match server startup
let db = SurrealDatabase::new_server(
"ws://localhost:8000",
"syntaxis",
"projects",
Some("admin"), // Must match --username
Some("your_password"), // Must match --password
).await?;
```
### "Database already in use" Error
```bash
# Port 8000 is already in use
# Use a different port
surreal start --bind 127.0.0.1:8001 memory
# Update configuration
[surrealdb]
url = "ws://localhost:8001" # New port
```
### Slow Queries
```bash
# Enable query logging
surreal start --log debug --bind 127.0.0.1:8000 memory
# Check output for slow queries in logs
```
---
## Common Patterns
### Pattern 1: Batch Operations
```rust
async fn create_multiple_items(
db: &dyn Database,
items: Vec<DbChecklistItem>,
) -> Result<()> {
for item in items {
db.create_checklist_item(&item).await?;
}
Ok(())
}
```
### Pattern 2: Error Handling
```rust
use workspace_core::error::LifecycleError;
match db.get_project(&id).await {
Ok(Some(project)) => println!("Found: {}", project.name),
Ok(None) => println!("Project not found"),
Err(LifecycleError::Database(msg)) => eprintln!("DB error: {}", msg),
Err(e) => eprintln!("Other error: {}", e),
}
```
### Pattern 3: Configuration-Driven
```rust
use workspace_core::DatabaseConfig;
let config = DatabaseConfig::load_from_file("configs/database.toml")?;
let db = match config.engine.as_str() {
"surrealdb" => {
let surreal_config = config.surrealdb.ok_or("No SurrealDB config")?;
SurrealDatabase::new_server(
&surreal_config.url,
&surreal_config.namespace,
&surreal_config.database,
surreal_config.username,
surreal_config.password,
).await?
}
"sqlite" => {
// ... SQLite setup ...
}
_ => return Err("Unknown database engine".into()),
};
```
---
## Performance Tips
### 1. Use Connection Pooling
```toml
[surrealdb]
max_connections = 20 # Tune based on load
timeout_secs = 60 # Increase for slow networks
```
### 2. Batch Operations
```rust
// Good: Multiple operations
for item in items {
db.create_checklist_item(&item).await?;
}
// Could be optimized with batch API (if available)
```
### 3. Index Critical Fields
```surreql
-- In SurrealDB SQL
DEFINE INDEX idx_project_phase ON TABLE projects COLUMNS current_phase;
DEFINE INDEX idx_item_project ON TABLE checklist_items COLUMNS project_id;
```
---
## Next Steps
1. **Choose Deployment Mode**
- Development: `mem://` (in-memory, fastest)
- Testing: `file://` (persistent, local)
- Production: Server mode with Docker/K8s
2. **Configure Application**
- Copy appropriate config template
- Update `configs/database.toml`
- Set environment variables if needed
3. **Test Connection**
- Run: `cargo run -p syntaxis-cli`
- Execute: `syntaxis-cli checklist show`
- Verify: Data is being stored
4. **Learn More**
- [SURREALDB_SETUP_GUIDE.md](SURREALDB_SETUP_GUIDE.md) - Detailed setup
- [SURREALDB_2_3_MIGRATION.md](SURREALDB_2_3_MIGRATION.md) - Migration guide
- [PERSISTENCE_QUICK_START.md](PERSISTENCE_QUICK_START.md) - Generic DB usage
---
## References
- **Official**: https://surrealdb.com/
- **Docs**: https://surrealdb.com/docs
- **GitHub**: https://github.com/surrealdb/surrealdb
- **Docker**: https://hub.docker.com/r/surrealdb/surrealdb
---
**Status**: ✅ Production Ready
**Last Updated**: November 15, 2025
**SurrealDB Version**: 2.3