Архитектура Backend¶
Обзор¶
graph TB
subgraph FastAPI["FastAPI Application"]
MW[Middleware: Auth, CORS]
R[Routers]
end
subgraph Environment
S[Settings]
M[Models]
A[Apps / Services]
end
subgraph Services
DB[PostgresDB Service]
AUTH[AuthToken Service]
CHAT[Chat Service]
CRUD[CRUD Auto Service]
SEC[Security Service]
end
subgraph DotORM
MOD[DotModel]
BLD[Builder]
SES[Session / Pool]
end
FastAPI --> Environment
Environment --> Services
Services --> DotORM
DotORM --> PG[(PostgreSQL)]
CHAT --> WS[WebSocket Manager]
WS --> PUBSUB[PubSub: PG LISTEN/NOTIFY]
PUBSUB --> PG
Жизненный цикл приложения¶
Приложение запускается в определённом порядке — это критично для корректной инициализации:
sequenceDiagram
participant M as main.py
participant E as Environment
participant SB as services_before
participant SA as services_after
M->>E: Environment(Settings, Models, Apps)
E->>E: setup_services()
E->>SB: start_services_before(app)
Note over SB: DB Pool, Logger, Security
E->>E: load_routers(app)
E->>SA: start_services_after(app)
Note over SA: CRUD Auto, Chat PubSub
E->>E: start_post_init(app)
Note over E: Default data, migrations
Порядок запуска сервисов¶
backend/project_setup.py
class Apps(AppsCore):
"""Определяет порядок инициализации модулей."""
services_before = [
"logger", # 1. Логирование
"dotorm_databases_postgres", # 2. DB Pool
"security", # 3. ACL, роли
"auth_token", # 4. Аутентификация
]
services_after = [
"dotorm_crud_auto", # 5. CRUD роутеры
"chat", # 6. WebSocket + PubSub
]
Порядок важен
services_before запускаются до загрузки роутеров — они настраивают DB pool, без которого роутеры не могут работать. services_after запускаются после — они могут использовать роутеры и другие сервисы.
Модульная структура¶
Каждый CRM-модуль — это папка с фиксированной структурой:
backend/base/crm/chat/
├── app.py # Service: startup/shutdown
├── models/ # DotModel-классы
│ ├── chat.py
│ ├── chat_message.py
│ └── chat_member.py
├── routers/ # FastAPI роутеры
│ ├── chats.py
│ └── messages.py
├── schemas/ # Pydantic-схемы (если нужны)
└── websocket/ # Доп. логика (WS, pubsub)
Регистрация модуля в project_setup.py:
backend/project_setup.py
class Models(ModelsCore):
# Каждая модель получает CRUD API автоматически
chat = Chat
chat_message = ChatMessage
chat_member = ChatMember
user = User
# ...
Request Lifecycle¶
sequenceDiagram
participant C as Client
participant MW as Auth Middleware
participant R as Router
participant ORM as DotORM
participant DB as PostgreSQL
C->>MW: POST /chats/1/messages
MW->>MW: verify_access(token)
MW->>MW: set_access_session(session)
MW->>R: pin_message(req, chat_id, msg_id)
R->>ORM: ChatMember.check_can_pin(...)
ORM->>DB: SELECT ... FROM chat_members
DB-->>ORM: row
R->>ORM: message.update(pinned=True)
ORM->>DB: UPDATE chat_messages SET pinned=true
R->>R: chat_manager.send_to_chat(ws_event)
R-->>C: {"success": true}