Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions samples/isolated-entities/Chirper/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Build output
bin/
obj/

# User-specific files
*.user
*.suo

# Azure Functions local settings
local.settings.json

# Visual Studio cache
.vs/
26 changes: 26 additions & 0 deletions samples/isolated-entities/Chirper/Chirper.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" VersionOverride="2.23.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" VersionOverride="2.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Core" VersionOverride="2.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" VersionOverride="2.0.0" />
<ProjectReference Include="..\..\..\src\Worker.Extensions.DurableTask\Worker.Extensions.DurableTask.csproj" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" VersionOverride="2.0.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" VersionOverride="2.0.5" />
</ItemGroup>

<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/>
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions samples/isolated-entities/Chirper/Entities/IUserChirps.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Chirper
{
public interface IUserChirps
{
void Add(Chirp chirp);

void Remove(DateTime timestamp);

Task<List<Chirp>> Get();
}
}
16 changes: 16 additions & 0 deletions samples/isolated-entities/Chirper/Entities/IUserFollows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Chirper
{
public interface IUserFollows
{
void Add(string user);

void Remove(string user);

Task<List<string>> Get();
}
}
40 changes: 40 additions & 0 deletions samples/isolated-entities/Chirper/Entities/UserChirps.cs
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>();
}
}
}
40 changes: 40 additions & 0 deletions samples/isolated-entities/Chirper/Entities/UserFollows.cs
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);
}

public void Remove(string user)
{
FollowedUsers.Remove(user);
}

public Task<List<string>> Get()
{
return Task.FromResult(FollowedUsers);
}

// Boilerplate (entry point for the functions runtime)
[Function(nameof(UserFollows))]
public static Task HandleEntityOperation([EntityTrigger] TaskEntityDispatcher context)
{
return context.DispatchAsync<UserFollows>();
}
}
}
44 changes: 44 additions & 0 deletions samples/isolated-entities/Chirper/Orchestrations/GetTimeline.cs
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();

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();
}
}
}
14 changes: 14 additions & 0 deletions samples/isolated-entities/Chirper/Program.cs
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"
}
}
}
24 changes: 24 additions & 0 deletions samples/isolated-entities/Chirper/PublicRest/Chirp.cs
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;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

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; }
}
}
Loading
Loading