fix(shared,bot,discordbot): make club-picker Dapper calls AOT-safe (v3.9.2)
The 3.9.1 hotfix only repaired WizardDraftRepository, the most common
Dapper call in the wizard. The same AOT-unsafe CommandDefinition pattern
remained in 4 other places that the user hit immediately after the
deploy: the 'Choose visibility' wizard step triggers GetOwnerClubsAsync
when the user picks 'Публичная в витрине клуба' or 'Только для членов
клуба'. The wizard swallowed PlatformNotSupportedException, the
callback ack replied with '⚠️ Ошибка', and the next step never rendered.
Privacy 'didn't stick' from the user's perspective.
Two changes to fix the Discord side as well:
1. Switched GetOwnerClubsAsync / LoadClubsAsync / LoadManagerUserIdsAsync
to the direct (sql, params) overload across TelegramWizardMessenger,
DiscordWizardMessenger, DiscordWizardInteractionModule, and
DiscordPermissionLookup — same pattern as the 3.9.1 fix.
2. Added Dapper.AOT module attribute ([module: Dapper.DapperAot]) and
InterceptorsPreviewNamespaces to the DiscordBot project. The
DiscordBot assembly was previously skipped by the AOT source
generator, so even the direct-overload fix wouldn't have produced
interceptors for the Discord-specific Dapper call sites. With this
addition, the generator emits 3 DiscordBot-specific interceptors
(DiscordWizardMessenger, DiscordWizardInteractionModule,
DiscordPermissionLookup) and the AssemblyLoad ships with the right
GmRelay.DiscordBot.generated.cs.
Also expanded the AOT shape regression tests to cover all 4
CommandDefinition sites + added a 'containingClass' parameter to
ExtractMethodBody to disambiguate the duplicated LoadClubsAsync names
in DiscordWizardInteractionModule.
Bumps: 3.9.1 -> 3.9.2.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# Этап 1: Сборка с использованием .NET SDK
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build
|
||||
|
||||
# Установка зависимостей для Native AOT-компиляции (clang и zlib)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
clang zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
# Копирование проектов
|
||||
COPY ["src/GmRelay.Bot/GmRelay.Bot.csproj", "src/GmRelay.Bot/"]
|
||||
COPY ["src/GmRelay.ServiceDefaults/GmRelay.ServiceDefaults.csproj", "src/GmRelay.ServiceDefaults/"]
|
||||
|
||||
# Восстановление зависимостей с учетом архитектуры
|
||||
RUN dotnet restore "src/GmRelay.Bot/GmRelay.Bot.csproj" -a amd64
|
||||
|
||||
# Копирование остального исходного кода
|
||||
COPY src/ src/
|
||||
|
||||
WORKDIR /src/src/GmRelay.Bot
|
||||
|
||||
# Публикация AOT-бинарного файла
|
||||
RUN dotnet publish "GmRelay.Bot.csproj" -c Release -a amd64 -o /app/publish
|
||||
|
||||
# Этап 2: Runtime (runtime-deps содержит только ОС-зависимости, без .NET Runtime)
|
||||
FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-noble AS final
|
||||
WORKDIR /app
|
||||
|
||||
# Устанавливаем wget для healthcheck
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends wget \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Копируем только AOT-результаты из билда
|
||||
COPY --from=build /app/publish .
|
||||
|
||||
EXPOSE 8081
|
||||
|
||||
USER $APP_UID
|
||||
|
||||
# Запуск скомпилированного AOT бинарного файла напрямую
|
||||
ENTRYPOINT ["./GmRelay.Bot"]
|
||||
@@ -82,6 +82,14 @@ public sealed class TelegramWizardMessenger(
|
||||
// and game_groups has no `club_id` FK). The picker therefore returns the
|
||||
// game_groups the owner manages as a GM (via group_managers), matching
|
||||
// the WizardClubOption contract (UUID id, name) used downstream.
|
||||
//
|
||||
// NativeAOT: Dapper.AOT 1.0.48 only generates interceptors for the
|
||||
// (sql, object?) extension overload — not the (CommandDefinition) overload.
|
||||
// The wizard reaches this method on the PickClub visibility step
|
||||
// (issue #112 follow-up); using CommandDefinition here would fall back
|
||||
// to Dapper.SqlMapper.CreateParamInfoGenerator, which uses Reflection.Emit
|
||||
// and throws PlatformNotSupportedException on AOT. Same root cause as
|
||||
// WizardDraftRepository.GetActiveAsync in v3.9.0, same fix pattern.
|
||||
const string sql = """
|
||||
SELECT g.id AS ClubId,
|
||||
g.name AS Name
|
||||
@@ -95,10 +103,8 @@ public sealed class TelegramWizardMessenger(
|
||||
""";
|
||||
await using var connection = await dataSource.OpenConnectionAsync(ct);
|
||||
var rows = await connection.QueryAsync<WizardClubOption>(
|
||||
new CommandDefinition(
|
||||
sql,
|
||||
new { Platform = "Telegram", ExternalId = ownerId },
|
||||
cancellationToken: ct));
|
||||
sql,
|
||||
new { Platform = "Telegram", ExternalId = ownerId });
|
||||
return rows.AsList();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user