Skip to content

v1.0 API redesign: annotation-based config, client library, and OTel integration#289

Merged
ElanHasson merged 26 commits intomainfrom
feature/v1-api-redesign
Mar 7, 2026
Merged

v1.0 API redesign: annotation-based config, client library, and OTel integration#289
ElanHasson merged 26 commits intomainfrom
feature/v1-api-redesign

Conversation

@ElanHasson
Copy link
Copy Markdown
Contributor

Summary

Complete v1.0 API redesign of InfinityFlow.Aspire.Temporal:

  • Annotation-based configuration replacing the old lambda callback builder pattern
  • New client library (InfinityFlow.Aspire.Temporal.Client) with AddTemporalClient, AddTemporalWorker, health checks, and automatic OpenTelemetry
  • OTel export from the Temporal container to the Aspire dashboard
  • All 18 temporal server start-dev CLI flags supported
  • 95 tests (84 unit + 11 integration with real Aspire hosts)

Breaking Changes

Hosting API

Before (lambda callback):

builder.AddTemporalServerContainer("temporal", x => x
    .WithPort(7233)
    .WithLogFormat(LogFormat.Json)
    .WithNamespace("ns1"));

After (fluent extension methods):

builder.AddTemporalServerContainer("temporal")
    .WithServicePort(7233)
    .WithLogFormat(LogFormat.Json)
    .WithNamespace("ns1");
  • TemporalServerResourceBuilder and TemporalServerResourceArguments removed
  • Configuration now stored as Aspire annotations on the resource
  • CLI args built dynamically from annotations via TemporalServerArgsBuilder

New Client Library

// Worker project
builder.AddTemporalWorker("temporal", "my-task-queue", opts =>
{
    opts.Namespace = "my-namespace";
})
.AddWorkflow<MyWorkflow>()
.AddScopedActivities<MyActivities>();

// API project
builder.AddTemporalClient("temporal", opts =>
{
    opts.Namespace = "my-namespace";
});

// Service defaults
builder.Services.AddTemporalServiceDefaults();

Both methods automatically resolve connection strings, add TracingInterceptor, configure CustomMetricMeter, and register health checks.

Architecture

Configuration is now stored as IResourceAnnotation types:

  • TemporalNamespaceAnnotation, TemporalLogFormatAnnotation, TemporalLogLevelAnnotation, etc.
  • TemporalServerArgsBuilder reads all annotations and builds CLI args
  • ITemporalServerResource interface shared by container and executable resources

Configuration Reference

All temporal server start-dev flags are supported:

builder.AddTemporalServerContainer("temporal")
    .WithDbFileName("/path/to/db")           // --db-filename
    .WithNamespace("ns1", "ns2")             // --namespace
    .WithServicePort(7233)                   // --port (external only, internal is always 7233)
    .WithHttpPort()                          // --http-port
    .WithMetricsEndpoint()                   // --metrics-port
    .WithUiPort(8233)                        // --ui-port (external only, internal is always 8233)
    .WithHeadlessUi()                        // --headless
    .WithIp("127.0.0.1")                     // --ip
    .WithUiIp("127.0.0.1")                   // --ui-ip
    .WithUiAssetPath("/path")                // --ui-asset-path
    .WithUiCodecEndpoint("http://...")        // --ui-codec-endpoint
    .WithUiPublicPath("/temporal")           // --ui-public-path
    .WithLogFormat(LogFormat.Pretty)         // --log-format
    .WithLogLevel(LogLevel.Info)             // --log-level
    .WithLogConfig(true)                     // --log-config
    .WithSQLitePragma(SQLitePragma.JournalMode) // --sqlite-pragma
    .WithDynamicConfigValue("key", value)    // --dynamic-config-value
    .WithSearchAttribute("Key", SearchAttributeType.Keyword) // --search-attribute
    .WithImageTag("latest");                 // custom image tag

Other Changes

  • Docker image updated to temporalio/admin-tools:1.30.1
  • .WithOtlpExporter() added to container resource for Aspire dashboard telemetry
  • Package version bumped to 1.0.0
  • Sample apps updated to new API
  • Dependency versions updated (Aspire 13.1.2, Temporalio 1.9.0)
  • Container WithServicePort/WithUiPort only set external host port, internal container port stays fixed

Test Plan

  • 84 unit tests covering annotations, args builder, fluent API, endpoints, client extensions
  • 2 integration tests: search attributes and namespace creation via Temporal APIs
  • 9 client library integration tests: AddTemporalClient, AddTemporalWorker (scoped/transient/singleton/instance activities), ConfigureOptions, health check, end-to-end workflow execution
  • All tests run against real Temporal dev server containers via Aspire hosting
Passed! - Failed: 0, Passed: 95, Skipped: 0

Supersedes #273.

Generated with Claude Code

