-
Notifications
You must be signed in to change notification settings - Fork 285
Add .NET Isolated Durable Entities sample #3228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
ad6e219
d3ca1ef
0c7d3d8
41cf944
c65909d
fe9d570
664d357
7945da0
4ecdf80
8c4c409
c7aa0c7
6670ee0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Build output | ||
| bin/ | ||
| obj/ | ||
|
|
||
| # User-specific files | ||
| *.user | ||
| *.suo | ||
|
|
||
| # Visual Studio cache | ||
| .vs/ |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|
|
||||
| <PropertyGroup> | ||||
| <TargetFramework>net8.0</TargetFramework> | ||||
| <AzureFunctionsVersion>v4</AzureFunctionsVersion> | ||||
| <OutputType>Exe</OutputType> | ||||
| <ImplicitUsings>enable</ImplicitUsings> | ||||
| <Nullable>enable</Nullable> | ||||
| </PropertyGroup> | ||||
|
|
||||
| <ItemGroup> | ||||
| <Content Include="local.settings.json" /> | ||||
| </ItemGroup> | ||||
|
|
||||
| <ItemGroup> | ||||
| <FrameworkReference Include="Microsoft.AspNetCore.App" /> | ||||
| <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" VersionOverride="2.23.0" /> | ||||
| <PackageReference Include="Microsoft.Azure.Functions.Worker" VersionOverride="2.2.0" /> | ||||
| <PackageReference Include="Microsoft.Azure.Functions.Worker.Core" VersionOverride="2.2.0" /> | ||||
|
||||
| <PackageReference Include="Microsoft.Azure.Functions.Worker.Core" VersionOverride="2.2.0" /> |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,16 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
|
bachuv marked this conversation as resolved.
|
||||
| using System.Text; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,16 @@ | ||||||||||
| using System; | ||||||||||
| using System.Collections.Generic; | ||||||||||
| using System.Text; | ||||||||||
|
bachuv marked this conversation as resolved.
Comment on lines
+1
to
+3
|
||||||||||
| using System; | |
| using System.Collections.Generic; | |
| using System.Text; | |
| using System.Collections.Generic; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Copyright (c) .NET Foundation. All rights reserved. | ||
| // Licensed under the MIT License. See LICENSE in the project root for license information. | ||
|
|
||
| using Microsoft.Azure.Functions.Worker; | ||
| using Newtonsoft.Json; | ||
|
|
||
| namespace Chirper | ||
| { | ||
| // The UserChirps entity stores all the chirps by ONE user. | ||
| // The entity key is the userId. | ||
|
|
||
| [JsonObject(MemberSerialization = MemberSerialization.OptIn)] | ||
| public class UserChirps : IUserChirps | ||
| { | ||
| [JsonProperty] | ||
| public List<Chirp> Chirps { get; set; } = new List<Chirp>(); | ||
|
|
||
| public void Add(Chirp chirp) | ||
| { | ||
| Chirps.Add(chirp); | ||
| } | ||
|
|
||
| public void Remove(DateTime timestamp) | ||
| { | ||
| Chirps.RemoveAll(chirp => chirp.Timestamp == timestamp); | ||
| } | ||
|
|
||
| public Task<List<Chirp>> Get() | ||
| { | ||
| return Task.FromResult(Chirps); | ||
| } | ||
|
|
||
| // Boilerplate (entry point for the functions runtime) | ||
| [Function(nameof(UserChirps))] | ||
| public static Task HandleEntityOperation([EntityTrigger] TaskEntityDispatcher context) | ||
| { | ||
| return context.DispatchAsync<UserChirps>(); | ||
|
bachuv marked this conversation as resolved.
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,40 @@ | ||||||||||||
| // Copyright (c) .NET Foundation. All rights reserved. | ||||||||||||
| // Licensed under the MIT License. See LICENSE in the project root for license information. | ||||||||||||
|
|
||||||||||||
| using Microsoft.Azure.Functions.Worker; | ||||||||||||
| using Newtonsoft.Json; | ||||||||||||
|
|
||||||||||||
| namespace Chirper | ||||||||||||
| { | ||||||||||||
| // The UserFollows entity stores all the follows of ONE user. | ||||||||||||
| // The entity key is the userId. | ||||||||||||
|
|
||||||||||||
| [JsonObject(MemberSerialization = MemberSerialization.OptIn)] | ||||||||||||
| public class UserFollows : IUserFollows | ||||||||||||
| { | ||||||||||||
| [JsonProperty] | ||||||||||||
| public List<string> FollowedUsers { get; set; } = new List<string>(); | ||||||||||||
|
|
||||||||||||
| public void Add(string user) | ||||||||||||
| { | ||||||||||||
| FollowedUsers.Add(user); | ||||||||||||
|
||||||||||||
| FollowedUsers.Add(user); | |
| if (!FollowedUsers.Contains(user)) | |
| { | |
| FollowedUsers.Add(user); | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Copyright (c) .NET Foundation. All rights reserved. | ||
| // Licensed under the MIT License. See LICENSE in the project root for license information. | ||
|
|
||
| using Microsoft.Azure.Functions.Worker; | ||
| using Microsoft.DurableTask; | ||
| using Microsoft.DurableTask.Entities; | ||
|
|
||
| namespace Chirper | ||
| { | ||
| // The GetTimeline orchestration collects all chirps by followed users, | ||
| // and returns it as a list sorted by timestamp. | ||
| public static class GetTimeline | ||
| { | ||
| [Function(nameof(GetTimeline))] | ||
| public static async Task<Chirp[]> RunOrchestrator( | ||
| [OrchestrationTrigger] TaskOrchestrationContext context) | ||
| { | ||
| var userId = context.GetInput<string>(); | ||
|
|
||
| // call the UserFollows entity to figure out whose chirps should be included | ||
| var userFollowsId = new EntityInstanceId(nameof(UserFollows), userId); | ||
| var followedUsers = await context.Entities.CallEntityAsync<List<string>>(userFollowsId, "Get"); | ||
|
|
||
|
|
||
| // in parallel, collect all the chirps | ||
| var tasks = followedUsers | ||
| .Select(id => | ||
| { | ||
| var userChirpsId = new EntityInstanceId(nameof(UserChirps), id); | ||
| return context.Entities.CallEntityAsync<List<Chirp>>(userChirpsId, "Get"); | ||
| }) | ||
| .ToList(); | ||
|
Comment on lines
+22
to
+32
|
||
|
|
||
| await Task.WhenAll(tasks); | ||
|
|
||
| // combine and sort the returned lists of chirps | ||
| var sortedResults = tasks | ||
| .SelectMany(task => task.Result) | ||
| .OrderBy(chirp => chirp.Timestamp); | ||
|
|
||
| return sortedResults.ToArray(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| using Microsoft.Azure.Functions.Worker; | ||
| using Microsoft.Azure.Functions.Worker.Builder; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Hosting; | ||
|
|
||
| var builder = FunctionsApplication.CreateBuilder(args); | ||
|
|
||
| builder.ConfigureFunctionsWebApplication(); | ||
|
|
||
| builder.Services | ||
| .AddApplicationInsightsTelemetryWorkerService() | ||
| .ConfigureFunctionsApplicationInsights(); | ||
|
|
||
| builder.Build().Run(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "dependencies": { | ||
| "appInsights1": { | ||
| "type": "appInsights" | ||
| }, | ||
| "storage1": { | ||
| "type": "storage", | ||
| "connectionId": "AzureWebJobsStorage" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "dependencies": { | ||
| "appInsights1": { | ||
| "type": "appInsights.sdk" | ||
| }, | ||
| "storage1": { | ||
| "type": "storage.emulator", | ||
| "connectionId": "AzureWebJobsStorage" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Copyright (c) .NET Foundation. All rights reserved. | ||
| // Licensed under the MIT License. See LICENSE in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Text; | ||
|
bachuv marked this conversation as resolved.
|
||
| using Newtonsoft.Json; | ||
| using Newtonsoft.Json.Serialization; | ||
|
bachuv marked this conversation as resolved.
|
||
|
|
||
| namespace Chirper | ||
| { | ||
| /// <summary> | ||
| /// A data structure representing a chirp. | ||
| /// </summary> | ||
| [JsonObject(MemberSerialization.OptOut)] | ||
| public struct Chirp | ||
| { | ||
| public string UserId { get; set; } | ||
|
|
||
| public DateTime Timestamp { get; set; } | ||
|
|
||
| public string Content { get; set; } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.