grpc-hosting -> Interceptors/Models/Options/Services; UrlSafeToken -> SharedKernel/Utilities. Маркеры проектов оставлены в корнях. namespace/using/FQN мигрированы.
58 lines
4.0 KiB
C#
58 lines
4.0 KiB
C#
// ml-service — точка входа gRPC-хоста (план Task 3, L240–248; Ruling 1/2/4/12).
|
||
//
|
||
// Kestrel HTTP/2 на порту 5103 (env GRPC_PORT, затем PORT) + AddGrpc с интерцепторами service-token
|
||
// и access-лога + стандартный gRPC-health (grpc.health.v1.Health). Транспорт: dev — plaintext
|
||
// (Ruling 2); mTLS (TLS + клиентский сертификат) — при DEAL_MTLS_ENABLED=1 (Ruling 6, план Task 13;
|
||
// сертификаты deploy/certs — scripts/mtls-certs.sh, env передаёт compose-prod Task 14); fail-closed:
|
||
// Production без mTLS не стартует (GrpcHostEnvironment.RequireMtlsInProduction).
|
||
// Серверная обвязка (Kestrel/AddGrpc/health) — общий Deal.Grpc.Hosting (C31): хост-фабрика
|
||
// MlServiceHost.Create используется и интеграционными тестами (Deal.Ml.Tests), которые поднимают
|
||
// его в своём процессе на эфемерном порту. Реальная логика (план Task 5/6): инкрементальный
|
||
// наивный Байес по терминам per-tenant (файлы data/ml/<tenantId>.sqlite, Ruling 4) — движок/пул
|
||
// в Model/, хранилище в Storage/, gRPC Predict/Status/Reset/TrainBatch — MlServiceImpl.
|
||
|
||
using Deal.Grpc.Hosting.Interceptors;
|
||
using Deal.Grpc.Hosting.Models;
|
||
using Deal.Grpc.Hosting.Options;
|
||
using Deal.Grpc.Hosting.Services;
|
||
using Deal.Ml;
|
||
|
||
// Порт по умолчанию — 5103 (Ruling 12, compose.dev.yml); переопределяется env GRPC_PORT (контейнер)
|
||
// или PORT (общий конвенциональный env хостинг-платформ) — см. GrpcHostEnvironment.ResolveGrpcPort.
|
||
const int defaultGrpcPort = 5103;
|
||
// Имя процесса для rolling-файла логов (Ruling 7, Task 14): data/logs/deal-ml-<дата>.json.
|
||
const string mlProcessName = "ml";
|
||
|
||
int grpcPort = GrpcHostEnvironment.ResolveGrpcPort(defaultGrpcPort);
|
||
// Порт эндпоинта метрик /metrics (HTTP/1.1, отдельно от gRPC HTTP/2; этап 12, пакет A).
|
||
int metricsPort = DealMetricsHosting.ResolveMetricsPort(DealMetricsHosting.DefaultMetricsPort);
|
||
|
||
// Serilog (Ruling 7, план Task 14): JSON-консоль + rolling-файл data/logs/deal-ml-*.json —
|
||
// конфигурируется production-точкой входа через configureBuilder-хук хоста (тесты хост поднимают
|
||
// без Serilog, DealLogging.Configure в MlServiceHost/Create вызывается только здесь). Метрики
|
||
// (OTel → Prometheus, /metrics) — тем же хуком до builder.Build().
|
||
WebApplication app = MlServiceHost.Create(
|
||
grpcPort,
|
||
configureBuilder: builder =>
|
||
{
|
||
DealLogging.Configure(builder, mlProcessName);
|
||
DealMetricsHosting.AddDealMetrics(builder, metricsPort);
|
||
});
|
||
|
||
// Эндпоинт метрик /metrics (HTTP/1.1 на отдельном порту): формат Prometheus (этап 12, пакет A).
|
||
DealMetricsHosting.MapDealMetrics(app);
|
||
|
||
// Режим транспорта — из тех же env, что читал хост (Ruling 6, Task 13): mTLS при DEAL_MTLS_ENABLED=1.
|
||
MtlsOptions mtlsOptions = MtlsOptions.FromConfiguration(app.Configuration);
|
||
|
||
// Fail-closed (замечание code-review): отсутствие/опечатка DEAL_MTLS_ENABLED не должны давать
|
||
// «тихого» plaintext в Production; Development (и прочие не-prod окружения) — как раньше.
|
||
GrpcHostEnvironment.RequireMtlsInProduction(mtlsOptions);
|
||
|
||
app.Logger.LogInformation(
|
||
"ml-service стартует: gRPC {Transport} 0.0.0.0:{Port} (health /grpc.health.v1.Health/Check)",
|
||
mtlsOptions.Enabled ? "mTLS (TLS + клиентский сертификат)" : "plaintext + service-token",
|
||
grpcPort);
|
||
|
||
await app.RunAsync();
|