ElanHasson and others added 21 commits March 7, 2026 10:40
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…LI args

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sourceBuilder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mporalWorker

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AppHost: fluent extension methods, no lambda callbacks
- Worker: AddTemporalWorker() with auto-OTel, remove manual boilerplate
- Api: AddTemporalClient() with auto-OTel, remove manual boilerplate
- ServiceDefaults: AddTemporalServiceDefaults() replaces manual OTel wiring
- Replace direct Temporal package references with Client library project refs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Document new fluent extension method API (no lambda callbacks)
- Add client library section with AddTemporalWorker/AddTemporalClient examples
- Add AddTemporalServiceDefaults() for OTel integration
- Update configuration reference with new method names
- Document automatic OTel and health check features

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hosting library:
- Fluent API: WithUiIp, WithUiAssetPath, WithUiCodecEndpoint, WithHeadlessUi (executable)
- Executable endpoints: WithUiPort, WithMetricsEndpoint, WithHttpPort, WithHeadlessUi, args callback
- ArgsBuilder: float, double, long dynamic config types

Client library (new coverage):
- AddTemporalClient: missing connection string throws, registers services/health check/runtime
- AddTemporalWorker: missing connection string throws, registers services/health check/runtime
- Default connection name, configureOptions callback, return types
- Runtime registered once across multiple calls
- AddTemporalServiceDefaults: registers meter and tracer provider config
- Health check registered with correct connection-name-based key

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add --log-config support (WithLogConfig)
- Add --search-attribute support (WithSearchAttribute, SearchAttributeType enum)
- Add --ui-public-path support (WithUiPublicPath)
- Update default image tag from 1.28.2-tctl-1.18.1-cli-1.1.1 to 1.30.1
- 84 tests passing (was 72)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SearchAttributes_AreRegisteredOnServer: verifies WithSearchAttribute()
  registers custom search attributes (Keyword, Text, Bool, Datetime) on
  the Temporal server via the OperatorService API
- Namespace_IsCreatedOnServer: verifies WithNamespace() creates custom
  namespaces accessible via DescribeNamespace
- Uses DistributedApplicationTestingBuilder with a minimal TestAppHost
- Non-proxied HTTP endpoint for direct gRPC access (bypasses TLS proxy)
- 84 unit tests + 2 integration tests all passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests AddTemporalClient, AddTemporalWorker (all activity lifetime
variants), ConfigureOptions, health check, and end-to-end workflow
execution against a live Temporal dev server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests AddTemporalClient, AddTemporalWorker (all activity lifetime
variants), ConfigureOptions, health check, and end-to-end workflow
execution against a live Temporal dev server. Also fixes resource name
collisions across all integration tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WithServicePort and WithUiPort for containers were setting both
endpoint.Port (host-side) and endpoint.TargetPort (container-internal)
to the user value. The internal container port must remain fixed at
7233/8233 since the Temporal process always listens on its defaults.
Only the external host port should change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR delivers a v1.0 redesign of the Aspire Temporal integration by moving server configuration to resource annotations, adding a dedicated client/worker integration package with automatic OpenTelemetry wiring and health checks, and updating samples/docs/tests accordingly.

Changes:

  • Replace the legacy callback-based server configuration (TemporalServerResourceBuilder/TemporalServerResourceArguments) with annotation-based configuration and a centralized TemporalServerArgsBuilder.
  • Introduce InfinityFlow.Aspire.Temporal.Client with AddTemporalClient, AddTemporalWorker, AddTemporalServiceDefaults, and a Temporal health check.
  • Add a new Aspire TestAppHost plus extensive unit/integration test coverage; update samples, solution, and README to the new APIs.

Reviewed changes

