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

217 lines
7.4 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 Migration Plan
## Overview
This document describes a **step-by-step plan** to migrate from the old `modules/services` (Services hub) to the new `modules/serviceCenter`. The migration is **incremental**—one feature at a time—with UI-driven testing after each step.
**Recommended first feature: Chatbot** — it has a clear UI, limited service dependencies, and is already partially using the service center (AI, generation, billing).
---
## Architecture Summary
### Current State
| Component | Location | Notes |
|-----------|----------|-------|
| **Service Center** | `modules/serviceCenter/` | New: registry, resolver, context-based DI |
| **Services Hub** | `modules/services/` | Legacy: `getInterface()``Services` instance |
| **Chatbot** | `modules/features/chatbot/` | Uses `getServices()``.chat`, `.ai` |
### Service Center vs Legacy Services
| Aspect | Service Center | Legacy Services |
|--------|----------------|-----------------|
| **Constructor** | `(context: ServiceCenterContext, get_service)` | `(services: Services)` — receives hub |
| **Context** | Minimal: user, mandate_id, feature_instance_id, workflow | Full hub with all interfaces |
| **Dependencies** | Injected via `get_service("key")` | Via `self.services.<attr>` |
| **RBAC** | Per-service `objectKey` in registry | Shared via hub |
| **Pre-warm** | `preWarm()` at app startup | Loaded on first use |
### Services Already Using Service Center (in Services class)
The `Services` class in `modules/services/__init__.py` already uses `getService()` for:
- `messaging`
- `ai`
- `generation`
- `billing`
### Services Still Using Legacy Direct Imports
- `chat`**Target for Phase 1**
- `sharepoint`
- `ticket`
- `utils`
- `security`
- `streaming`
- `extraction`
- `web`
---
## Phase 1: Migrate Chatbot to Use Service Center for Chat
**Goal:** Switch the Chatbot feature to get the Chat service from Service Center instead of the legacy hub. This validates the full flow with minimal risk.
### Step 1.1: Switch Services Class to Use Service Center for Chat
**File:** `modules/services/__init__.py`
**Change:** Replace the direct ChatService import with `getService("chat", ...)`.
```python
# BEFORE (line ~126-127):
from .serviceChat.mainServiceChat import ChatService
self.chat = PublicService(ChatService(self))
# AFTER:
self.chat = PublicService(getService("chat", _ctx, legacy_hub=self))
```
The `_ctx` (ServiceCenterContext) is already created for messaging/ai/generation. Add `workflow=self.workflow` to the context if not already present (it should be—check the existing `_ctx` creation around line 109116).
**Verification:**
1. Ensure `ServiceCenterContext` includes `workflow` when Services has one (chatbot often passes `workflow=None` initially).
2. The service center ChatService gets `interfaceDbComponent` from `getInterface(context.user, mandateId=context.mandate_id)` — same as legacy. The chatbot calls `getFileInfo(fileId)` which only needs `interfaceDbComponent`, not workflow.
### Step 1.2: Ensure Service Center Context Has Workflow
**File:** `modules/services/__init__.py`
Verify the existing context creation:
```python
_ctx = ServiceCenterContext(
user=self.user,
mandate_id=self.mandateId,
feature_instance_id=self.featureInstanceId,
workflow=self.workflow,
)
```
If `workflow` is missing, add it. The ChatService uses `_context.workflow` for methods like `getChatDocumentsFromDocumentList`; for `getFileInfo` it is not needed.
### Step 1.3: Run Unit Tests
```powershell
cd c:\Users\IdaDittrich\Documents\01_Code\gateway
pytest tests/unit/serviceCenter/test_service_center_imports.py -v
python tests/scripts/smoke_test_service_center.py
```
### Step 1.4: Manual UI Test — Chatbot with File Upload
1. **Start the gateway:**
```powershell
cd c:\Users\IdaDittrich\Documents\01_Code\gateway
uvicorn app:app --reload --host 0.0.0.0 --port 8000
```
2. **Start the frontend** (if using frontend_nyla):
```powershell
cd c:\Users\IdaDittrich\Documents\01_Code\frontend_nyla
npm run dev
```
3. **Log in** as a user with access to the Chatbot feature.
4. **Open a Chatbot instance** (navigate to the chatbot feature, select or create an instance).
5. **Create a new conversation** — click "New conversation" or equivalent.
6. **Attach a file** — upload a PDF or document before sending.
7. **Send a message** — e.g. "Summarize this document."
8. **Verify:**
- No 500 errors in gateway logs
- File is processed (chat services `getFileInfo` is used when creating `ChatbotDocument`s)
- AI response streams back correctly (AI service already from service center)
### Step 1.5: Rollback if Needed
If something breaks, revert the change in `modules/services/__init__.py`:
```python
from .serviceChat.mainServiceChat import ChatService
self.chat = PublicService(ChatService(self))
```
---
## Phase 2 (Future): Migrate Extraction for Chatbot
The chatbot may use extraction when processing documents. After Phase 1 is stable:
1. Switch `Services` to use `getService("extraction", _ctx, legacy_hub=self)` instead of direct import.
2. Ensure `ExtractionService` in service center has the same interface as the legacy one.
3. Re-test chatbot with document-heavy prompts.
---
## Phase 3 (Future): Migrate Remaining Services
| Service | Used By | Priority |
|---------|---------|----------|
| utils | Chat, Extraction, AI, Web, Generation | High (core) |
| security | Sharepoint | Medium |
| streaming | Workflows, Chatbot SSE | Medium |
| sharepoint | Sharepoint workflows | Medium |
| ticket | Ticket system | Low |
| web | Web research workflows | Medium |
---
## Service Center Bootstrap (Already Done)
The app already:
- Calls `preWarm()` at startup (`app.py` lifespan)
- Has `registerServiceObjects()` available for RBAC catalog (call from bootstrap if needed)
### Optional: Register Service RBAC Objects
If you want service-level RBAC (e.g. `can_access_service()`), call during bootstrap:
```python
# In app.py lifespan or interfaceBootstrap
from modules.serviceCenter import registerServiceObjects
from modules.security.rbacCatalog import getCatalogService
catalogService = getCatalogService()
registerServiceObjects(catalogService)
```
---
## Testing Checklist (Chatbot Phase 1)
- [ ] Unit tests pass: `pytest tests/unit/serviceCenter/ -v`
- [ ] Smoke test passes: `python tests/scripts/smoke_test_service_center.py`
- [ ] Gateway starts without import errors
- [ ] Chatbot UI loads
- [ ] New conversation creates successfully
- [ ] Message without file sends and gets AI response
- [ ] Message with file attachment sends and gets AI response
- [ ] No errors in gateway logs during the above flows
---
## File Summary for Phase 1
| File | Action |
|------|--------|
| `modules/services/__init__.py` | Replace `ChatService` import with `getService("chat", _ctx, legacy_hub=self)` |
| (No other changes) | Service center ChatService and resolver already support legacy fallback |
---
## FAQ
**Q: Why start with Chat instead of Utils?**
A: Chat has a clear UI path (chatbot) and only a few call sites. Utils is used everywhere; migrating it later reduces risk.
**Q: What if `getService("chat", ctx)` fails?**
A: The resolver passes `legacy_hub=self`, so it falls back to the legacy `Services.chat` if the service center module fails to load. You get graceful degradation.
**Q: Can I test without the frontend?**
A: Yes. Use the API directly, e.g. `POST /api/chatbot/{instanceId}/start/stream` with a valid `UserInputRequest` (with `listFileId` for file upload).