Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BREAKING_CHANGES_V1.6.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ of `Behavior`, `Wire`, `API` (combine with `+`).

| Status | PR / Branch | Component | Type | Change | Migration |
|--------|-------------|-----------|------|--------|-----------|
| Planned | `aot/m1-b-mailboxes` | `Akka` (core / `Akka.Dispatch.Mailboxes`) | Behavior + API | `Mailboxes` resolves the mailbox names core's own `akka.conf` ships from two built-in tables (`BuiltInMailboxTypes`, `BuiltInMessageQueueSemantics`) instead of `Type.GetType`, so the trimmer and the Native AOT compiler can see which type is loaded. Two observable changes. (1) A built-in `mailbox-type` is constructed directly, so when its constructor rejects its config the `ArgumentException` from `Mailboxes.Lookup` carries that constructor's own exception as `InnerException` instead of the `TargetInvocationException` `Activator.CreateInstance` wrapped it in, and names the configured spelling (e.g. `Akka.Dispatch.BoundedMailbox, Akka`) where it previously named `Type.ToString()`; relatedly, the non-zero-push-timeout warning now runs outside that `try`, so an exception from a custom `IProducesPushTimeoutSemanticsMailbox.PushTimeout` getter propagates as itself rather than wrapped. (2) With the `Akka.DynamicTypeLoading` switch **off**, a key under `akka.actor.mailbox.requirements` that is neither built in nor resolvable now throws a `ConfigurationException` out of `ActorSystem.Create`, where the switch-on path still logs a warning and skips that one binding; an unknown `mailbox-type` or `mailbox-requirement` likewise throws a `ConfigurationException` naming the setting, the value and the switch, in place of the previous `ConfigurationException` / `TypeLoadException`. With the switch on - the default, and what every existing application gets - every other input resolves to the same mailbox as before. Separately, `MailboxType` and the `Type` parameters of `Mailboxes.HasRequiredType`, `Mailboxes.ProducesMessageQueue` and `Mailboxes.GetRequiredType` gain `[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]` so that trimming keeps `IProducesMessageQueue<>` / `IRequiresMessageQueue<>` on subclasses. | None at the default -- the switch is on unless a project file explicitly turns it off. Code that caught `TargetInvocationException` around a rejected `mailbox-capacity` / `mailbox-push-timeout-time` should catch the inner exception type instead, and code asserting on the exact `Cannot instantiate MailboxType ...` text should expect the configured spelling for the five built-in types. A trimmed or Native AOT application that turns the switch off must keep `mailbox-type`, `mailbox-requirement` and every key under `akka.actor.mailbox.requirements` at built-in values. The new attributes are visible only to trim analysis -- they change no signature a compiler binds to -- but a caller that has trim analysis enabled and passes an unannotated `Type` into those three methods now gets `IL2072` at its own call site: annotate the `Type` it flows from with `[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]`, or pass a `typeof(...)`. |
| Planned | `aot/m1-a-feature-switch-and-first-tables` | `Akka` (core / actor system bootstrap) | Behavior | Adds the internal trimming / Native AOT feature switch `Akka.DynamicTypeLoading` (default **on**) and puts built-in lookup tables in front of the first three HOCON type-name sites: `akka.stdout-logger-class` and `akka.logger-formatter` in `Settings`, and `akka.scheduler.implementation` in `ActorSystemImpl.ConfigureScheduler`. Each site now checks a `BuiltIn*` table before falling back to `Type.GetType`. Each table carries two spellings of every name it knows -- the bare `Ns.T` and the `Ns.T, Akka` form, which is what core's own `akka.conf` uses -- and the lookup first runs the configured value through the new internal `Akka.Util.TypeExtensions.StripAssemblyIdentity`, which removes the `Version=`, `Culture=`, `PublicKeyToken=`, `ProcessorArchitecture=`, `Retargetable=` and `ContentType=` components. With the switch on, which is what every existing application gets, the same config resolves to the same type as before, with two narrow differences: (1) a built-in name is constructed directly, so a constructor that rejects its config (e.g. `akka.scheduler.tick-duration` below 10 ms, which `HashedWheelTimerScheduler` refuses) now surfaces its own `ArgumentOutOfRangeException` / `ConfigurationException` instead of the `TargetInvocationException` that `Activator.CreateInstance` wrapped it in; (2) a built-in type name written with a full assembly-qualified name of a different Akka version (what `Akka.Hosting` writes into HOCON, carried across an upgrade) now resolves where it previously threw. `Type.GetType` rejects the version mismatch, so on `dev` such a value fails in both switch states -- measured: `ArgumentException("Could not load type of ...")` for `akka.logger-formatter`/`akka.stdout-logger-class`, and `FileNotFoundException` for `akka.scheduler.implementation`, whose `Type.GetType` call passes `throwOnError: true`. Custom (non-built-in) names are unchanged, since the reflection fallback still receives the raw value. An application that turns the switch off with `<RuntimeHostConfigurationOption Include="Akka.DynamicTypeLoading" Value="false" Trim="true" />` gets only the names in the tables: anything else throws a `ConfigurationException` naming the setting, the value and the switch, where it previously threw `TypeLoadException` (scheduler) or `ArgumentException` (stdout logger, log formatter). | None at the default -- the switch is on unless a project file explicitly turns it off. Code that caught `TargetInvocationException` around `ActorSystem.Create` to read a rejected `akka.scheduler.*` value should catch the inner exception type instead. A trimmed or Native AOT application that turns the switch off must leave these three settings at their built-in values. |
| Planned | `fix/aot-provider-constant-type-names` | `Akka` (core / actor system bootstrap) | Behavior | `ActorSystemImpl` now resolves the three built-in actor ref providers from the compile-time constant type names on `ProviderSelection`, with the `Type.GetType` call inlined at each site, so the trimmer and the Native AOT compiler can see which type is loaded and keep it. Two observable consequences: (1) `ProviderSelection.GetProvider` now maps the local provider's type name -- both the bare `"Akka.Actor.LocalActorRefProvider"` that ships in `akka.conf` and the assembly-qualified `"Akka.Actor.LocalActorRefProvider, Akka"` -- onto `ProviderSelection.Local` instead of letting it fall through to `Custom`, so `Settings.ProviderClass` on a default boot now reports `"Akka.Actor.LocalActorRefProvider, Akka"` where it previously reported the bare `"Akka.Actor.LocalActorRefProvider"`. (2) `Settings` only validates `ProviderClass` through `Type.GetType` when the selection is `ProviderSelection.Custom`; the built-in three are validated where they are constructed, and a missing `Akka.Remote` / `Akka.Cluster` reference now throws `ConfigurationException("akka.actor.provider = cluster, but Akka.Cluster is not referenced by this application.")` from `ActorSystemImpl` rather than the generic "not a valid type name" message from `Settings`. Which provider gets constructed for any given config is unchanged. | None for normal use. Code that compares `Settings.ProviderClass` against the bare string `"Akka.Actor.LocalActorRefProvider"` should compare against `ProviderSelection.Local.Instance.Fqn`, or test `Settings.ProviderSelectionType is ProviderSelection.Local`. Code that asserted on the exact text of the misconfiguration exception for `provider = remote` / `provider = cluster` should expect the new message. |
| Planned | `feature/hosting-import-dev` (forward-port of [#8591](https://github.com/akkadotnet/akka.net/pull/8591)) | `Akka.Hosting`, `Akka.Remote.Hosting`, `Akka.Cluster.Hosting`, `Akka.Persistence.Hosting`, `Akka.Hosting.TestKit`, `Akka.Hosting.TestKit.Xunit2` | API | The Akka.Hosting packages now ship from this repository at the Akka.NET version. On 1.6 they target `net10.0` only (previously `netstandard2.0;net6.0`), matching the rest of Akka.NET 1.6. `Microsoft.Extensions.*` floor moves to 10.0.0 for `Akka`, `Akka.DependencyInjection` and the Hosting packages. | Reference `Akka.Hosting.*` at the same version as `Akka.*`. Applications must target `net10.0` or later, as for every other Akka.NET 1.6 package. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2884,6 +2884,7 @@ namespace Akka.Dispatch
[System.Diagnostics.Conditional("MAILBOXDEBUG")]
public static void DebugPrint(string message, params object[] args) { }
}
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)]
public abstract class MailboxType
{
protected readonly Akka.Configuration.Config Config;
Expand All @@ -2898,11 +2899,11 @@ namespace Akka.Dispatch
public Mailboxes(Akka.Actor.ActorSystem system) { }
public Akka.Actor.DeadLetterMailbox DeadLetterMailbox { get; }
public Akka.Dispatch.MailboxType GetMailboxType(Akka.Actor.Props props, Akka.Configuration.Config dispatcherConfig) { }
public System.Type GetRequiredType(System.Type actorType) { }
public bool HasRequiredType(System.Type actorType) { }
public System.Type GetRequiredType([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)] System.Type actorType) { }
public bool HasRequiredType([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)] System.Type actorType) { }
public Akka.Dispatch.MailboxType Lookup(string id) { }
public Akka.Dispatch.MailboxType LookupByQueueType(System.Type queueType) { }
public bool ProducesMessageQueue(System.Type mailboxType) { }
public bool ProducesMessageQueue([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)] System.Type mailboxType) { }
[Akka.Annotations.InternalApi]
public int StashCapacity(string dispatcher, string mailbox) { }
}
Expand Down Expand Up @@ -5727,4 +5728,4 @@ namespace Akka.Util.Reflection
{
public static System.Type GetType(string typeName) { }
}
}
}
Loading
Loading