Skip to content

Native AOT: the hosted daemon, subscriptions, side effects, raw SQL and a second store (#430) - #432

Merged
jeremydmiller merged 1 commit into
mainfrom
fisher-aot-unmeasured-paths
Oct 4, 2026
Merged

jeremydmiller merged 1 commit into
mainfrom
fisher-aot-unmeasured-paths

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #430. Stacked on #431 (Weasel 9.41), so it targets that branch. Retarget to main before #431 merges, or GitHub will close this PR. CI doesn't run on it until then.

Measured natively (macOS arm64, ILC 10.0.1)

smoke/aot-consumer/UnmeasuredPaths.cs runs each path in the native image, each on a store and file of its own:

  • Hosted daemon (AddAsyncDaemon()), a subscription, a message and an event raised from RaiseSideEffects, and AdvancedSql / QueueSqlCommand: all worked with no change.
  • AddFisherStore<T>(): failed. Its marker is a DispatchProxy, which emits a type at runtime (AssemblyBuilder.DefineDynamicAssembly → PlatformNotSupportedException). That's a .NET limitation, not something in Fisher.

The fix: a declared store class

New public API, AddFisherStore<T, TImplementation>():

public sealed class ArchiveStore(StoreOptions options) : DocumentStore(options), IArchiveStore;
services.AddFisherStore<IArchiveStore, ArchiveStore>(options => ...);
  • DocumentStore already implements everything the marker inherits, so the class body is empty.
  • Nothing downstream changed. Every consumer of the marker already unwrapped through SecondaryStoreProxy.Unwrap, which returns a non-proxy store as-is, and a declared class is an IEventStore and the document tooling interfaces.
  • In a native image, the one-argument overload refuses by name, naming the class to declare and the overload to call. The native smoke asserts that refusal.
  • Docs: compiled samples in native-aot.md and multiple-stores.md.

Verification

  • Native publish and run pass, including the refusal step.
  • multi_store_registration gains a JIT test for the declared store: isolation, StoreName, and the monitoring registrations resolving to the store itself.
  • Full CI-shaped run green on net9.0 and net10.0: 2539 / 36 / 31. check_scoreboard.py agrees for both TFMs; leak check clean.

🤖 Generated with Claude Code

@jeremydmiller
jeremydmiller changed the base branch from fisher-weasel-9.41 to main October 4, 2026 23:00
…nd a second store (#430)

The five paths native-aot.md listed as never measured in a native image.
smoke/aot-consumer/UnmeasuredPaths.cs runs each natively, on a store and
file of its own.

- The hosted daemon (AddAsyncDaemon), a subscription, a message and an
  event raised from a projection's RaiseSideEffects, and AdvancedSql /
  QueueSqlCommand all ran natively with no change.
- AddFisherStore<T>() cannot: its marker is a DispatchProxy, which emits
  a type at runtime and throws PlatformNotSupportedException in a native
  image. New AddFisherStore<T, TImplementation>() takes a store class the
  application declares (an empty DocumentStore subclass implementing the
  marker). Every consumer of the marker already unwrapped through
  SecondaryStoreProxy.Unwrap, so nothing downstream changed. The
  one-argument overload now refuses by name in a native image, naming the
  class to declare; the smoke asserts that refusal natively.
- Compiled samples in native-aot.md and multiple-stores.md.

Closes #430

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jeremydmiller
jeremydmiller force-pushed the fisher-aot-unmeasured-paths branch from 05e6658 to 8d6da92 Compare October 4, 2026 23:01
@jeremydmiller
jeremydmiller merged commit f82625f into main Oct 4, 2026
3 checks passed
@jeremydmiller jeremydmiller mentioned this pull request Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Native AOT: measure the hosted daemon, subscriptions, projection side effects, AdvancedSql and AddFisherStore<T>

1 participant