257 lines
6 KiB
Markdown
257 lines
6 KiB
Markdown
|
|
# Read-Only and Frozen Modes Guide
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Brainy provides two levels of immutability control for different use cases:
|
||
|
|
|
||
|
|
1. **`readOnly`** - Prevents data mutations while allowing performance optimizations
|
||
|
|
2. **`frozen`** - Completely freezes the database, preventing all changes
|
||
|
|
|
||
|
|
## Quick Start
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// Read-only mode (default behavior - allows optimizations)
|
||
|
|
const db = new BrainyData({
|
||
|
|
readOnly: true // frozen defaults to false
|
||
|
|
})
|
||
|
|
|
||
|
|
// Completely frozen database (no changes at all)
|
||
|
|
const db = new BrainyData({
|
||
|
|
readOnly: true,
|
||
|
|
frozen: true
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
## Understanding the Modes
|
||
|
|
|
||
|
|
### Read-Only Mode (`readOnly: true, frozen: false`)
|
||
|
|
|
||
|
|
This is the **default and recommended** configuration for read-only databases. It provides:
|
||
|
|
|
||
|
|
- ✅ **Data Protection**: No adds, updates, or deletes allowed
|
||
|
|
- ✅ **Performance Optimization**: Index rebalancing and cache updates continue
|
||
|
|
- ✅ **Live Monitoring**: Statistics and metrics stay current
|
||
|
|
- ✅ **Real-time Updates**: Can detect external changes if configured
|
||
|
|
|
||
|
|
**Use cases:**
|
||
|
|
- Production read replicas
|
||
|
|
- Public-facing search APIs
|
||
|
|
- Analytics dashboards
|
||
|
|
- Most read-only scenarios
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
const db = new BrainyData({
|
||
|
|
readOnly: true,
|
||
|
|
// frozen: false (default)
|
||
|
|
realtimeUpdates: {
|
||
|
|
enabled: true, // Still works!
|
||
|
|
interval: 30000
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
// Data mutations are blocked
|
||
|
|
await db.add(data) // ❌ Throws error
|
||
|
|
|
||
|
|
// But optimizations continue
|
||
|
|
await db.getStatistics({ forceRefresh: true }) // ✅ Works
|
||
|
|
await db.flushStatistics() // ✅ Works
|
||
|
|
// Index optimizations happen automatically // ✅ Works
|
||
|
|
```
|
||
|
|
|
||
|
|
### Frozen Mode (`frozen: true`)
|
||
|
|
|
||
|
|
Complete immutability for special scenarios requiring absolutely no changes:
|
||
|
|
|
||
|
|
- ❌ **No Data Changes**: Same as readOnly
|
||
|
|
- ❌ **No Optimizations**: Index remains exactly as-is
|
||
|
|
- ❌ **No Statistics Updates**: Metrics are frozen
|
||
|
|
- ❌ **No Real-time Updates**: All monitoring stopped
|
||
|
|
|
||
|
|
**Use cases:**
|
||
|
|
- Forensic analysis
|
||
|
|
- Compliance/audit snapshots
|
||
|
|
- Deterministic testing
|
||
|
|
- Cryptographic verification
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
const db = new BrainyData({
|
||
|
|
readOnly: true, // Usually set together
|
||
|
|
frozen: true // Complete immutability
|
||
|
|
})
|
||
|
|
|
||
|
|
// Everything is blocked or becomes a no-op
|
||
|
|
await db.add(data) // ❌ Throws error
|
||
|
|
await db.flushStatistics() // ⚠️ No-op (does nothing)
|
||
|
|
// No index changes // ❌ Disabled
|
||
|
|
// No cache updates // ❌ Disabled
|
||
|
|
```
|
||
|
|
|
||
|
|
## Dynamic Mode Changes
|
||
|
|
|
||
|
|
You can change modes at runtime:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
const db = new BrainyData()
|
||
|
|
await db.init()
|
||
|
|
|
||
|
|
// Switch to read-only (optimizations continue)
|
||
|
|
db.setReadOnly(true)
|
||
|
|
console.log(db.isReadOnly()) // true
|
||
|
|
console.log(db.isFrozen()) // false
|
||
|
|
|
||
|
|
// Freeze completely
|
||
|
|
db.setFrozen(true)
|
||
|
|
console.log(db.isFrozen()) // true
|
||
|
|
|
||
|
|
// Unfreeze (real-time updates restart if configured)
|
||
|
|
db.setFrozen(false)
|
||
|
|
|
||
|
|
// Allow writes again
|
||
|
|
db.setReadOnly(false)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Configuration Examples
|
||
|
|
|
||
|
|
### Example 1: High-Performance Read Replica
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
const readReplica = new BrainyData({
|
||
|
|
readOnly: true, // Prevent writes
|
||
|
|
// frozen: false (default - allows optimizations)
|
||
|
|
|
||
|
|
// Enable real-time sync with primary
|
||
|
|
realtimeUpdates: {
|
||
|
|
enabled: true,
|
||
|
|
interval: 10000,
|
||
|
|
updateStatistics: true,
|
||
|
|
updateIndex: true
|
||
|
|
},
|
||
|
|
|
||
|
|
// Aggressive caching for performance
|
||
|
|
cache: {
|
||
|
|
autoTune: true,
|
||
|
|
hotCacheMaxSize: 50000
|
||
|
|
}
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 2: Compliance Snapshot
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
const auditSnapshot = new BrainyData({
|
||
|
|
readOnly: true,
|
||
|
|
frozen: true, // Complete immutability for compliance
|
||
|
|
|
||
|
|
storage: {
|
||
|
|
s3Storage: {
|
||
|
|
bucketName: 'audit-snapshots',
|
||
|
|
// ... S3 credentials
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
// This database will never change, perfect for:
|
||
|
|
// - Legal discovery
|
||
|
|
// - Compliance audits
|
||
|
|
// - Historical analysis
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 3: Testing Environment
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
describe('Search Tests', () => {
|
||
|
|
let db
|
||
|
|
|
||
|
|
beforeAll(async () => {
|
||
|
|
db = new BrainyData({
|
||
|
|
readOnly: true,
|
||
|
|
frozen: true // Deterministic state for tests
|
||
|
|
})
|
||
|
|
await db.init()
|
||
|
|
// Load test data...
|
||
|
|
})
|
||
|
|
|
||
|
|
it('should return consistent results', async () => {
|
||
|
|
// Tests run against unchanging data
|
||
|
|
const results = await db.search('test query')
|
||
|
|
expect(results).toHaveLength(3)
|
||
|
|
})
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
## Migration Guide
|
||
|
|
|
||
|
|
If you're upgrading and using `readOnly`:
|
||
|
|
|
||
|
|
### Previous Behavior (< v0.49.0)
|
||
|
|
```javascript
|
||
|
|
// Old: readOnly prevented ALL changes
|
||
|
|
const db = new BrainyData({ readOnly: true })
|
||
|
|
// No optimizations, no statistics updates
|
||
|
|
```
|
||
|
|
|
||
|
|
### New Behavior (>= v0.49.0)
|
||
|
|
```javascript
|
||
|
|
// New default: readOnly allows optimizations
|
||
|
|
const db = new BrainyData({ readOnly: true })
|
||
|
|
// Optimizations and statistics continue!
|
||
|
|
|
||
|
|
// To get old behavior, add frozen:
|
||
|
|
const db = new BrainyData({
|
||
|
|
readOnly: true,
|
||
|
|
frozen: true // Matches old behavior
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
## Best Practices
|
||
|
|
|
||
|
|
1. **Default to `readOnly` without `frozen`** for most read-only use cases
|
||
|
|
2. **Only use `frozen: true`** when you specifically need complete immutability
|
||
|
|
3. **Consider performance impact** - frozen mode disables beneficial optimizations
|
||
|
|
4. **Use dynamic switching** for temporary freezing during sensitive operations
|
||
|
|
|
||
|
|
## API Reference
|
||
|
|
|
||
|
|
### Configuration Options
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface BrainyDataConfig {
|
||
|
|
// Prevent data mutations (adds, updates, deletes)
|
||
|
|
readOnly?: boolean
|
||
|
|
|
||
|
|
// Completely freeze database (no changes at all)
|
||
|
|
// Default: false (allows optimizations in readOnly mode)
|
||
|
|
frozen?: boolean
|
||
|
|
|
||
|
|
// Other options...
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Methods
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Check current state
|
||
|
|
db.isReadOnly(): boolean
|
||
|
|
db.isFrozen(): boolean
|
||
|
|
|
||
|
|
// Change state dynamically
|
||
|
|
db.setReadOnly(readOnly: boolean): void
|
||
|
|
db.setFrozen(frozen: boolean): void
|
||
|
|
```
|
||
|
|
|
||
|
|
### Behavior Matrix
|
||
|
|
|
||
|
|
| Operation | Normal | ReadOnly | Frozen |
|
||
|
|
|-----------|--------|----------|---------|
|
||
|
|
| Add/Update/Delete | ✅ | ❌ | ❌ |
|
||
|
|
| Search/Get | ✅ | ✅ | ✅ |
|
||
|
|
| Statistics Refresh | ✅ | ✅ | ❌ |
|
||
|
|
| Index Optimization | ✅ | ✅ | ❌ |
|
||
|
|
| Real-time Updates | ✅ | ✅ | ❌ |
|
||
|
|
| Cache Updates | ✅ | ✅ | ❌ |
|
||
|
|
|
||
|
|
## See Also
|
||
|
|
|
||
|
|
- [Cache Configuration Guide](./cache-configuration.md)
|
||
|
|
- [Production Migration Guide](./production-migration-guide.md)
|
||
|
|
- [Real-time Updates Documentation](../technical/REALTIME_UPDATES.md)
|