Files
Deal/src/ml-service/Deal.Ml/Program.cs
T
Rustam Khalimov 5f5538d33b Разложить grpc-hosting и UrlSafeToken по назначению
grpc-hosting -> Interceptors/Models/Options/Services; UrlSafeToken
-> SharedKernel/Utilities. Маркеры проектов оставлены в корнях.
namespace/using/FQN мигрированы.
2026-09-11 13:33:19 +03:00

58 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ml-service — точка входа gRPC-хоста (план Task 3, L240248; 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();