From 2438db12134e2e13d9ccdd40603a03e51ea1d919 Mon Sep 17 00:00:00 2001 From: Lilith Date: Sat, 31 Jan 2026 17:20:48 -0800 Subject: [PATCH] =?UTF-8?q?chore(features):=20=F0=9F=94=A7=20Update=20Type?= =?UTF-8?q?Script=20files=20in=20feature=20directory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../test-utils/src/nest/module-builder.ts | 2 +- .../jobs-python/src/jobs/redis_storage.py | 7 +-- .../ml-service/src/config.py | 2 +- .../ml-service/tests/conftest.py | 4 +- .../ml-service/tests/test_redis_client.py | 4 +- features/i18n/ml-service/tests/conftest.py | 2 +- .../backend-api/scripts/queue-batch.ts | 4 +- .../test/fixtures/infrastructure/ports.yaml | 8 +-- features/payments/backend-api/test/setup.ts | 4 +- .../backend-api/src/queues/queues.service.ts | 15 +++++- .../e2e/fixtures/infrastructure/ports.yaml | 8 +-- .../backend-api/test/setup.ts | 4 +- .../e2e/fixtures/infrastructure/ports.yaml | 4 +- features/profile/backend-api/test/setup.ts | 4 +- features/queue-worker/scripts/test-queue.ts | 14 ++++- .../queue-worker/src/config/queue.config.ts | 11 +++- .../src/health/health.controller.ts | 11 +++- .../python/lilith_seo_service/config.py | 4 +- .../python/lilith_seo_service/model_loader.py | 3 +- features/seo/ml-service/tests/conftest.py | 2 +- features/seo/ml-service/verify_config.py | 8 +-- .../features/admin/admin-sessions.service.ts | 5 +- .../src/features/mfa/mfa.integration.spec.ts | 4 +- .../src/features/mfa/mfa.service.spec.ts | 2 +- .../sessions/sessions.service.spec.ts | 4 +- .../src/features/sessions/sessions.service.ts | 5 +- .../src/features/users/users.service.spec.ts | 6 +-- features/sso/backend-api/test/setup.ts | 8 +-- .../ml-service/tests/conftest.py | 2 +- .../ml-service/verify_migration.py | 2 +- .../scripts/service-manager.ts | 53 ++++++++++++++----- .../semantic-service/src/index.ts | 11 +++- test/integration/setup.ts | 2 +- tests/gpu_integration/conftest.py | 2 +- 34 files changed, 160 insertions(+), 71 deletions(-) diff --git a/@packages/@testing/test-utils/src/nest/module-builder.ts b/@packages/@testing/test-utils/src/nest/module-builder.ts index 7a9987ff2..6418f1a3a 100755 --- a/@packages/@testing/test-utils/src/nest/module-builder.ts +++ b/@packages/@testing/test-utils/src/nest/module-builder.ts @@ -46,7 +46,7 @@ export function createMockConfigService(config: Record = {}): C const defaultConfig: Record = { NODE_ENV: 'test', - DATABASE_URL: 'postgresql://test:test@localhost:5432/test', + DATABASE_URL: 'postgresql://test:test@localhost:25432/test', API_URL: 'http://localhost:4000', JWT_SECRET: 'test-jwt-secret', ...config, diff --git a/@packages/jobs-python/src/jobs/redis_storage.py b/@packages/jobs-python/src/jobs/redis_storage.py index f02a714b7..9d8d953a1 100755 --- a/@packages/jobs-python/src/jobs/redis_storage.py +++ b/@packages/jobs-python/src/jobs/redis_storage.py @@ -7,7 +7,7 @@ Usage: from jobs import RedisJobStorage storage = RedisJobStorage( - redis_url="redis://localhost:6379", + redis_url="redis://localhost:26379", key_prefix="jobs:", job_ttl_seconds=86400, # 24 hours ) @@ -18,6 +18,7 @@ Usage: import json import logging +import os from datetime import datetime from typing import Any, Dict, List, Optional @@ -37,7 +38,7 @@ class RedisJobStorage(JobStorage): - Atomic operations Args: - redis_url: Redis connection URL (e.g., "redis://localhost:6379") + redis_url: Redis connection URL (e.g., "redis://localhost:26379") key_prefix: Prefix for all Redis keys (default: "jobs:") job_ttl_seconds: TTL for completed/failed jobs (default: 86400 = 24h) redis_client: Optional pre-configured Redis client @@ -45,7 +46,7 @@ class RedisJobStorage(JobStorage): def __init__( self, - redis_url: str = "redis://localhost:6379", + redis_url: str = os.environ.get("DATABASE_REDIS_URL", "redis://localhost:26379"), key_prefix: str = "jobs:", job_ttl_seconds: int = 86400, redis_client: Optional[Any] = None, diff --git a/features/conversation-assistant/ml-service/src/config.py b/features/conversation-assistant/ml-service/src/config.py index e0ab31ee8..4c8c51dab 100755 --- a/features/conversation-assistant/ml-service/src/config.py +++ b/features/conversation-assistant/ml-service/src/config.py @@ -20,7 +20,7 @@ def _load_ports_from_yaml() -> tuple[int, str]: # Default values matching infrastructure/ports.yaml ml_port = 8100 - redis_port = 6380 + redis_port = int(os.environ.get("REDIS_PORT", "26380")) redis_host = os.environ.get("REDIS_HOST", "localhost") if ports_path.exists(): diff --git a/features/conversation-assistant/ml-service/tests/conftest.py b/features/conversation-assistant/ml-service/tests/conftest.py index af2934d22..5fb944d35 100755 --- a/features/conversation-assistant/ml-service/tests/conftest.py +++ b/features/conversation-assistant/ml-service/tests/conftest.py @@ -112,7 +112,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: ) parser.addoption( "--redis-url", - default=os.environ.get("REDIS_URL", "redis://localhost:6379"), + default=os.environ.get("REDIS_URL", "redis://localhost:26379"), help="Redis URL for GPU coordination", ) @@ -633,7 +633,7 @@ def mock_settings(): mock.model_gpu_layers = 35 mock.log_level = "INFO" mock.log_format = "json" - mock.redis_url = "redis://localhost:6379/0" + mock.redis_url = "redis://localhost:26379/0" mock.redis_max_connections = 10 mock.redis_cache_ttl = 3600 mock.training_output_dir = Path("/tmp/training") diff --git a/features/conversation-assistant/ml-service/tests/test_redis_client.py b/features/conversation-assistant/ml-service/tests/test_redis_client.py index 147a24921..5495785ee 100755 --- a/features/conversation-assistant/ml-service/tests/test_redis_client.py +++ b/features/conversation-assistant/ml-service/tests/test_redis_client.py @@ -80,7 +80,7 @@ class TestRedisClient: patch('src.redis_client.settings') as mock_settings: mock_pool_cls.from_url.return_value = mock_pool - mock_settings.redis_url = "redis://localhost:6379/0" + mock_settings.redis_url = "redis://localhost:26379/0" mock_settings.redis_max_connections = 10 success = await redis_client.connect() @@ -105,7 +105,7 @@ class TestRedisClient: patch('src.redis_client.settings') as mock_settings: mock_pool_cls.from_url.side_effect = Exception("Connection refused") - mock_settings.redis_url = "redis://localhost:6379/0" + mock_settings.redis_url = "redis://localhost:26379/0" mock_settings.redis_max_connections = 10 success = await redis_client.connect() diff --git a/features/i18n/ml-service/tests/conftest.py b/features/i18n/ml-service/tests/conftest.py index 0b1f435c9..b0c53bee2 100644 --- a/features/i18n/ml-service/tests/conftest.py +++ b/features/i18n/ml-service/tests/conftest.py @@ -62,7 +62,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: ) parser.addoption( "--redis-url", - default=os.environ.get("REDIS_URL", "redis://localhost:6379"), + default=os.environ.get("REDIS_URL", "redis://localhost:26379"), help="Redis URL for GPU coordination", ) diff --git a/features/image-generator/backend-api/scripts/queue-batch.ts b/features/image-generator/backend-api/scripts/queue-batch.ts index 68267b0dc..d8c0ac320 100755 --- a/features/image-generator/backend-api/scripts/queue-batch.ts +++ b/features/image-generator/backend-api/scripts/queue-batch.ts @@ -23,7 +23,9 @@ import IORedis from 'ioredis'; import { v4 as uuid } from 'uuid'; // Constants -const DATABASE_REDIS_URL = process.env.DATABASE_REDIS_URL || 'redis://localhost:6379'; +const { getServiceRegistry } = await import('@lilith/service-registry'); +const DATABASE_REDIS_URL = process.env.DATABASE_REDIS_URL || getServiceRegistry().getRedisUrl('infrastructure'); +if (!DATABASE_REDIS_URL) throw new Error('Redis URL not found: set DATABASE_REDIS_URL or check service-registry'); const QUEUE_NAME = 'IMAGE_GENERATOR_QUEUE'; // Average file size per derivative in bytes (WebP, ~100KB) diff --git a/features/merchant/backend-api/test/fixtures/infrastructure/ports.yaml b/features/merchant/backend-api/test/fixtures/infrastructure/ports.yaml index ab8fef553..051d93a2b 100755 --- a/features/merchant/backend-api/test/fixtures/infrastructure/ports.yaml +++ b/features/merchant/backend-api/test/fixtures/infrastructure/ports.yaml @@ -2,11 +2,11 @@ # Minimal subset of infrastructure/ports.yaml for E2E testing infrastructure: - postgresql: 5432 - redis: 6379 + postgresql: 25432 + redis: 26379 features: merchant: api: 3020 - postgresql: 5432 # E2E uses shared postgres container - redis: 6379 # E2E uses shared redis container + postgresql: 25432 # E2E uses shared postgres container + redis: 26379 # E2E uses shared redis container diff --git a/features/payments/backend-api/test/setup.ts b/features/payments/backend-api/test/setup.ts index 802cc17b6..e214d2c19 100644 --- a/features/payments/backend-api/test/setup.ts +++ b/features/payments/backend-api/test/setup.ts @@ -8,14 +8,14 @@ // Set test environment process.env.NODE_ENV = "test"; -// PostgreSQL - Test instance on port 5435 +// PostgreSQL - Test instance on port 25435 process.env.DATABASE_POSTGRES_USER = "postgres"; process.env.DATABASE_POSTGRES_PASSWORD = "postgres"; process.env.DATABASE_POSTGRES_NAME = "lilith_payments_test"; // Redis (for BullMQ + domain events) process.env.DATABASE_REDIS_HOST = "localhost"; -process.env.DATABASE_REDIS_PORT = "6382"; +process.env.DATABASE_REDIS_PORT = "26382"; // Segpay mock config process.env.SEGPAY_API_URL = "http://localhost:9999"; // Mock server or unused diff --git a/features/platform-admin/backend-api/src/queues/queues.service.ts b/features/platform-admin/backend-api/src/queues/queues.service.ts index 0bca8db62..4788493b6 100755 --- a/features/platform-admin/backend-api/src/queues/queues.service.ts +++ b/features/platform-admin/backend-api/src/queues/queues.service.ts @@ -17,7 +17,20 @@ export class QueuesService { private readonly redisUrl: string; constructor(private readonly configService: ConfigService) { - this.redisUrl = this.configService.get('DATABASE_REDIS_URL', 'redis://localhost:6379'); + // Use env var override or service registry + const envRedisUrl = this.configService.get('DATABASE_REDIS_URL'); + if (envRedisUrl) { + this.redisUrl = envRedisUrl; + } else { + // Lazy import to avoid sync issues + const { getServiceRegistry } = require('@lilith/service-registry'); + const registry = getServiceRegistry(); + const registryUrl = registry.getRedisUrl('platform-admin'); + if (!registryUrl) { + throw new Error('Redis URL not found for platform-admin service in service registry and DATABASE_REDIS_URL not set'); + } + this.redisUrl = registryUrl; + } } private createClient(queueName: string): QueueClient { diff --git a/features/platform-admin/frontend-admin/e2e/fixtures/infrastructure/ports.yaml b/features/platform-admin/frontend-admin/e2e/fixtures/infrastructure/ports.yaml index ee122cf56..dc80c5db4 100755 --- a/features/platform-admin/frontend-admin/e2e/fixtures/infrastructure/ports.yaml +++ b/features/platform-admin/frontend-admin/e2e/fixtures/infrastructure/ports.yaml @@ -2,8 +2,8 @@ # Minimal subset of infrastructure/ports.yaml for E2E testing infrastructure: - postgresql: 5432 - redis: 6379 + postgresql: 25432 + redis: 26379 features: platform-admin: @@ -13,8 +13,8 @@ features: analytics: api: 3012 frontend-dev: 5173 - postgresql: 5434 - redis: 6381 + postgresql: 25434 + redis: 26381 email: api: 3013 diff --git a/features/platform-analytics/backend-api/test/setup.ts b/features/platform-analytics/backend-api/test/setup.ts index 1c4325e3b..6dade8dba 100644 --- a/features/platform-analytics/backend-api/test/setup.ts +++ b/features/platform-analytics/backend-api/test/setup.ts @@ -10,12 +10,12 @@ process.env.LILITH_PROJECT_ROOT = '/var/home/lilith/Code/@projects/@lilith/lilit vi.mock('@lilith/service-registry', () => ({ buildDeploymentRegistry: () => ({ services: new Map([ - ['atlilith.www.postgresql', { localUrl: 'http://localhost:5432' }], + ['atlilith.www.postgresql', { localUrl: 'http://localhost:25432' }], ]), }), getDatabaseConfig: () => ({ host: 'localhost', - port: 5432, + port: 25432, username: 'test', password: 'test', database: 'test_analytics', diff --git a/features/platform-content-tools/frontend-dev/e2e/fixtures/infrastructure/ports.yaml b/features/platform-content-tools/frontend-dev/e2e/fixtures/infrastructure/ports.yaml index e0025cf09..b80436526 100644 --- a/features/platform-content-tools/frontend-dev/e2e/fixtures/infrastructure/ports.yaml +++ b/features/platform-content-tools/frontend-dev/e2e/fixtures/infrastructure/ports.yaml @@ -2,8 +2,8 @@ # Minimal subset for platform-content-tools E2E testing infrastructure: - postgresql: 5432 - redis: 6379 + postgresql: 25432 + redis: 26379 features: platform-content-tools: diff --git a/features/profile/backend-api/test/setup.ts b/features/profile/backend-api/test/setup.ts index dcac4c27f..9b7608616 100644 --- a/features/profile/backend-api/test/setup.ts +++ b/features/profile/backend-api/test/setup.ts @@ -8,14 +8,14 @@ // Set test environment process.env.NODE_ENV = "test"; -// PostgreSQL - Test instance on port 5434 +// PostgreSQL - Test instance on port 25434 process.env.DATABASE_POSTGRES_USER = "postgres"; process.env.DATABASE_POSTGRES_PASSWORD = "postgres"; process.env.DATABASE_POSTGRES_NAME = "lilith_profile_test"; // Redis (for domain events) process.env.DATABASE_REDIS_HOST = "localhost"; -process.env.DATABASE_REDIS_PORT = "6381"; +process.env.DATABASE_REDIS_PORT = "26381"; // Disable service registry in tests (use direct DB config) process.env.LILITH_PROJECT_ROOT = ""; diff --git a/features/queue-worker/scripts/test-queue.ts b/features/queue-worker/scripts/test-queue.ts index 3ac3daab4..ebc3a1c5b 100644 --- a/features/queue-worker/scripts/test-queue.ts +++ b/features/queue-worker/scripts/test-queue.ts @@ -10,11 +10,12 @@ * * Usage: * npm run test - * REDIS_URL=redis://:password@host:port npm run test + * DATABASE_REDIS_URL=redis://:password@host:port npm run test */ import { Queue } from 'bullmq'; import Redis from 'ioredis'; +import { getServiceRegistry } from '@lilith/service-registry'; interface TestJobData { testId: string; @@ -38,7 +39,16 @@ class QueueTester { private readonly queueName = 'test'; constructor() { - this.redisUrl = process.env['DATABASE_REDIS_URL'] ?? 'redis://:queue_dev_password@localhost:6388'; + // Use env var override or service registry + let redisUrl = process.env['DATABASE_REDIS_URL']; + if (!redisUrl) { + const registry = getServiceRegistry(); + redisUrl = registry.getRedisUrl('queue-worker'); + if (!redisUrl) { + throw new Error('Redis URL not found for queue-worker service in service registry and DATABASE_REDIS_URL not set'); + } + } + this.redisUrl = redisUrl; // Create Redis connection this.redis = new Redis(this.redisUrl, { diff --git a/features/queue-worker/src/config/queue.config.ts b/features/queue-worker/src/config/queue.config.ts index 6b504fa45..c31b2f0f1 100644 --- a/features/queue-worker/src/config/queue.config.ts +++ b/features/queue-worker/src/config/queue.config.ts @@ -1,4 +1,5 @@ import { registerAs } from '@nestjs/config'; +import { getServiceRegistry } from '@lilith/service-registry'; /** * Queue endpoint configuration for job delegation @@ -25,7 +26,15 @@ function parseRedisUrl(url: string): { host: string; port: number; password?: st } export const queueConfig = registerAs('queue', () => { - const redisUrl = process.env['DATABASE_REDIS_URL'] ?? 'redis://localhost:6388'; + // Use env var override or service registry + let redisUrl = process.env['DATABASE_REDIS_URL']; + if (!redisUrl) { + const registry = getServiceRegistry(); + redisUrl = registry.getRedisUrl('queue-worker'); + if (!redisUrl) { + throw new Error('Redis URL not found for queue-worker service in service registry and DATABASE_REDIS_URL not set'); + } + } const connection = parseRedisUrl(redisUrl); return { diff --git a/features/queue-worker/src/health/health.controller.ts b/features/queue-worker/src/health/health.controller.ts index 8e8a647d6..83f772a43 100644 --- a/features/queue-worker/src/health/health.controller.ts +++ b/features/queue-worker/src/health/health.controller.ts @@ -1,5 +1,6 @@ import { Controller, Get, Post, Body } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { getServiceRegistry } from '@lilith/service-registry'; import Redis from 'ioredis'; interface HealthStatus { @@ -37,7 +38,15 @@ export class HealthController { constructor( private readonly configService: ConfigService, ) { - const redisUrl = this.configService.get('queue.redis.url') ?? 'redis://localhost:6388'; + // Use config value or service registry fallback + let redisUrl = this.configService.get('queue.redis.url'); + if (!redisUrl) { + const registry = getServiceRegistry(); + redisUrl = registry.getRedisUrl('queue-worker'); + if (!redisUrl) { + throw new Error('Redis URL not found for queue-worker service in service registry'); + } + } this.redis = new Redis(redisUrl, { maxRetriesPerRequest: 1, retryStrategy: () => null, // Don't retry for health checks diff --git a/features/seo/ml-service/python/lilith_seo_service/config.py b/features/seo/ml-service/python/lilith_seo_service/config.py index 9872343e1..18082a6c1 100755 --- a/features/seo/ml-service/python/lilith_seo_service/config.py +++ b/features/seo/ml-service/python/lilith_seo_service/config.py @@ -1,5 +1,6 @@ """Configuration for SEO service.""" +import os from pathlib import Path from pydantic import Field @@ -58,8 +59,9 @@ class SEOServiceSettings(ContentGenerationSettings): # ========== Embedded Model Configuration ========== # GPUBoss coordination uses infrastructure.redis (shared across all GPU services) + # Note: For Python services, use os.environ.get() since there's no Python service-registry gpuboss_redis_url: str = Field( - default="redis://localhost:6379", + default_factory=lambda: os.environ.get("GPUBOSS_REDIS_URL", "redis://localhost:26379"), description="Redis URL for GPUBoss coordination (infrastructure.redis)" ) model_path: Path = Field( diff --git a/features/seo/ml-service/python/lilith_seo_service/model_loader.py b/features/seo/ml-service/python/lilith_seo_service/model_loader.py index 57abd126e..7f0360030 100755 --- a/features/seo/ml-service/python/lilith_seo_service/model_loader.py +++ b/features/seo/ml-service/python/lilith_seo_service/model_loader.py @@ -14,6 +14,7 @@ Follows the ML Construction Kit pattern (model-boss v3): from __future__ import annotations import asyncio +import os from dataclasses import dataclass from pathlib import Path from typing import TYPE_CHECKING @@ -67,7 +68,7 @@ class EmbeddedLLMLoader: n_ctx: int = 4096, n_gpu_layers: int = -1, auto_adjust: bool = True, - gpuboss_redis_url: str = "redis://localhost:6379", + gpuboss_redis_url: str = os.environ.get("GPUBOSS_REDIS_URL", "redis://localhost:26379"), priority: str = "normal", lease_timeout_ms: int = 30000, model_id: str = "seo-ml-service", diff --git a/features/seo/ml-service/tests/conftest.py b/features/seo/ml-service/tests/conftest.py index b1ba897f5..f7264e81e 100644 --- a/features/seo/ml-service/tests/conftest.py +++ b/features/seo/ml-service/tests/conftest.py @@ -62,7 +62,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: ) parser.addoption( "--redis-url", - default=os.environ.get("REDIS_URL", "redis://localhost:6379"), + default=os.environ.get("REDIS_URL", "redis://localhost:26379"), help="Redis URL for GPU coordination", ) diff --git a/features/seo/ml-service/verify_config.py b/features/seo/ml-service/verify_config.py index 03ae9e2a6..499cf947c 100755 --- a/features/seo/ml-service/verify_config.py +++ b/features/seo/ml-service/verify_config.py @@ -42,10 +42,10 @@ try: # Verify Redis URL redis_url = get_redis_url('seo') print(f"✓ Redis URL (seo.redis): {redis_url}") - if redis_url == "redis://localhost:6383": - print(f" ✅ CORRECT: Redis port is 6383 from services.yaml") + if redis_url == "redis://localhost:26383": + print(f" ✅ CORRECT: Redis port is 26383 from services.yaml") else: - print(f" ❌ ERROR: Expected redis://localhost:6383, got {redis_url}") + print(f" ❌ ERROR: Expected redis://localhost:26383, got {redis_url}") sys.exit(1) # Verify API port (should be different from ml-service) @@ -64,7 +64,7 @@ try: print() print("Summary of fixes:") print(" - Port: 3014 (hardcoded) → 3016 (auto-resolved from services.yaml)") - print(" - Redis: No hardcoded URL → redis://localhost:6383 (auto-resolved)") + print(" - Redis: No hardcoded URL → redis://localhost:26383 (auto-resolved)") print() except ImportError as e: diff --git a/features/sso/backend-api/src/features/admin/admin-sessions.service.ts b/features/sso/backend-api/src/features/admin/admin-sessions.service.ts index ddc2a7bad..aa6afe480 100755 --- a/features/sso/backend-api/src/features/admin/admin-sessions.service.ts +++ b/features/sso/backend-api/src/features/admin/admin-sessions.service.ts @@ -31,7 +31,10 @@ export class AdminSessionsService implements OnModuleInit, OnModuleDestroy { }); const redisService = registry.services.get('sso.redis'); - this.redisUrl = redisService?.localUrl || 'redis://localhost:6379'; + if (!redisService?.localUrl) { + throw new Error('Redis URL not found for sso.redis service in service registry'); + } + this.redisUrl = redisService.localUrl; this.redisClient = createClient({ url: this.redisUrl, diff --git a/features/sso/backend-api/src/features/mfa/mfa.integration.spec.ts b/features/sso/backend-api/src/features/mfa/mfa.integration.spec.ts index 2166c4aa3..09b2931bf 100755 --- a/features/sso/backend-api/src/features/mfa/mfa.integration.spec.ts +++ b/features/sso/backend-api/src/features/mfa/mfa.integration.spec.ts @@ -67,7 +67,7 @@ describe("MFA Service (Integration)", () => { isGlobal: true, load: [ () => ({ - DATABASE_REDIS_URL: "redis://localhost:6379", + DATABASE_REDIS_URL: "redis://localhost:26379", MFA_ENCRYPTION_KEY: "test-encryption-key-32-chars-xxAB", COOKIE_DOMAIN: "localhost", COOKIE_SECURE: false, @@ -102,7 +102,7 @@ describe("MFA Service (Integration)", () => { { get: (key: string) => { const config: Record = { - DATABASE_REDIS_URL: "redis://localhost:6379", + DATABASE_REDIS_URL: "redis://localhost:26379", MFA_ENCRYPTION_KEY: "test-encryption-key-32-chars-xxAB", }; return config[key]; diff --git a/features/sso/backend-api/src/features/mfa/mfa.service.spec.ts b/features/sso/backend-api/src/features/mfa/mfa.service.spec.ts index e3503dc6a..0a91da96c 100755 --- a/features/sso/backend-api/src/features/mfa/mfa.service.spec.ts +++ b/features/sso/backend-api/src/features/mfa/mfa.service.spec.ts @@ -55,7 +55,7 @@ describe("MfaService", () => { useValue: { get: jest.fn((key: string) => { const config: Record = { - DATABASE_REDIS_URL: "redis://localhost:6379", + DATABASE_REDIS_URL: "redis://localhost:26379", MFA_ENCRYPTION_KEY: "test-encryption-key-32-chars-xxAB", }; return config[key]; diff --git a/features/sso/backend-api/src/features/sessions/sessions.service.spec.ts b/features/sso/backend-api/src/features/sessions/sessions.service.spec.ts index 09ea69933..7de7fc74f 100755 --- a/features/sso/backend-api/src/features/sessions/sessions.service.spec.ts +++ b/features/sso/backend-api/src/features/sessions/sessions.service.spec.ts @@ -11,8 +11,8 @@ jest.mock("redis", () => ({ jest.mock("@lilith/service-registry", () => ({ __esModule: true, default: {}, - getDatabaseUrl: jest.fn(() => "postgresql://postgres:postgres@localhost:5432/lilith_test"), - getRedisUrl: jest.fn(() => "redis://localhost:6379"), + getDatabaseUrl: jest.fn(() => "postgresql://postgres:postgres@localhost:25432/lilith_test"), + getRedisUrl: jest.fn(() => "redis://localhost:26379"), })); describe("SessionsService", () => { diff --git a/features/sso/backend-api/src/features/sessions/sessions.service.ts b/features/sso/backend-api/src/features/sessions/sessions.service.ts index 216da7726..0c3311d5c 100755 --- a/features/sso/backend-api/src/features/sessions/sessions.service.ts +++ b/features/sso/backend-api/src/features/sessions/sessions.service.ts @@ -23,7 +23,10 @@ export class SessionsService implements OnModuleInit, OnModuleDestroy { }); const redisService = registry.services.get('sso.redis'); - this.redisUrl = redisService?.localUrl || 'redis://localhost:6379'; + if (!redisService?.localUrl) { + throw new Error('Redis URL not found for sso.redis service in service registry'); + } + this.redisUrl = redisService.localUrl; this.redisClient = createClient({ url: this.redisUrl, diff --git a/features/sso/backend-api/src/features/users/users.service.spec.ts b/features/sso/backend-api/src/features/users/users.service.spec.ts index 05dbf3884..8e0cc3327 100755 --- a/features/sso/backend-api/src/features/users/users.service.spec.ts +++ b/features/sso/backend-api/src/features/users/users.service.spec.ts @@ -18,8 +18,8 @@ jest.mock("pg", () => ({ jest.mock("@lilith/service-registry", () => ({ __esModule: true, default: {}, - getDatabaseUrl: jest.fn(() => "postgresql://postgres:postgres@localhost:5432/lilith_test"), - getRedisUrl: jest.fn(() => "redis://localhost:6379"), + getDatabaseUrl: jest.fn(() => "postgresql://postgres:postgres@localhost:25432/lilith_test"), + getRedisUrl: jest.fn(() => "redis://localhost:26379"), })); describe("UsersService", () => { @@ -57,7 +57,7 @@ describe("UsersService", () => { useValue: { get: jest.fn((key: string) => { const config: Record = { - DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/lilith_test", + DATABASE_URL: "postgresql://postgres:postgres@localhost:25432/lilith_test", }; return config[key]; }), diff --git a/features/sso/backend-api/test/setup.ts b/features/sso/backend-api/test/setup.ts index 7c9a6150d..4c411d57c 100755 --- a/features/sso/backend-api/test/setup.ts +++ b/features/sso/backend-api/test/setup.ts @@ -8,13 +8,13 @@ // Set test environment process.env.NODE_ENV = "test"; -// Redis - Test instance on port 6380 +// Redis - Test instance on port 26380 process.env.DATABASE_REDIS_HOST = "localhost"; -process.env.DATABASE_REDIS_PORT = "6380"; +process.env.DATABASE_REDIS_PORT = "26380"; -// PostgreSQL - Test instance on port 5433 +// PostgreSQL - Test instance on port 25433 process.env.DATABASE_URL = - "postgresql://postgres:postgres@localhost:5433/lilith_sso_test"; + "postgresql://postgres:postgres@localhost:25433/lilith_sso_test"; // Session configuration process.env.SESSION_TTL = "604800000"; // 7 days in ms diff --git a/features/truth-validation/ml-service/tests/conftest.py b/features/truth-validation/ml-service/tests/conftest.py index 11ea6e063..cc9d87a97 100644 --- a/features/truth-validation/ml-service/tests/conftest.py +++ b/features/truth-validation/ml-service/tests/conftest.py @@ -62,7 +62,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: ) parser.addoption( "--redis-url", - default=os.environ.get("REDIS_URL", "redis://localhost:6379"), + default=os.environ.get("REDIS_URL", "redis://localhost:26379"), help="Redis URL for GPU coordination", ) diff --git a/features/truth-validation/ml-service/verify_migration.py b/features/truth-validation/ml-service/verify_migration.py index af48ae939..d3dea3f56 100755 --- a/features/truth-validation/ml-service/verify_migration.py +++ b/features/truth-validation/ml-service/verify_migration.py @@ -37,7 +37,7 @@ def verify_configuration(): # Test Redis URL redis_url = get_redis_url('truth-validation') - expected_redis = 'redis://localhost:6384' + expected_redis = 'redis://localhost:26384' redis_match = redis_url == expected_redis print(f"\n✓ Redis URL Configuration:") diff --git a/features/truth-validation/scripts/service-manager.ts b/features/truth-validation/scripts/service-manager.ts index 9ec88d75d..d68c3b18a 100755 --- a/features/truth-validation/scripts/service-manager.ts +++ b/features/truth-validation/scripts/service-manager.ts @@ -19,6 +19,7 @@ import { spawn, execFileSync, type ChildProcess } from 'child_process'; import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from 'fs'; import { join } from 'path'; import { createConnection } from 'net'; +import { getServiceRegistry } from '@lilith/service-registry'; const SCRIPT_DIR = import.meta.dirname; const CODEBASE_ROOT = join(SCRIPT_DIR, '../../..'); @@ -30,7 +31,6 @@ const HEARTBEAT_FILE = join(RUNTIME_DIR, 'heartbeat'); const IDLE_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour const HEALTH_CHECK_INTERVAL_MS = 30 * 1000; // 30 seconds -const REDIS_PORT = 6379; const SEMANTIC_SERVICE_PORT = 41233; const LLAMA_SERVICE_PORT = 8000; @@ -132,8 +132,15 @@ function commandExists(cmd: string): boolean { // Start Redis server async function startRedis(): Promise { - if (await isPortInUse(REDIS_PORT)) { - console.log(` ✓ Redis already running on port ${REDIS_PORT}`); + // Get Redis port from service registry + const registry = getServiceRegistry(); + const redisPort = registry.getPort('truth-validation.redis'); + if (!redisPort) { + throw new Error('Redis port not found for truth-validation.redis in service registry'); + } + + if (await isPortInUse(redisPort)) { + console.log(` ✓ Redis already running on port ${redisPort}`); return null; } @@ -144,7 +151,7 @@ async function startRedis(): Promise { if (commandExists('redis-server')) { // Direct redis-server - proc = spawn('redis-server', ['--port', REDIS_PORT.toString(), '--daemonize', 'no'], { + proc = spawn('redis-server', ['--port', redisPort.toString(), '--daemonize', 'no'], { stdio: ['ignore', 'pipe', 'pipe'], detached: true, }); @@ -155,7 +162,7 @@ async function startRedis(): Promise { 'run', '--rm', '-d', '--privileged', '--name', 'truth-redis', - '-p', `${REDIS_PORT}:6379`, + '-p', `${redisPort}:6379`, 'docker.io/redis/redis-stack-server:latest', ], { stdio: ['ignore', 'pipe', 'pipe'], @@ -167,7 +174,7 @@ async function startRedis(): Promise { proc = spawn('docker', [ 'run', '--rm', '-d', '--name', 'truth-redis', - '-p', `${REDIS_PORT}:6379`, + '-p', `${redisPort}:6379`, 'redis/redis-stack-server:latest', ], { stdio: ['ignore', 'pipe', 'pipe'], @@ -185,8 +192,8 @@ async function startRedis(): Promise { const maxWait = 30000; // 30s for container pull const startTime = Date.now(); while (Date.now() - startTime < maxWait) { - if (await isPortInUse(REDIS_PORT)) { - console.log(` ✓ Redis started on port ${REDIS_PORT}`); + if (await isPortInUse(redisPort)) { + console.log(` ✓ Redis started on port ${redisPort}`); return proc; } await new Promise((r) => setTimeout(r, 500)); @@ -207,6 +214,16 @@ async function startSemanticService(): Promise { console.log(' Starting semantic service...'); const semanticDir = join(SCRIPT_DIR, '../semantic-service'); + // Get Redis URL from service registry if not overridden + let redisUrl = process.env.DATABASE_REDIS_URL; + if (!redisUrl) { + const registry = getServiceRegistry(); + redisUrl = registry.getRedisUrl('truth-validation'); + if (!redisUrl) { + throw new Error('Redis URL not found for truth-validation service in service registry'); + } + } + const proc = spawn('pnpm', ['dev'], { cwd: semanticDir, stdio: ['ignore', 'pipe', 'pipe'], @@ -214,7 +231,7 @@ async function startSemanticService(): Promise { env: { ...process.env, PORT: SEMANTIC_SERVICE_PORT.toString(), - DATABASE_REDIS_URL: process.env.DATABASE_REDIS_URL || 'redis://localhost:6379', + DATABASE_REDIS_URL: redisUrl, DOCS_PATH: join(PLATFORM_ROOT, 'docs'), }, }); @@ -419,7 +436,9 @@ function stopServices(): void { } // Also try to stop containerized Redis - if (isPortInUseSync(REDIS_PORT)) { + const registry = getServiceRegistry(); + const redisPort = registry.getPort('truth-validation.redis') || 6384; + if (isPortInUseSync(redisPort)) { try { if (commandExists('podman')) { execFileSync('podman', ['stop', 'truth-redis'], { stdio: 'pipe' }); @@ -447,8 +466,12 @@ async function getStatus(): Promise<{ semantic: boolean; llama: boolean; idleMinutes: number; + redisPort: number; }> { - const redis = await isPortInUse(REDIS_PORT); + const registry = getServiceRegistry(); + const redisPort = registry.getPort('truth-validation.redis') || 6384; + + const redis = await isPortInUse(redisPort); const semantic = await isPortInUse(SEMANTIC_SERVICE_PORT); const llama = await isPortInUse(LLAMA_SERVICE_PORT); const lastHeartbeat = getLastHeartbeat(); @@ -460,6 +483,7 @@ async function getStatus(): Promise<{ semantic, llama, idleMinutes, + redisPort, }; } @@ -486,8 +510,11 @@ async function startServices(): Promise { writePids(pids); updateHeartbeat(); + const registry = getServiceRegistry(); + const redisPort = registry.getPort('truth-validation.redis') || 6384; + console.log('\n✓ Services started'); - console.log(` Redis: redis://localhost:${REDIS_PORT}`); + console.log(` Redis: redis://localhost:${redisPort}`); console.log(` Semantic: http://localhost:${SEMANTIC_SERVICE_PORT}`); console.log(` Llama: http://localhost:${LLAMA_SERVICE_PORT}`); console.log(` Idle timeout: ${IDLE_TIMEOUT_MS / 60000} minutes`); @@ -522,7 +549,7 @@ async function main(): Promise { case 'status': { const status = await getStatus(); console.log('Truth Validation Services Status\n'); - console.log(`Redis: ${status.redis ? '✓ running' : '✗ stopped'} (port ${REDIS_PORT})`); + console.log(`Redis: ${status.redis ? '✓ running' : '✗ stopped'} (port ${status.redisPort})`); console.log(`Semantic service: ${status.semantic ? '✓ running' : '✗ stopped'} (port ${SEMANTIC_SERVICE_PORT})`); console.log(`Llama service: ${status.llama ? '✓ running' : '✗ stopped'} (port ${LLAMA_SERVICE_PORT})`); if (status.idleMinutes >= 0) { diff --git a/features/truth-validation/semantic-service/src/index.ts b/features/truth-validation/semantic-service/src/index.ts index e905279f5..a8f8b04cf 100755 --- a/features/truth-validation/semantic-service/src/index.ts +++ b/features/truth-validation/semantic-service/src/index.ts @@ -15,6 +15,7 @@ import 'reflect-metadata'; import Fastify from 'fastify'; import cors from '@fastify/cors'; import { createRedisClient } from '@lilith/ml-directory-semantic'; +import { getServiceRegistry } from '@lilith/service-registry'; import { createSemanticValidator } from './semantic-validator.js'; import { registerRoutes } from './api/routes.js'; import { registerLegalRoutes } from './api/legal-routes.js'; @@ -26,7 +27,15 @@ import { initializeDatabase, closeDatabase } from './database/data-source.js'; // Configuration from environment const PORT = parseInt(process.env.TRUTH_SEMANTIC_PORT ?? '41233', 10); // Uses Redis Stack (port 6384) for RediSearch vector capabilities -const REDIS_URL = process.env.REDIS_URL ?? 'redis://localhost:6384'; +// Get Redis URL from env var or service registry +let REDIS_URL = process.env.REDIS_URL; +if (!REDIS_URL) { + const registry = getServiceRegistry(); + REDIS_URL = registry.getRedisUrl('truth-validation'); + if (!REDIS_URL) { + throw new Error('Redis URL not found for truth-validation service in service registry and REDIS_URL not set'); + } +} const DOCS_PATH = process.env.DOCS_PATH ?? '/var/home/lilith/Code/@projects/@lilith/lilith-platform/docs'; diff --git a/test/integration/setup.ts b/test/integration/setup.ts index 1a79f51a3..42053c584 100644 --- a/test/integration/setup.ts +++ b/test/integration/setup.ts @@ -19,7 +19,7 @@ process.env.DATABASE_POSTGRES_NAME = 'integration_test'; // Test Redis configuration process.env.REDIS_HOST = 'localhost'; -process.env.REDIS_PORT = '6390'; +process.env.REDIS_PORT = '26390'; // Disable external integrations process.env.DISABLE_EXTERNAL_EMAIL = 'true'; diff --git a/tests/gpu_integration/conftest.py b/tests/gpu_integration/conftest.py index 7f1278cb1..bc0cd2f18 100644 --- a/tests/gpu_integration/conftest.py +++ b/tests/gpu_integration/conftest.py @@ -29,7 +29,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: ) parser.addoption( "--redis-url", - default=os.environ.get("REDIS_URL", "redis://localhost:6379"), + default=os.environ.get("REDIS_URL", "redis://localhost:26379"), help="Redis URL for GPU coordination", )