7.4 KiB
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:
messagingaigenerationbilling
Services Still Using Legacy Direct Imports
chat← Target for Phase 1sharepointticketutilssecuritystreamingextractionweb
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", ...).
# 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 109–116).
Verification:
- Ensure
ServiceCenterContextincludesworkflowwhen Services has one (chatbot often passesworkflow=Noneinitially). - The service center ChatService gets
interfaceDbComponentfromgetInterface(context.user, mandateId=context.mandate_id)— same as legacy. The chatbot callsgetFileInfo(fileId)which only needsinterfaceDbComponent, not workflow.
Step 1.2: Ensure Service Center Context Has Workflow
File: modules/services/__init__.py
Verify the existing context creation:
_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
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
-
Start the gateway:
cd c:\Users\IdaDittrich\Documents\01_Code\gateway uvicorn app:app --reload --host 0.0.0.0 --port 8000 -
Start the frontend (if using frontend_nyla):
cd c:\Users\IdaDittrich\Documents\01_Code\frontend_nyla npm run dev -
Log in as a user with access to the Chatbot feature.
-
Open a Chatbot instance (navigate to the chatbot feature, select or create an instance).
-
Create a new conversation — click "New conversation" or equivalent.
-
Attach a file — upload a PDF or document before sending.
-
Send a message — e.g. "Summarize this document."
-
Verify:
- No 500 errors in gateway logs
- File is processed (chat service’s
getFileInfois used when creatingChatbotDocuments) - 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:
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:
- Switch
Servicesto usegetService("extraction", _ctx, legacy_hub=self)instead of direct import. - Ensure
ExtractionServicein service center has the same interface as the legacy one. - 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.pylifespan) - 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:
# 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).