Skip to content

Make MicroStack Native AOT compatible - #2

Merged
damianh merged 1 commit into
mainfrom
port-ministack
Apr 13, 2026
Merged

damianh merged 1 commit into
mainfrom
port-ministack

Conversation

@damianh

@damianh damianh commented Apr 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Enable PublishAot=true with zero trim/AOT warnings and all 1,178 tests passing
  • Add MicroStackJsonContext (source-generated serializer context) and DictionaryObjectJsonConverter for AOT-safe Dictionary<string, object?> serialization — the core in-memory model used by all 39 service handlers
  • Change IServiceHandler.GetState()/RestoreState() from object to JsonElement for type-safe persistence round-trips without reflection

What changed

Infrastructure (new files)

  • MicroStackJsonContext.cs — [JsonSerializable] source-generated context registering all serialized types (persistence records, response types, dictionary variants)
  • DictionaryObjectJsonConverter.cs — Custom JsonConverter<Dictionary<string, object?>> handling known primitive types (string, long, double, bool, null, nested dicts/lists, JsonElement, JsonNode) without reflection

Interface & persistence

  • IServiceHandler.GetState() returns JsonElement? (was object?), RestoreState() takes JsonElement (was object)
  • StatePersistence writes JsonElement.GetRawText() directly, reads via JsonDocument.Parse — no JsonSerializer.Serialize(object) calls
  • 5 stateful handlers (SecretsManager, SSM, SNS, SQS, S3) updated with typed serialization records
  • 34 null-state handlers updated with new signatures

Anonymous type elimination

  • All JsonResponse(new { ... }) calls replaced with Dictionary<string, object?> across STS, RDS Data, SES, CloudWatch, WAF, ECR
  • Removed AOT-unsafe JsonResponse(object data) overload from AwsResponseHelpers
  • Program.cs anonymous types replaced with named records (HealthResponse, ResetResponse, ConfigResponse)

Serializer call audit

  • All JsonSerializer.Serialize/Deserialize calls across StepFunctions, CloudFormation, Lambda, ApiGateway, KMS, SES, CloudWatch, and Program.cs now use MicroStackJsonContext.Default

Bug fixes discovered during migration

  • Lambda/ApiGateway response parsing: statusCode and body extraction now handles long/int/string primitives (not just JsonElement)
  • DictionaryObjectJsonConverter.WriteValue: added ulong, uint, short, byte cases for CloudWatch CBOR values
  • STS JSON protocol: prop.Value[0].ToString() → prop.Value[0].GetString() (returns string value, not raw JSON token)

Verification

  • dotnet build -c Release -p:IsAotCompatible=true → 0 warnings, 0 errors
  • dotnet test → 1,178 passed, 0 failed (1 pre-existing skip)
  • Native binary compilation requires C++ Desktop workload (platform linker) — code is AOT-clean, linking is an environment prerequisite

Enable PublishAot=true with zero trim/AOT warnings and all 1,178 tests passing.

Key changes:
- Add MicroStackJsonContext (source-generated) and DictionaryObjectJsonConverter
  for AOT-safe Dictionary<string, object?> serialization
- Change IServiceHandler.GetState()/RestoreState() from object to JsonElement
  for type-safe persistence round-trips
- Update StatePersistence to use JsonElement directly (no reflection)
- Replace all anonymous types in JSON response paths with Dictionary<string, object?>
  across STS, RDS Data, SES, CloudWatch, WAF, ECR handlers
- Remove AOT-unsafe JsonResponse(object) overload from AwsResponseHelpers
- Update all 39 service handlers for new interface signatures
- Update all JsonSerializer calls to use source-generated context
- Fix Lambda/ApiGateway response parsing for primitive types
- Replace Program.cs anonymous types with named records
- Update persistence tests for JsonElement-based assertions
@damianh
damianh merged commit c6fef27 into main Apr 13, 2026
2 checks passed
@damianh
damianh deleted the port-ministack branch April 13, 2026 19:42
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.

1 participant