gateway/docs/SERVICE_CENTER_VS_LEGACY_COMPARISON.md
2026-03-06 14:03:18 +01:00

92 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Service Center vs Legacy Services Hub — Comparison & Assessment
## Executive Summary
The **Service Center** (`modules/serviceCenter`) is a superior architecture compared to the legacy **Services Hub** (`modules/services`). It was worthwhile to create it. The main benefits are: **explicit dependency graph**, **lazy loading**, **per-service RBAC**, and **context-scoped resolution** without carrying the entire hub. The legacy hub remains valid for incremental migration and backward compatibility.
---
## 1. Architecture Comparison
| Aspect | Service Center | Legacy Services Hub |
|--------|----------------|---------------------|
| **Location** | `modules/serviceCenter/` | `modules/services/` |
| **Entry point** | `getService(key, context, legacy_hub)` | `getInterface(user, ...)``Services` |
| **Constructor** | `(context, get_service)` | `(services)` — full hub |
| **Dependencies** | Declared in registry, resolved lazily via `get_service("key")` | Via `self.services.<attr>` — all services always present |
| **Loading** | **Lazy** — only requested services + deps | **Eager** — everything at construction |
| **RBAC** | Per-service `objectKey`, `can_access_service()` | Shared via hub `.rbac` |
| **Caching** | Per-context cache (user + mandate + featureInstance) | No instance cache — new `Services` each call |
| **Feature override** | N/A — features use `getService` directly | Feature services override hub attributes |
| **Pre-warm** | `preWarm()` at app startup | None |
| **Structure** | Core vs importable split; explicit registry | Flat `serviceX/` dirs; discovery via glob |
---
## 2. Which Setup is Better?
**Service Center is better** for these reasons:
### 2.1 Explicit Dependency Graph
- Dependencies are declared in `registry.py` (e.g. `"ai": {"dependencies": ["chat", "utils", "extraction", "billing"]}`).
- Circular dependencies are detected and raise `RuntimeError`.
- Easier to reason about and refactor.
### 2.2 Lazy Loading & Resource Efficiency
- Only requested services (and their transitive deps) are loaded.
- A feature like chatbot needs `chat`, `ai`, `billing`, `streaming` — not `sharepoint`, `ticket`, `neutralization`, etc.
- Legacy hub loads **everything** on first `getInterface()`.
### 2.3 Context-Scoped Resolution
- Each request gets a `ServiceCenterContext` (user, mandate_id, feature_instance_id, workflow).
- Resolution is cached per context. Same user+mandate+feature → same instances.
- No need to pass or construct a full hub.
### 2.4 Per-Service RBAC
- Services have `objectKey` (e.g. `service.ai`, `service.extraction`).
- `can_access_service(user, rbac, service_key)` checks before resolving.
- Finer-grained control than a single hub-level RBAC.
### 2.5 Separation of Concerns
- **Core services** (utils, security, streaming): internal, no RBAC.
- **Importable services** (ai, billing, extraction, etc.): feature-facing, RBAC-protected.
- Clear distinction vs. flat structure in legacy.
### 2.6 Pre-warm for Cold Start
- `preWarm()` imports all service modules at startup.
- First request avoids import latency.
- Legacy has no equivalent.
---
## 3. When Legacy Still Makes Sense
- **Migration**: Features that havent moved yet still use `getInterface()`.
- **Feature overrides**: Feature-specific services (e.g. `serviceAi/mainServiceAi.py` in a feature) that override hub attributes.
- **Backward compatibility**: `legacy_hub` fallback in Service Center allows gradual migration.
---
## 4. Did It Make Sense to Create the Service Center?
**Yes.** The legacy hub has inherent limitations:
1. **Monolithic hub** — every `getInterface()` constructs a full `Services` object with all services, interfaces, and feature discovery.
2. **Implicit dependencies** — services grab what they need via `self.services.<attr>`, leading to hidden coupling.
3. **No explicit RBAC per service** — access control is at the hub level.
4. **Eager loading** — every request pays for all services even when only a few are used.
Service Center addresses these while keeping a migration path via `legacy_hub` fallback. The Chatbot feature already uses it successfully.
---
## 5. Benchmark Script
Run the comparison script to measure runtime and memory:
```bash
# From gateway root
python tests/benchmarks/benchmark_service_center_vs_legacy.py
```
See `tests/benchmarks/benchmark_service_center_vs_legacy.py` for details on metrics and methodology.