feat: add momentry_playground binary for development
- Add separate momentry_playground binary with distinct configuration - Production (momentry): Port 3002, Redis prefix 'momentry:' - Development (momentry_playground): Port 3003, Redis prefix 'momentry_dev:' - Add SERVER_PORT and REDIS_KEY_PREFIX config via environment variables - Replace all hardcoded Redis key prefixes with configurable values - Create .env.development for playground environment settings - Update .env with production defaults - Add dotenv dependency for environment file loading Configuration isolation allows running both binaries simultaneously without port conflicts or Redis key collisions.
This commit is contained in:
376
docs/PLAYGROUND_BINARY_IMPLEMENTATION.md
Normal file
376
docs/PLAYGROUND_BINARY_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,376 @@
|
||||
# Playground Binary Implementation Plan
|
||||
|
||||
## Overview
|
||||
|
||||
Create separate `momentry_playground` binary with distinct configuration from `momentry` (production).
|
||||
|
||||
| Aspect | Production (`momentry`) | Development (`momentry_playground`) |
|
||||
|--------|------------------------|-------------------------------------|
|
||||
| **Port** | 3002 | 3003 |
|
||||
| **Redis Prefix** | `momentry:` | `momentry_dev:` |
|
||||
| **Worker** | Enabled | Disabled |
|
||||
| **Purpose** | Production deployment | Testing/Development |
|
||||
|
||||
---
|
||||
|
||||
## Files to Modify
|
||||
|
||||
```
|
||||
Files Changed: 6 files (+1 new)
|
||||
├── src/core/config.rs ← Add server_port(), redis_key_prefix()
|
||||
├── src/core/db/redis_client.rs ← Replace hardcoded prefixes
|
||||
├── src/core/cache/redis_cache.rs ← Use configurable prefix
|
||||
├── src/main.rs ← Update CLI defaults
|
||||
├── src/playground.rs ← NEW: Development binary
|
||||
├── Cargo.toml ← Add new binary
|
||||
└── .env.development ← NEW: Dev environment config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Update `src/core/config.rs`
|
||||
|
||||
Add after line 51 (after `MEDIA_BASE_URL`):
|
||||
|
||||
```rust
|
||||
pub static SERVER_PORT: Lazy<u16> = Lazy::new(|| {
|
||||
env::var("MOMENTRY_SERVER_PORT")
|
||||
.unwrap_or_else(|_| "3002".to_string())
|
||||
.parse()
|
||||
.unwrap_or(3002)
|
||||
});
|
||||
|
||||
pub static REDIS_KEY_PREFIX: Lazy<String> = Lazy::new(|| {
|
||||
env::var("MOMENTRY_REDIS_PREFIX")
|
||||
.unwrap_or_else(|_| "momentry:".to_string())
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Update `src/core/db/redis_client.rs`
|
||||
|
||||
Replace all hardcoded `momentry:` prefixes with configurable prefix.
|
||||
|
||||
**Import at top:**
|
||||
```rust
|
||||
use crate::core::config::REDIS_KEY_PREFIX;
|
||||
```
|
||||
|
||||
**Pattern for each method:**
|
||||
```rust
|
||||
let prefix = REDIS_KEY_PREFIX.as_str();
|
||||
let key = format!("{}job:{}", prefix, uuid);
|
||||
```
|
||||
|
||||
**Affected lines:**
|
||||
|
||||
| Line | Key Pattern |
|
||||
|------|-------------|
|
||||
| 47 | `job:{uuid}` |
|
||||
| 81, 109 | `job:{uuid}:processor:{processor}` |
|
||||
| 136, 146 | `progress:{uuid}` |
|
||||
| 172 | `jobs:active` |
|
||||
| 179 | `jobs:active` → `jobs:completed` |
|
||||
| 187 | `jobs:active` → `jobs:failed` |
|
||||
| 194 | `jobs:active` |
|
||||
| 201, 208 | `health:momentry_core` |
|
||||
| 214 | `monitor:job:{uuid}` |
|
||||
| 242, 300 | `errors:{uuid}` |
|
||||
| 258, 281 | `anomaly:alerts`, `anomaly:key:{key_id}` |
|
||||
| 317, 346, 364, 392, 397 | `worker:job:{uuid}...` |
|
||||
| 406, 410 | `worker:job:*` |
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Update `src/core/cache/redis_cache.rs`
|
||||
|
||||
**Import:**
|
||||
```rust
|
||||
use crate::core::config::REDIS_KEY_PREFIX;
|
||||
```
|
||||
|
||||
**Replace line 10:**
|
||||
```rust
|
||||
// Remove: const KEY_PREFIX: &str = "momentry:cache:";
|
||||
```
|
||||
|
||||
**Update `prefixed_key` method (line 24):**
|
||||
```rust
|
||||
fn prefixed_key(&self, key: &str) -> String {
|
||||
format!("{}cache:{}", REDIS_KEY_PREFIX.as_str(), key)
|
||||
}
|
||||
```
|
||||
|
||||
**Update tests (lines 161-162):**
|
||||
```rust
|
||||
#[test]
|
||||
fn test_prefixed_key() {
|
||||
// Note: This test will use the configured prefix
|
||||
let cache = RedisCache::new().unwrap();
|
||||
// With default prefix "momentry:"
|
||||
assert_eq!(cache.prefixed_key("test"), "momentry:cache:test");
|
||||
assert_eq!(cache.prefixed_key("video:abc"), "momentry:cache:video:abc");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Update `src/main.rs`
|
||||
|
||||
**Change CLI defaults (Lines 691-695):**
|
||||
|
||||
```rust
|
||||
// Before:
|
||||
#[arg(long, default_value = "3000")]
|
||||
port: u16,
|
||||
|
||||
// After:
|
||||
#[arg(long)]
|
||||
port: Option<u16>,
|
||||
```
|
||||
|
||||
**Update Server match arm (around line 2398):**
|
||||
|
||||
```rust
|
||||
Commands::Server { host, port } => {
|
||||
let port = port.unwrap_or_else(|| *crate::core::config::SERVER_PORT);
|
||||
momentry_core::api::start_server(&host, port).await?;
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
**Update Redis key usage (Line 1098):**
|
||||
|
||||
```rust
|
||||
// Before:
|
||||
let key = format!("momentry:job:{}:processor:{}", uuid, processor);
|
||||
|
||||
// After:
|
||||
let key = format!(
|
||||
"{}job:{}:processor:{}",
|
||||
crate::core::config::REDIS_KEY_PREFIX.as_str(),
|
||||
uuid,
|
||||
processor
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Create `src/playground.rs`
|
||||
|
||||
```rust
|
||||
use anyhow::{Context, Result};
|
||||
use clap::{Parser, Subcommand};
|
||||
// ... same imports as main.rs ...
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// Load development environment first
|
||||
dotenv::from_filename(".env.development").ok();
|
||||
|
||||
tracing_subscriber::fmt::init();
|
||||
tracing::info!("Starting momentry_playground (development binary)");
|
||||
tracing::info!("Port: {}", *momentry_core::core::config::SERVER_PORT);
|
||||
tracing::info!("Redis prefix: {}", *momentry_core::core::config::REDIS_KEY_PREFIX);
|
||||
|
||||
let cli = Cli::parse();
|
||||
// ... rest identical to main.rs ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 6: Update `Cargo.toml`
|
||||
|
||||
**Add after line 90:**
|
||||
|
||||
```toml
|
||||
[[bin]]
|
||||
name = "momentry_playground"
|
||||
path = "src/playground.rs"
|
||||
```
|
||||
|
||||
**Add dependency (if not present):**
|
||||
|
||||
```toml
|
||||
dotenv = "0.15"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 7: Create `.env.development`
|
||||
|
||||
```bash
|
||||
# Development Environment Configuration
|
||||
# Used by: momentry_playground binary
|
||||
|
||||
# Server Configuration
|
||||
MOMENTRY_SERVER_PORT=3003
|
||||
MOMENTRY_REDIS_PREFIX=momentry_dev:
|
||||
|
||||
# Worker Configuration (disabled for development)
|
||||
MOMENTRY_WORKER_ENABLED=false
|
||||
MOMENTRY_MAX_CONCURRENT=1
|
||||
MOMENTRY_POLL_INTERVAL=10
|
||||
|
||||
# Database (can use separate dev database)
|
||||
DATABASE_URL=postgres://accusys@localhost:5432/momentry
|
||||
MONGODB_URL=mongodb://accusys:Test3200Test3200@localhost:27017/admin
|
||||
|
||||
# Redis
|
||||
REDIS_URL=redis://:accusys@localhost:6379
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 8: Update `.env` (Production)
|
||||
|
||||
Add these lines:
|
||||
|
||||
```bash
|
||||
# Production Environment Configuration
|
||||
# Used by: momentry binary
|
||||
|
||||
# Server Configuration
|
||||
MOMENTRY_SERVER_PORT=3002
|
||||
MOMENTRY_REDIS_PREFIX=momentry:
|
||||
|
||||
# Worker Configuration
|
||||
MOMENTRY_WORKER_ENABLED=true
|
||||
MOMENTRY_MAX_CONCURRENT=2
|
||||
MOMENTRY_POLL_INTERVAL=5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### 1. Build and Run Production Binary
|
||||
|
||||
```bash
|
||||
cargo build --release --bin momentry
|
||||
cargo run --bin momentry -- server
|
||||
# Expected: Listening on http://127.0.0.1:3002
|
||||
|
||||
cargo run --bin momentry -- worker
|
||||
# Expected: Worker started with momentry: prefix
|
||||
```
|
||||
|
||||
### 2. Build and Run Development Binary
|
||||
|
||||
```bash
|
||||
cargo build --bin momentry_playground
|
||||
cargo run --bin momentry_playground -- server
|
||||
# Expected: Listening on http://127.0.0.1:3003
|
||||
```
|
||||
|
||||
### 3. Verify Redis Key Isolation
|
||||
|
||||
```bash
|
||||
# Production data
|
||||
redis-cli KEYS "momentry:*"
|
||||
# Development data
|
||||
redis-cli KEYS "momentry_dev:*"
|
||||
# Should be separate
|
||||
```
|
||||
|
||||
### 4. Run Both Simultaneously
|
||||
|
||||
```bash
|
||||
# Terminal 1: Production
|
||||
cargo run --bin momentry -- server
|
||||
|
||||
# Terminal 2: Development
|
||||
cargo run --bin momentry_playground -- server
|
||||
|
||||
# Both should run without port conflicts
|
||||
```
|
||||
|
||||
### 5. Unit Tests
|
||||
|
||||
```bash
|
||||
cargo test --lib
|
||||
# All tests should pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Redis Key Structure
|
||||
|
||||
### Production (`momentry:`)
|
||||
|
||||
```
|
||||
momentry:job:{uuid} # Job status
|
||||
momentry:job:{uuid}:processor:{name} # Processor progress
|
||||
momentry:progress:{uuid} # Progress pub/sub
|
||||
momentry:jobs:active # Active job set
|
||||
momentry:jobs:completed # Completed job set
|
||||
momentry:jobs:failed # Failed job set
|
||||
momentry:health:momentry_core # Health status
|
||||
momentry:cache:{key} # Cache entries
|
||||
momentry:worker:job:{uuid} # Worker job
|
||||
momentry:worker:job:{uuid}:processor:{name}
|
||||
```
|
||||
|
||||
### Development (`momentry_dev:`)
|
||||
|
||||
```
|
||||
momentry_dev:job:{uuid}
|
||||
momentry_dev:job:{uuid}:processor:{name}
|
||||
momentry_dev:progress:{uuid}
|
||||
momentry_dev:jobs:active
|
||||
momentry_dev:jobs:completed
|
||||
momentry_dev:jobs:failed
|
||||
momentry_dev:health:momentry_core
|
||||
momentry_dev:cache:{key}
|
||||
momentry_dev:worker:job:{uuid}
|
||||
momentry_dev:worker:job:{uuid}:processor:{name}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Potential Issues & Solutions
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| `dotenv` crate not in dependencies | Add to Cargo.toml |
|
||||
| Tests use hardcoded prefix | Update tests to use config, or use `#[cfg(test)]` defaults |
|
||||
| Worker starts in playground | Check `MOMENTRY_WORKER_ENABLED=false` in `.env.development` |
|
||||
| Port already in use | Graceful error message with suggestion to use `--port` flag |
|
||||
| Mixed data in Redis | Ensure prefix is loaded before any Redis operations |
|
||||
|
||||
---
|
||||
|
||||
## Files Summary
|
||||
|
||||
| File | Lines Changed | Purpose |
|
||||
|------|---------------|---------|
|
||||
| `src/core/config.rs` | +15 | Add SERVER_PORT and REDIS_KEY_PREFIX |
|
||||
| `src/core/db/redis_client.rs` | ~50 | Replace hardcoded prefixes |
|
||||
| `src/core/cache/redis_cache.rs` | ~10 | Use configurable prefix |
|
||||
| `src/main.rs` | ~15 | Update CLI defaults, Redis key usage |
|
||||
| `src/playground.rs` | NEW (~2800) | Development binary |
|
||||
| `Cargo.toml` | +4 | Add binary definition |
|
||||
| `.env.development` | NEW (~20) | Development environment |
|
||||
|
||||
**Total**: ~60 lines modified + ~2800 lines new file
|
||||
|
||||
---
|
||||
|
||||
## Reference Documents
|
||||
|
||||
| Document | Purpose |
|
||||
|----------|---------|
|
||||
| `docs/SERVICES.md` | Port allocations |
|
||||
| `docs/MOMENTRY_CORE_REDIS_KEYS.md` | Redis key design |
|
||||
| `AGENTS.md` | Code style and conventions |
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Author | Changes |
|
||||
|---------|------|--------|---------|
|
||||
| 1.0 | 2025-03-25 | OpenCode | Initial implementation plan |
|
||||
Reference in New Issue
Block a user