Copilot reviewed 54 out of 55 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/TestAppHost/TestAppHost.csproj Adds a minimal Aspire AppHost project for integration testing.
tests/TestAppHost/Program.cs Minimal AppHost entry point for tests.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalServiceDefaultsTests.cs Verifies Temporal service-defaults OTel registrations.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalResourceTests.cs Validates resource types implement expected interfaces.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalIntegrationTests.cs Integration tests for namespaces and search attributes using a real server.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalHealthCheckTests.cs Verifies health check naming for client/worker registrations.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalFluentApiTests.cs Validates fluent API methods attach expected annotations.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalEndpointTests.cs Validates endpoint annotations/ports for container and executable resources.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalClientIntegrationTests.cs End-to-end client/worker integration tests (connect, execute workflow, activities lifetimes).
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalClientExtensionsTests.cs Unit tests for client/worker registration behaviors and errors.
tests/InfinityFlow.Aspire.Temporal.Tests/TemporalArgsBuilderTests.cs Unit tests for args generation from annotations.
tests/InfinityFlow.Aspire.Temporal.Tests/InfinityFlow.Aspire.Temporal.Tests.csproj New test project referencing hosting + client projects.
tests/InfinityFlow.Aspire.Temporal.Tests/AnnotationTests.cs Unit tests for new annotation record types.
src/InfinityFlow.Aspire.Temporal/TemporalServerResourceExtensions.cs New fluent configuration API that stores configuration via annotations and manipulates endpoints.
src/InfinityFlow.Aspire.Temporal/TemporalServerResourceBuilder.cs Removes legacy callback builder type (deleted).
src/InfinityFlow.Aspire.Temporal/TemporalServerResourceArguments.cs Removes legacy arguments model/arg builder (deleted).
src/InfinityFlow.Aspire.Temporal/TemporalServerExecutableResource.cs Refactors executable resource to the new annotation-based model + shared interface.
src/InfinityFlow.Aspire.Temporal/TemporalServerExecutableBuilderExtensions.cs Adds executable resource using dynamic args generation via TemporalServerArgsBuilder.
src/InfinityFlow.Aspire.Temporal/TemporalServerContainerResource.cs Introduces container resource type implementing the shared interface.
src/InfinityFlow.Aspire.Temporal/TemporalServerContainerBuilderExtensions.cs Adds container resource with pinned image and OTLP exporter integration.
src/InfinityFlow.Aspire.Temporal/TemporalServerArgsBuilder.cs Centralizes temporal server start-dev argument construction from annotations.
src/InfinityFlow.Aspire.Temporal/InfinityFlow.Aspire.Temporal.csproj Bumps package to 1.0.0, updates deps, and exposes internals to tests.
src/InfinityFlow.Aspire.Temporal/ITemporalServerResource.cs New shared interface for container/executable resources.
src/InfinityFlow.Aspire.Temporal/Enums.cs Adds SearchAttributeType + mapping helper.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalUiPublicPathAnnotation.cs Adds annotation for --ui-public-path.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalUiIpAnnotation.cs Adds annotation for --ui-ip.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalUiCodecEndpointAnnotation.cs Adds annotation for --ui-codec-endpoint.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalUiAssetPathAnnotation.cs Adds annotation for --ui-asset-path.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalSearchAttributeAnnotation.cs Adds annotation for --search-attribute.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalSQLitePragmaAnnotation.cs Adds annotation for --sqlite-pragma.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalNamespaceAnnotation.cs Adds annotation for --namespace.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalLogLevelAnnotation.cs Adds annotation for --log-level.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalLogFormatAnnotation.cs Adds annotation for --log-format.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalLogConfigAnnotation.cs Adds annotation for --log-config.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalIpAnnotation.cs Adds annotation for --ip.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalHeadlessAnnotation.cs Adds annotation for --headless.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalDynamicConfigAnnotation.cs Adds annotation for --dynamic-config-value.
src/InfinityFlow.Aspire.Temporal/Annotations/TemporalDbFileNameAnnotation.cs Adds annotation for --db-filename.
src/InfinityFlow.Aspire.Temporal.Client/TemporalWorkerBuilder.cs Adds fluent worker builder wrapper over Temporal hosting builder.
src/InfinityFlow.Aspire.Temporal.Client/TemporalServiceDefaultsExtensions.cs Adds service-defaults helper to register Temporal meters/sources with OTel.
src/InfinityFlow.Aspire.Temporal.Client/TemporalHealthCheck.cs Adds health check implementation using Temporal connection health RPC.
src/InfinityFlow.Aspire.Temporal.Client/TemporalClientBuilder.cs Adds fluent client builder wrapper for additional configuration.
src/InfinityFlow.Aspire.Temporal.Client/InfinityFlow.Aspire.Temporal.Client.csproj Introduces new client package and dependencies.
src/InfinityFlow.Aspire.Temporal.Client/AspireTemporalExtensions.cs Adds AddTemporalClient/AddTemporalWorker with connection-string resolution, interceptors, health checks, runtime setup.
sample/Worker/Worker.csproj Updates sample worker to use new client library project reference.
sample/Worker/Program.cs Migrates sample worker to AddTemporalWorker fluent API.
sample/ServiceDefaults/ServiceDefaults.csproj Updates OTel dependency versions and references new client library.
sample/ServiceDefaults/Extensions.cs Uses AddTemporalServiceDefaults instead of manual Temporal OTel wiring.
sample/AppHost/Program.cs Migrates sample AppHost to new hosting API and fluent methods.
sample/AppHost/AppHost.csproj Updates Aspire SDK/AppHost package versions.
sample/Api/Program.cs Migrates sample API to AddTemporalClient.
sample/Api/Api.csproj Updates sample API to reference new client library project.
README.md Updates documentation for new v1.0 hosting API, client library, and observability setup.
InfinityFlow.Aspire.Temporal.sln Adds new client/test projects and solution structure updates.
.gitignore Adds .worktrees/ ignore entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

ElanHasson and others added 4 commits March 7, 2026 14:07
…UiPort safety

- Wire TemporalRuntime into client connect options so CustomMetricMeter
  is actually used for metrics collection
- Deduplicate health check registration when both AddTemporalClient and
  AddTemporalWorker are used with the same connection name
- Make WithUiPort no-op instead of throwing when called after
  WithHeadlessUi (for both container and executable)
- Clarify README port comments: WithServicePort/WithUiPort set external
  host port only, container internal ports are always fixed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… CancellationToken

- Add XML doc comments to all public types (CS1591): annotations, enums, interfaces, resources
- Fix ambiguous WithHeadlessUi cref references (CS0419)
- Pass TestContext.Current.CancellationToken in integration tests (xUnit1051)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…S1591

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ElanHasson ElanHasson merged commit 0e15ab5 into main Mar 7, 2026
2 checks passed
@ElanHasson ElanHasson deleted the feature/v1-api-redesign branch March 7, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants