Files
momentry_core/docs/PLAYGROUND_BINARY_IMPLEMENTATION.md

9.0 KiB

Playground Binary Implementation Plan

Item Content
Author Warren
Created 2026-03-23
Document Version V1.0

Version History

Version Date Purpose Operator Tool/Model
V1.0 2026-03-23 Create implementation plan Warren OpenCode

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):

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:

use crate::core::config::REDIS_KEY_PREFIX;

Pattern for each method:

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:activejobs:completed
187 jobs:activejobs: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:

use crate::core::config::REDIS_KEY_PREFIX;

Replace line 10:

// Remove: const KEY_PREFIX: &str = "momentry:cache:";

Update prefixed_key method (line 24):

fn prefixed_key(&self, key: &str) -> String {
    format!("{}cache:{}", REDIS_KEY_PREFIX.as_str(), key)
}

Update tests (lines 161-162):

#[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):

// Before:
#[arg(long, default_value = "3000")]
port: u16,

// After:
#[arg(long)]
port: Option<u16>,

Update Server match arm (around line 2398):

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):

// 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

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:

[[bin]]
name = "momentry_playground"
path = "src/playground.rs"

Add dependency (if not present):

dotenv = "0.15"

Step 7: Create .env.development

# 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:

# 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

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

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

# Production data
redis-cli KEYS "momentry:*"
# Development data
redis-cli KEYS "momentry_dev:*"
# Should be separate

4. Run Both Simultaneously

# 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

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