Polecat runs under Native AOT. This morning it did not — a natively-published app threw from
DocumentStore's constructor, before writing a single document. Seven of eight shapes now pass in a
native image against SQL Server, measured by a new CI lane that publishes and runs rather than
merely building.
Thirteen issues, sixteen commits, three Weasel releases and one JasperFx release.
⚠️ Breaking changes
Six scoped behaviour changes. Minor rather than patch, with the table first — the 5.26.0 / 5.10.0
precedent.
| Area | Before | After |
|---|---|---|
Streamed Select() (ToJsonArrayAsync) — gh-722 |
a key absent from the stored document emitted "key": null, which threw in a consumer's deserializer for a non-nullable value type |
the key is omitted for a non-nullable value-type member; a genuine null on a nullable or reference member still emits null |
| Search over a hierarchy root — gh-729 | every row materialized as the root, dropping sub-class members | each row resolves to its concrete type, matching Query<Root>() |
Advanced.CompletelyRemoveAllAsync() — gh-718 |
dropped pc_* tables only; partition schemes and functions survived — and they are database-scoped, so they outlived the schema and were shared across schemas |
drops the modeled partition schemes and functions too |
| LINQ async surface — gh-733 | carried [UnconditionalSuppressMessage] asserting it was trim/AOT-safe |
carries propagating [RequiresUnreferencedCode] / [RequiresDynamicCode]. A breaking diagnostic change for AOT publishers only — no new warnings unless you trim or publish AOT. |
| Async daemon event loading (via JasperFx 2.80.1) | an event-load failure surfaced as the bare provider exception | arrives wrapped in EventLoaderException. Matters if your code catches SqlException out of the daemon |
| Mapped concurrency version — gh-720 | Metadata(m => m.Version.MapTo(...)) selected no concurrency mode, so the documented API could not be turned on |
the mapped member's CLR type selects the mode, as the marker interfaces do |
Native AOT
See the new guide. Working natively:
store construction, schema migration, document writes, LoadAsync, LINQ reads (including enum
comparisons and child-collection filters), event append and FetchStreamAsync, and live aggregation.
Not working: a strong-typed document id (readonly record struct FooId(Guid)) — #733, measured
rather than assumed.
- root your document types with
[DynamicDependency(PublicProperties, typeof(YourDoc))]. Polecat
cannot name types it has never seen, and nothing statically reads yourIdproperty. - supply a source-generated
JsonSerializerContextviaConfigureSerialization. It must list
JasperFx.Events.Daemon.DeadLetterEvent— Polecat registers that as a document on your behalf, so
it crosses the serializer even if you never touch dead letters. - do not set
InvariantGlobalization— the event paths need real globalization data.
Six walls fell to get here, each invisible until the one before it did. The recurring lesson, three
times over: a statically-referenced interface survives trimming; a reflected member does not — and
Type.GetProperty / GetMethod return null for a trimmed member rather than throwing, so the
null-forgiving operator one line later is what you actually see.
Fixes
- gh-723 — vector, full-text and hybrid search ignored the hierarchy discriminator, so a sub-class
search returned siblings and base rows deserialized as the sub-class asked for. Marten has the
same bug (marten#5440); four facts added upstream in JasperFx/jasperfx#945. - gh-720 — a mapped
Version/Revisionmember was ignored when seeding the expected version, so
MapTo+ optimistic concurrency failed from any session that had not loaded the document. The
fourth independent sighting of this field after fisher#245, marten#5372 and polecat#592. - gh-722, gh-729, gh-718 — see the table above.
- gh-710 / gh-721 — a large
INlist travels as one JSON array. The threshold is now a floor with
a real per-command ceiling againstSqlServerMigrator.MaxParametersPerCommand, which closes the
many small lists case that no per-fragment threshold could reach. - gh-733 / gh-741 — the AOT work, including a
NullReferenceExceptionthat made every LINQ query
fail natively: six handler sites reflected forHandleAsyncandTask.Result, five of them latent.
Hardening and tooling
- gh-725 — a new
aot-runtime-smokelane publishes native and runs eight shapes against SQL
Server, printing per-shape results and stack frames. It iscontinue-on-errorwhile #733 is open,
and it found every wall in this release. - gh-685 — the full-text index becomes Weasel schema objects; the last document raw DDL is gone.
- gh-724 —
docs/configuration/retries.mdclaimed Polecat retried transient errors by default. It
does not, and the first sample it showed was the one that loses a write underSnapshotisolation
(marten#5528). Corrected, withPolecatRetryPredicatesencoding which errors must never be replayed. - gh-645 — the migration guide dated vector projections to 5.29; they shipped in 5.30.0.
Dependencies
JasperFx 2.79.1 → 2.80.2 · Weasel 9.38.0 → 9.41.0
None of it inert. Weasel 9.41's non-generic IIdentification facade and strong-typed-id factory were
filed from this work (JasperFx/weasel#689, #690) and shipped the same day; weasel#694 and marten#5600
remain open from it.
Full suite: 3124 passed / 0 failed / 12 skipped.