Wangbill/serverless private preview op1#734
Draft
YunchuWang wants to merge 43 commits into
Draft
Conversation
ServerlessActivitiesClientAdapter now takes an attachTaskHubMetadata flag (default true). The Azure-managed channel already injects the taskhub header via CallCredentials, so the AddDurableTaskScheduler* path constructs the adapter with attachTaskHubMetadata: false to avoid sending duplicate headers on DeclareServerlessActivities and ConnectServerlessActivityWorker. Added two unit tests with a recording CallInvoker covering both modes.
This reverts commit 18c8e02.
- Updated README.md to clarify remote worker image settings. - Simplified task hub retrieval in Program.cs. - Removed unnecessary endpoint configuration in remote worker. - Added Azure.Identity package reference in csproj. - Refined serverless worker extensions for environment configuration. - Updated serverless activity configuration to handle registered activities. - Modified tests to reflect changes in activity registration and filtering.
Comment on lines
+224
to
+230
| foreach (string? value in values) | ||
| { | ||
| if (!string.IsNullOrWhiteSpace(value)) | ||
| { | ||
| return value.Trim(); | ||
| } | ||
| } |
Comment on lines
+224
to
+229
| catch (Exception ex) | ||
| { | ||
| Logs.ServerlessActivityWorkerRegistrationFailed(this.logger, ex, this.options.TaskHub); | ||
| await this.DelayBeforeReconnectAsync(retryDelay, cancellationToken).ConfigureAwait(false); | ||
| retryDelay = this.GetNextRetryDelay(retryDelay); | ||
| } |
Comment on lines
+260
to
+263
| catch (Exception) | ||
| { | ||
| // The server response is authoritative once the response task wins the race. | ||
| } |
Comment on lines
+109
to
+111
| catch (Exception ex) when (ex is OperationCanceledException or ObjectDisposedException or RpcException) | ||
| { | ||
| } |
Comment on lines
+120
to
+122
| catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) | ||
| { | ||
| } |
Comment on lines
+123
to
+125
| catch (Exception ex) when (ex is OperationCanceledException or ObjectDisposedException or RpcException) | ||
| { | ||
| } |
Comment on lines
+176
to
+178
| catch (Exception ex) when (ex is OperationCanceledException or ObjectDisposedException or RpcException) | ||
| { | ||
| } |
Comment on lines
+257
to
+259
| catch (OperationCanceledException) when (heartbeatCts.IsCancellationRequested) | ||
| { | ||
| } |
YunchuWang
commented
May 26, 2026
| { | ||
| public override async Task<string> RunAsync(TaskOrchestrationContext context, string input) | ||
| { | ||
| string remoteResult = await context.CallActivityAsync<string>(ServerlessTaskNames.RemoteHello, input); |
YunchuWang
commented
May 26, 2026
| using Microsoft.Extensions.Logging; | ||
|
|
||
| string endpoint = GetRequiredEnvironmentVariable("DTS_ENDPOINT"); | ||
| string taskHub = Environment.GetEnvironmentVariable("DTS_TASK_HUB") ?? "ServerlessPocHub"; |
Member
Author
There was a problem hiding this comment.
better way to populate these values nicely and cleanly than env var?
YunchuWang
commented
May 26, 2026
| TokenCredential credential = new DefaultAzureCredential(); | ||
|
|
||
| HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); | ||
| builder.Logging.AddSimpleConsole(options => |
Member
Author
There was a problem hiding this comment.
why add this console? we really need this?
YunchuWang
commented
May 26, 2026
|
|
||
| await host.StopAsync(); | ||
|
|
||
| static string GetRequiredEnvironmentVariable(string name) |
Member
Author
There was a problem hiding this comment.
would be cleaner if we can remove these if not using env var
YunchuWang
commented
May 26, 2026
| : throw new InvalidOperationException($"Environment variable '{name}' must be a positive integer."); | ||
| } | ||
|
|
||
| static string ParseHelloInput(string[] args, string defaultHelloInput) |
Member
Author
There was a problem hiding this comment.
hello input dont need to be passed in, to make sample cleaner just use some random hardcoded values
Introduce annotation-driven serverless activity declarations and related plumbing. Add ServerlessWorkerProfileAttribute, ServerlessActivityAttribute, IServerlessWorkerProfile, and ServerlessActivityAnnotationResolver to discover profiles and activity markers in loaded assemblies. Replace DeclareServerlessActivities(configure) with EnableServerlessActivities(), change exclusion filter to use annotated activity names, and update scheduler wiring to configure endpoint/task hub without DefaultAzureCredential. Update ServerlessActivityDeclarationHostedService to accept and declare multiple ServerlessOptions. Update samples: add worker profile, declaration markers, many orchestrators and remote activity implementations, demo command parsing, and a skip-declaration flag. Extend tests to validate annotation resolution, hosted service registration, and worker runtime option behavior.
Rework the serverless sample to simplify activities and configuration. Move DefaultServerlessWorkerProfile into a new main-app/WorkerProfiles.cs and update README to reference it. Rename LocalEcho to LocalHello and change its output format; have the HelloOrchestrator call the local activity and concatenate local and remote results. Simplify main-app Program: streamline input handling, always enable serverless activities, and directly schedule the Hello orchestrator. Trim remote worker to a single RemoteHello activity that returns the scheduler-injected marker from env, and update the remote worker Program to only register that activity.
Replace ResolveActivityNames implementation to scan attribute-decorated types instead of relying on Resolve(taskHub). The new logic collects declared worker profiles, ensures profiles are unique, validates that activities reference declared profiles, and prevents the same activity name from being assigned to multiple profiles. Added unit test to assert ResolveActivityNames can run without triggering profile Configure calls and updated the annotated test profile with a ConfigureCallCount to verify no configure invocation occurs.
Add a runtime guard that throws when EnableServerlessActivities is called in a DTS serverless worker (DTS_SUBSTRATE == "Sandbox" or "AcaSessionPool"). Introduces a constant error message and ThrowIfServerlessWorkerRuntime, extracts IsServerlessWorkerSubstrate helper, and updates substrate-based mode detection to use it. Adds a unit test to verify the method throws and does not register hosted services when running in the serverless worker substrate.
Introduce a cached annotation catalog and centralize task-name resolution. ServerlessActivityAnnotationResolver now exposes ResolveDeclarations and uses a Lazy-scanned AnnotationCatalog (ProfileMetadata/ActivityMetadata) via ScanAnnotations to collect and validate profiles/activities, preventing duplicate scans and improving clarity. Extract DurableTask name logic into a new ServerlessTaskNameResolver and update ServerlessOptions.AddActivity and activity-name resolution to use it. Update DurableTaskSchedulerServerlessWorkerExtensions and tests to call the new ResolveDeclarations API.
Make serverless activity resolution task-hub aware and validate ownership. ServerlessActivityAnnotationResolver now resolves declarations per task hub, builds profile options, validates that an activity name isn't assigned to multiple profiles, and exposes ResolveDeclaredActivityNames. DurableTaskSchedulerServerlessWorkerExtensions uses the task-hub-specific declarations to exclude remote activities from local execution. ServerlessActivityAttribute docs updated to clarify Name is optional and resolution rules. Samples updated to register declared activities via IServerlessWorkerProfile.Configure (and remove marker declaration), and tests updated to reflect the new resolution and validation behavior.
Add appsettings.json to store scheduler endpoint and task hub (ServerlessSample:EndpointAddress/TaskHubName) and update README with instructions to run the sample. Program.cs now reads configuration from builder.Configuration, uses a constant input, and removes the GetRequiredEnvironmentVariable helper. WorkerProfiles no longer sets the SERVERLESS_SAMPLE_MARKER env var, and the remote activity stops reading/echoing the marker. Expected output in the README was updated to match the new activity output.
Inline the logic previously in ServerlessTaskNameResolver into ServerlessActivityAnnotationResolver and ServerlessOptions, and delete the now-unused ServerlessTaskNameResolver.cs. Both locations now resolve task names by checking for a DurableTaskAttribute (using DurableTaskAttribute.Name.Name when present and non-empty) and falling back to the type's Name; ServerlessOptions also adds a GetTaskName helper and a null check. This reduces indirection and removes the obsolete helper class.
Rename ServerlessActivityAnnotationResolver to ServerlessActivityDeclarationResolver and update references accordingly. Remove the ServerlessActivityAttribute type and adjust the resolver to scan worker profiles (Configure) for declarations instead of activity annotations. Update DurableTaskSchedulerServerlessWorkerExtensions to call the new resolver and modify tests to expect only profile-configured activities. This simplifies the serverless activity declaration model to rely on worker profile configuration.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines
+272
to
+278
| foreach (DurableTaskWorkerWorkItemFilters.ActivityFilter filter in existingFilters) | ||
| { | ||
| if (!string.IsNullOrWhiteSpace(filter.Name)) | ||
| { | ||
| merged[filter.Name] = filter; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What changed?
Why is this change needed?
Issues / work items
Project checklist
release_notes.mdAI-assisted code disclosure (required)
Was an AI tool used? (select one)
If AI was used:
AI verification (required if AI was used):
Testing
Automated tests
Manual validation (only if runtime/behavior changed)
1.
2.
3.
Notes for reviewers