Тема
QueryRuntime в host
runtime в примерах — локальная переменная host с экземпляром QueryRuntime. Он появляется только после вызова createQueryRuntime(config).
ts
import { createQueryRuntime } from "@dubium/query-layer/runtime"
import { refreshAccessToken, tokenProvider } from "../auth"
const runtime = createQueryRuntime(config)Module Federation не создаёт runtime автоматически.
Где создавать runtime
Создайте один экземпляр на composition root host:
ts
import { createQueryRuntime } from "@dubium/query-layer/runtime"
export const queryRuntime = createQueryRuntime({
mode: "host",
identity: {
// Стабильное имя host-приложения.
applicationId: "portal-shell",
// Версия используется при compatibility check remote.
version: "3.4.0",
},
// Host явно объявляет части scoped API, которые умеет предоставить.
capabilities: ["request", "fetch", "query", "mutation", "session"],
queryClientConfig: {
defaultOptions: {
queries: {
staleTime: 30_000,
gcTime: 5 * 60_000,
retry: 1,
},
mutations: {
retry: false,
},
},
refetchOnReconnect: true,
refetchOnWindowFocus: true,
},
requestExecutorOptions: {
// Событие не содержит body, token или response payload.
onEvent: (event) => {
console.debug("query-layer request", event)
},
},
// Если session capability объявлена явно, host должен настроить coordinator.
sessionCoordinatorOptions: {
// Token provider хранит и очищает access token host-сессии.
tokenProvider,
// Функция реализует refresh endpoint приложения.
refreshToken: refreshAccessToken,
},
})Если общий SessionCoordinator не используется, уберите session из capabilities и не передавайте sessionCoordinatorOptions.
Инициализация
ts
import { queryRuntime } from "./query-runtime"
// Подключает focus/online lifecycle и owned session coordinator.
await queryRuntime.initialize()
// Только после успешной инициализации монтируем host UI.
mountShellReactApp()createQueryRuntime не делает browser I/O. initialize() делает. Повторный вызов initialize() безопасен.
Как router получает runtime
Router не получает ничего от Module Federation автоматически. Route composition module импортирует singleton host:
ts
import { queryRuntime } from "../app/query-runtime"
import { mountBillingRemote } from "../remotes/mount-billing-remote"
export const openBillingRoute = async (container: HTMLElement): Promise<() => void> => {
// queryRuntime создан в host composition root.
return mountBillingRemote({
container,
runtime: queryRuntime,
})
}mountBillingRemote создаст participant scope и передаст remote уже scope, а не root runtime.
Что означают capabilities
ts
capabilities: ["fetch", "query", "mutation", "request", "session"]Это перечень возможностей host runtime для compatibility handshake. Это не HTTP methods, не роли пользователя и не namespace permissions.
| Capability | Какой scoped API обещает host |
|---|---|
request | scope.request.createStore() для RequestStore. |
fetch | scope.fetch.createStore() для FetchStore. |
query | scope.query.createStore(), infinite store, cache read/invalidation. |
mutation | scope.mutation.createStore() для MutationStore. |
session | Host настроил общий session coordinator. |
Если capabilities не переданы, runtime объявляет request, fetch, query и mutation; session добавляется только при наличии coordinator.
Remote не дублирует этот список как собственную конфигурацию. Remote указывает только, что ему обязательно требуется:
ts
requiredRuntimeCapabilities: ["query", "mutation"]Host runtime сравнит требования со своими возможностями.
Подробно: Capabilities.
Методы runtime
| Метод | Кто вызывает | Что делает |
|---|---|---|
initialize() | host bootstrap | Подключает общий browser lifecycle. |
createParticipantScope(registration) | host composition layer | Создаёт scope конкретного application/remote mount. |
getProtocolDescriptor() | host compatibility layer | Возвращает version, protocol и capabilities. |
getDiagnostics() | host diagnostics | Возвращает безопасные счётчики ресурсов. |
dispose() | host shutdown/logout | Освобождает все scopes и внутреннюю инфраструктуру. |
Remote ни один из этих root-методов не получает.
getProtocolDescriptor
ts
const descriptor = queryRuntime.getProtocolDescriptor()
// Пример результата:
// {
// applicationId: "portal-shell",
// version: "3.4.0",
// protocolVersion: 2,
// capabilities: ["request", "fetch", "query", "mutation", "session"]
// }Remote manifest может проверить этот descriptor до mount.
getDiagnostics
ts
const diagnostics = queryRuntime.getDiagnostics()
diagnostics.activeParticipantCount
diagnostics.activeRequestCount
diagnostics.activeRequestAttemptCount
diagnostics.pendingRequestAttemptCount
diagnostics.queryCount
diagnostics.mutationCount
diagnostics.initialized
diagnostics.disposed
diagnostics.sessionStatusDiagnostics не содержит URL, headers, tokens, request body или response data.
Полная конфигурация
| Поле | Type | Что делает |
|---|---|---|
identity.applicationId | string | Обязательный стабильный id host. |
identity.version | string | Версия host/runtime contract. |
mode | application | host | standalone-remote | Документирует назначение экземпляра. Для shell используйте host. |
capabilities | TQueryRuntimeCapability[] | Объявляет доступные scoped facades. |
protocolVersion | number | Версия participant protocol. Обычно оставляют default пакета. |
maxConcurrentRequests | number | Лимит HTTP-попыток общего пула этого runtime. |
requestConcurrency | { default?, groups? } | Общий и независимые групповые лимиты запросов. |
queryClientConfig | IQueryClientConfig | Общие cache/retry/focus настройки. |
requestExecutorOptions | IRequestExecutorOptions | onEvent, clock и timeout manager общего executor. |
sessionCoordinator | ISessionCoordinatorContract | Готовый внешний coordinator; host сохраняет ownership. |
sessionCoordinatorOptions | ISessionCoordinatorOptions | Runtime создаёт и будет освобождать coordinator. |
idGenerator | IIdGenerator | Генератор participant/operation ids, обычно для тестов. |
retryRandom | () => number | Детерминированный random для тестов retry jitter. |
Нельзя одновременно передать sessionCoordinator и sessionCoordinatorOptions.
Очередь общая для Store всех participant scopes этого экземпляра, но не для других пользователей или runtime. Подробнее: «Конкурентность запросов и retry jitter».
Shutdown host
ts
// Сначала router/unmount layer закрывает remote mounts.
await unmountAllRoutes()
// Затем root освобождает оставшиеся scopes и listeners.
await queryRuntime.dispose()На logout безопаснее закрыть scopes старого пользователя, dispose runtime и создать новый runtime для новой session. Не переиспользуйте персональный cache между пользователями.
Следующий шаг: как host создаёт и передаёт scope remote.