Files
fontvielle ee642e5eaa feat(m2mcore): PgRepository через pgx + интеграция в lk-gateway
PostgreSQL-репозиторий для m2m_core.deals — реальное хранилище сделок
вместо in-memory. Выбор Repository происходит автоматически в
lkgateway.NewServer: если в runtime-конфиге задан Postgres DSN, поднимается
pgxpool и используется PostgresRepository; иначе fallback на MemoryRepository.

internal/m2mcore/pgrepo.go:
- PostgresRepository: Create (идемпотентный по guid через ON CONFLICT DO NOTHING),
  GetByGUID, GetByID, Update, List (с фильтрами state/investor/created_*),
  AppendEvent для журнала deal_events
- request_xml/response_xml/decision_xml хранятся как windows-1251 XML через nsdxml,
  на чтении парсятся обратно в m2m.M2M* структуры
- stages — jsonb с историей FSM-переходов

migrations/m2m-core/002__stages.sql:
- ALTER TABLE deals ADD COLUMN stages jsonb DEFAULT '[]'

internal/lkgateway/server.go:
- При NewServer проверяется runtime-config: если есть DSN → PostgresRepository,
  иначе MemoryRepository; ошибка подключения логируется с fallback на in-memory
- Тесты используют tempdir SetupPath для изоляции от реальной БД

internal/lkgateway/setup.go:
- tryPingPostgres переписан с database/sql (требует регистрации драйвера)
  на pgx.Connect — теперь форма /admin/setup/postgres реально проверяет
  подключение перед сохранением DSN

Проверено сквозным smoke-тестом: введение DSN через UI →
сохранение в ~/.bj/setup.json → перезапуск lk-gateway → лог
"PostgresRepository подключён (m2m_core.deals)" → сделки реально пишутся
в БД.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 13:43:49 +03:00
..

internal/m2mcore — ядро бизнес-логики M2M

Конечный автомат сделки, репозиторий, идемпотентность по GUID, сборка M2MTransferRequest из заявки ЛК + данных Fansy, метрики SLA.

Состав

  • fsm.go — состояния FSM и матрица разрешённых переходов (Draft → Validated → SubmittedToNSD → AwaitingDecision → Confirmed → AwaitingSUB16 → Done, ветки Rejected, TimedOut, ManualApproval).
  • deal.go — доменная модель Deal с явными методами переходов (Validate, Submit, ReceiveDecision, Timeout, SendToManualApproval, ApproveManually, RejectManually, CompleteSUB16). Каждый переход проверяет текущее состояние, пишет историю в Stages и фиксирует событие в журнале.
  • uuid.go — генератор UUID v4 без внешних зависимостей.
  • repo.go — порт Repository + in-memory реализация MemoryRepository с идемпотентным Create (по GUID возвращает существующую сделку). PostgreSQL-реализация — задача M2 (миграция лежит в migrations/m2m-core/001__deals.sql).
  • ports.go — порты к внешним системам (NSDSender, LKCallbackClient, CryptoVerifier, FansyStore) с no-op заглушками для M1.
  • enrich.go — функция EnrichRequest: из ClaimInput (заявка ЛК)
    • данных Fansy собирает валидный M2MTransferRequest, генерирует GUID и ReferenceID по каждой ЦБ.
  • metrics.go — порт Recorder + MemoryRecorder, отдающий Prometheus text-format. В M2 заменим на prometheus/client_golang, когда прокси откроет Go-модули.

Зависимости

Только stdlib и собственные пакеты internal/m2m, internal/nsdxml. Никаких внешних модулей.

Тесты

  • fsm_test.go — переходы и терминальные состояния.
  • repo_test.go — идемпотентность по GUID, фильтры в List.
  • uuid_test.go — формат UUID v4 и ReferenceID.
  • metrics_test.go — Prometheus-текст.

Сервис cmd/m2m-core

cmd/m2m-core/main.go — HTTP-сервер с /healthz и /metrics, in-memory репозиторий, no-op порты. Адрес из BJ_HTTP_ADDR (по умолчанию :8081). В M2 будет заменено на реальные клиенты НРД и crypto-service.