dotnet / orleans

Cloud Native application framework for .NET
https://docs.microsoft.com/dotnet/orleans
MIT License
10.06k stars 2.03k forks source link

Microsoft.Orleans.CodeGenerator.MSBuild not working in SelfContained project? #7634

Closed wangjia184 closed 2 years ago

wangjia184 commented 2 years ago

.NET Core v6. Orleans v3.6.0

I have three projects, P / A / B. All of them are built into self-contained executable binaries. A & B are referenced in P because they are child processes launched by P.

P.csproj :

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Windows_NT' ">win-x64</RuntimeIdentifier>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Unix' ">linux-x64</RuntimeIdentifier>
    <SelfContained>true</SelfContained>
    <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    <UserRuntimeConfig Condition=" '$(RuntimeIdentifier)' == 'win-x64' ">$(MSBuildProjectDirectory)/runtimeconfig.template.windows.json</UserRuntimeConfig>
    <UserRuntimeConfig Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">$(MSBuildProjectDirectory)/runtimeconfig.template.linux.json</UserRuntimeConfig>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include=".\A\A.csproj" />
    <ProjectReference Include=".\B\B.csproj" />
  </ItemGroup>
</Project>

A.csproj :

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Windows_NT' ">win-x64</RuntimeIdentifier>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Unix' ">linux-x64</RuntimeIdentifier>
    <SelfContained>true</SelfContained>
    <LangVersion>10.0</LangVersion>
    <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>

B.csproj (v0, binary is self-contained)

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Windows_NT' ">win-x64</RuntimeIdentifier>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Unix' ">linux-x64</RuntimeIdentifier>
    <SelfContained>true</SelfContained>
    <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MySqlConnector" Version="2.1.8" />
    <PackageReference Include="Confluent.Kafka" Version="1.8.2" />
    <PackageReference Include="librdkafka.redist" Version="1.8.2" />
    <PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Features" Version="6.0.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
    <PackageReference Include="Microsoft.Orleans.Client" Version="3.6.0" />
    <PackageReference Include="GmMessages" Version="1.0.120" />
    <PackageReference Include="Microsoft.Orleans.OrleansConsulUtils" Version="3.6.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>

</Project>

This works well. When I run dotnet publish --configuration Release --self-contained --runtime win-x64 in directory of P.csproj, there will be three executable files there. P.exe / A.exe / B.exe. All of them are self-contained.

Now in Visual Studio 2022, right-click on project B, and select "Manage Nuget Packages" in popup menu. image Then I add Microsoft.Orleans.CodeGenerator.MSBuild reference in B.csproj, the csproj file is changed to following, and the output B.exe is not self-contained any more!

B.csproj (v1, shared framework)

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Windows_NT' ">win-x64</RuntimeIdentifier>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Unix' ">linux-x64</RuntimeIdentifier>
    <SelfContained>true</SelfContained>
    <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MySqlConnector" Version="2.1.8" />
    <PackageReference Include="Confluent.Kafka" Version="1.8.2" />
    <PackageReference Include="librdkafka.redist" Version="1.8.2" />
    <PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Features" Version="6.0.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
    <PackageReference Include="Microsoft.Orleans.Client" Version="3.6.0" />
    <PackageReference Include="GmMessages" Version="1.0.120" />
    <PackageReference Include="Microsoft.Orleans.OrleansConsulUtils" Version="3.6.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.6.0">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

Then I manually edit B.csproj. Remove <PrivateAssets>all</PrivateAssets> . And the compiled B.exe is self-contained again.

B.csproj (v2, self-contained again)

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Windows_NT' ">win-x64</RuntimeIdentifier>
    <RuntimeIdentifier Condition=" '$(OS)' == 'Unix' ">linux-x64</RuntimeIdentifier>
    <SelfContained>true</SelfContained>
    <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MySqlConnector" Version="2.1.8" />
    <PackageReference Include="Confluent.Kafka" Version="1.8.2" />
    <PackageReference Include="librdkafka.redist" Version="1.8.2" />
    <PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Features" Version="6.0.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
    <PackageReference Include="Microsoft.Orleans.Client" Version="3.6.0" />
    <PackageReference Include="GmMessages" Version="1.0.120" />
    <PackageReference Include="Microsoft.Orleans.OrleansConsulUtils" Version="3.6.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.6.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

It seems that <PrivateAssets>all</PrivateAssets> will force B.exe to be built with shared framework even if <SelfContained>true</SelfContained> is configured in B.csproj.

Now I received the following error.

System.TypeAccessException: Named type "ValueTuple2<MessageMetadata1,MessageBox>" is invalid: Type string "XXX.MessageKey" cannot be resolved.

XXX.MessageKey is defined in a 3rd-party's assembly which does not have reference to Microsoft.Orleans.Core.Abstractions. Hence in B project, I have the following code, but it does not work.

[assembly: Orleans.CodeGeneration.KnownAssembly(typeof(XXX.MessageKey))]

.ConfigureApplicationParts( parts =>
{
    parts.AddFromApplicationBaseDirectory();
    parts.AddApplicationPart(typeof(XXX.MessageKey).Assembly);
})

I do see this type is included in the generated code of assembly of project B.

image

But still it fails with TypeAccessException

      System.TypeAccessException: Named type "ValueTuple`2<MessageMetadata`1<XXX.MessageKey>,MessageBox>" is invalid: Type string "XXX.MessageKey" cannot be resolved.
         at Orleans.Serialization.BinaryTokenStreamReaderExtensinons.ReadSpecifiedTypeHeader[TReader](TReader this, SerializationManager serializationManager) in /_/src/Orleans.Core/Serialization/BinaryTokenStreamReader.cs:line 431
         at Orleans.Serialization.BinaryTokenStreamReaderExtensinons.ReadFullTypeHeader[TReader](TReader this, SerializationManager serializationManager, Type expected) in /_/src/Orleans.Core/Serialization/BinaryTokenStreamReader.cs:line 466
         at Orleans.Serialization.BinaryTokenStreamReaderExtensinons.ReadSpecifiedTypeHeader[TReader](TReader this, SerializationManager serializationManager) in /_/src/Orleans.Core/Serialization/BinaryTokenStreamReader.cs:line 353
         at Orleans.Serialization.SerializationManager.DeserializeInner[TContext,TReader](SerializationManager sm, Type expected, TContext context, TReader reader) in /_/src/Orleans.Core/Serialization/SerializationManager.cs:line 1298
         at Orleans.Serialization.BuiltInTypes.DeserializeInvokeMethodRequest(Type expected, IDeserializationContext context) in /_/src/Orleans.Core/Serialization/BuiltInTypes.cs:line 2100
         at Orleans.Serialization.SerializationManager.DeserializeInner[TContext,TReader](SerializationManager sm, Type expected, TContext context, TReader reader) in /_/src/Orleans.Core/Serialization/SerializationManager.cs:line 1349
         at Orleans.Runtime.Messaging.MessageSerializer.OrleansSerializer`1.Deserialize(ReadOnlySequence`1 input, T& value) in /_/src/Orleans.Core/Messaging/MessageSerializer.cs:line 151
         at Orleans.Runtime.Messaging.MessageSerializer.TryRead(ReadOnlySequence`1& input, Message& message) in /_/src/Orleans.Core/Messaging/MessageSerializer.cs:line 76
         at Orleans.Runtime.Messaging.Connection.ProcessIncoming() in /_/src/Orleans.Core/Networking/Connection.cs:line 358  
wangjia184 commented 2 years ago

The issue is from Heterogeneous silos. All silos must be deployed even if this grain type is not hosted by some silos. otherwise it causes that error when that silo is selected as gateway