Skip to content

Commit

Permalink
Solution 3b - observability.
Browse files Browse the repository at this point in the history
  • Loading branch information
PiotrJustyna committed Jun 9, 2021
1 parent e37db3f commit fc2d776
Show file tree
Hide file tree
Showing 27 changed files with 755 additions and 0 deletions.
2 changes: 2 additions & 0 deletions 3b/.devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ARG VARIANT="5.0"
FROM mcr.microsoft.com/vscode/devcontainers/dotnetcore:0-${VARIANT}
23 changes: 23 additions & 0 deletions 3b/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "C# (.NET)",
"build": {
"dockerfile": "Dockerfile",
"args": { }
},

"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"editor.insertSpaces": true,
"editor.tabSize": 2,
"editor.detectIndentation": false
},

"extensions": [
"ms-vscode.csharp",
"ms-dotnettools.csharp",
"yzhang.markdown-all-in-one",
"bierner.markdown-emoji"
],

"remoteUser": "vscode"
}
25 changes: 25 additions & 0 deletions 3b/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
27 changes: 27 additions & 0 deletions 3b/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "run silo host",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build silo host",
"program": "${workspaceFolder}/SiloHost/bin/Debug/net5.0/SiloHost.dll",
"args": [],
"cwd": "${workspaceFolder}/SiloHost",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "run client",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build client",
"program": "${workspaceFolder}/Client/bin/Debug/net5.0/Client.dll",
"args": [],
"cwd": "${workspaceFolder}/Client",
"console": "internalConsole",
"stopAtEntry": false
}
]
}
27 changes: 27 additions & 0 deletions 3b/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build silo host",
"type": "shell",
"command": "dotnet build ./SiloHost/SiloHost.csproj",
"args": [],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build client",
"type": "shell",
"command": "dotnet build ./Client/Client.csproj",
"args": [],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}
20 changes: 20 additions & 0 deletions 3b/Client/Client.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
<PackageReference Include="Microsoft.Orleans.Core" Version="3.4.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Interfaces\Interfaces.csproj" />
</ItemGroup>

</Project>
130 changes: 130 additions & 0 deletions 3b/Client/src/ClusterClientHostedService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Orleans;
using Orleans.Configuration;
using Orleans.Runtime;

namespace Client
{
public class ClusterClientHostedService : IHostedService
{
private readonly ILogger<ClusterClientHostedService> _logger;

public IClusterClient Client { get; }

public ClusterClientHostedService(
ILogger<ClusterClientHostedService> logger,
ILoggerProvider loggerProvider)
{
_logger = logger;
_logger.LogInformation("creating cluster client...");

var advertisedIp = Environment.GetEnvironmentVariable("ADVERTISEDIP");
var siloAdvertisedIpAddress = advertisedIp == null ? GetLocalIpAddress() : IPAddress.Parse(advertisedIp);
var siloGatewayPort = int.Parse(Environment.GetEnvironmentVariable("GATEWAYPORT") ?? "3000");

Client = new ClientBuilder()
.Configure<ClusterOptions>(clusterOptions =>
{
clusterOptions.ClusterId = "this-is-not-relevant-yet";
clusterOptions.ServiceId = "this-is-not-relevant-yet";
})
.UseStaticClustering(new IPEndPoint(siloAdvertisedIpAddress, siloGatewayPort))
.ConfigureLogging(loggingBuilder =>
loggingBuilder.SetMinimumLevel(LogLevel.Information).AddProvider(loggerProvider))
.Build();

_logger.LogInformation("cluster client created");
}

public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("connecting cluster client...");

var attempt = 0;
var maxAttempts = 100;
var delay = TimeSpan.FromSeconds(1);

return Client.Connect(async error =>
{
if (cancellationToken.IsCancellationRequested)
{
return false;
}

if (++attempt < maxAttempts)
{
_logger.LogWarning(
error,
"Failed to connect to Orleans cluster on attempt {@Attempt} of {@MaxAttempts}.",
attempt,
maxAttempts);

try
{
await Task.Delay(delay, cancellationToken);
}
catch (OperationCanceledException)
{
return false;
}

return true;
}

_logger.LogError(
error,
"Failed to connect to Orleans cluster on attempt {@Attempt} of {@MaxAttempts}.",
attempt,
maxAttempts);

return false;
});
}

public async Task StopAsync(CancellationToken cancellationToken)
{
try
{
await Client.Close();
}
catch (OrleansException error)
{
_logger.LogWarning(
error,
"Error while gracefully disconnecting from Orleans cluster. Will ignore and continue to shutdown.");
}
}

private static IPAddress GetLocalIpAddress()
{
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != OperationalStatus.Up)
continue;

var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
continue;

foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(address.Address))
{
return address.Address;
}
}
}

return null;
}
}
}
27 changes: 27 additions & 0 deletions 3b/Client/src/HelloWorldClientHostedService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Interfaces;
using Microsoft.Extensions.Hosting;
using Orleans;

namespace Client
{
public class HelloWorldClientHostedService : IHostedService
{
private readonly IClusterClient _clusterClient;

public HelloWorldClientHostedService(IClusterClient clusterClient)
{
_clusterClient = clusterClient;
}

public async Task StartAsync(CancellationToken cancellationToken)
{
var helloWorldGrain = _clusterClient.GetGrain<IHelloWorld>(0);
Console.WriteLine($"{await helloWorldGrain.SayHello("Piotr")}");
}

public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}
33 changes: 33 additions & 0 deletions 3b/Client/src/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Client
{
class Program
{
static Task Main(string[] args)
{
return new HostBuilder()
.ConfigureServices(services =>
{
services.AddSingleton<ClusterClientHostedService>();
services.AddSingleton<IHostedService>(_ => _.GetService<ClusterClientHostedService>());
services.AddSingleton(_ => _.GetService<ClusterClientHostedService>().Client);

services.AddHostedService<HelloWorldClientHostedService>();

services.Configure<ConsoleLifetimeOptions>(options =>
{
options.SuppressStatusMessages = true;
});
})
.ConfigureLogging(builder =>
{
builder.AddConsole();
})
.RunConsoleAsync();
}
}
}
18 changes: 18 additions & 0 deletions 3b/Grains/Grains.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Interfaces\Interfaces.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.4.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

</Project>
13 changes: 13 additions & 0 deletions 3b/Grains/src/HelloWorld.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Interfaces;

namespace Grains
{
public class HelloWorld : Orleans.Grain, IHelloWorld
{
public Task<string> SayHello(string name)
{
return Task.FromResult($@"Hello {name}!");
}
}
}
15 changes: 15 additions & 0 deletions 3b/Interfaces/Interfaces.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.4.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Orleans.Core.Abstractions" Version="3.4.2" />
</ItemGroup>

</Project>
9 changes: 9 additions & 0 deletions 3b/Interfaces/src/IHelloWorld.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Threading.Tasks;

namespace Interfaces
{
public interface IHelloWorld : Orleans.IGrainWithIntegerKey
{
Task<string> SayHello(string name);
}
}
Loading

0 comments on commit fc2d776

Please sign in to comment.