Skip to content

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
requestscope.request.createStore() для RequestStore.
fetchscope.fetch.createStore() для FetchStore.
queryscope.query.createStore(), infinite store, cache read/invalidation.
mutationscope.mutation.createStore() для MutationStore.
sessionHost настроил общий 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.sessionStatus

Diagnostics не содержит URL, headers, tokens, request body или response data.

Полная конфигурация

ПолеTypeЧто делает
identity.applicationIdstringОбязательный стабильный id host.
identity.versionstringВерсия host/runtime contract.
modeapplication | host | standalone-remoteДокументирует назначение экземпляра. Для shell используйте host.
capabilitiesTQueryRuntimeCapability[]Объявляет доступные scoped facades.
protocolVersionnumberВерсия participant protocol. Обычно оставляют default пакета.
maxConcurrentRequestsnumberЛимит HTTP-попыток общего пула этого runtime.
requestConcurrency{ default?, groups? }Общий и независимые групповые лимиты запросов.
queryClientConfigIQueryClientConfigОбщие cache/retry/focus настройки.
requestExecutorOptionsIRequestExecutorOptionsonEvent, clock и timeout manager общего executor.
sessionCoordinatorISessionCoordinatorContractГотовый внешний coordinator; host сохраняет ownership.
sessionCoordinatorOptionsISessionCoordinatorOptionsRuntime создаёт и будет освобождать coordinator.
idGeneratorIIdGeneratorГенератор 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.