Skip to content
This repository has been archived by the owner on Mar 5, 2022. It is now read-only.

Commit

Permalink
Merge branch 'features/dotnet-3-1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Weyer committed May 31, 2020
2 parents 4a5d01f + c3943e5 commit 3080a98
Show file tree
Hide file tree
Showing 22 changed files with 119 additions and 338 deletions.
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"cake.tool": {
"version": "0.37.0",
"commands": [
"dotnet-cake"
]
}
}
}
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

| CI | Status | Platform(s) | Framework(s) | Test Framework(s) |
| --- | --- | --- | --- | --- |
| [AppVeyor][app-veyor] | [![Build Status][app-veyor-shield]][app-veyor] | `Windows` | `nestandard2.0` | `netcoreapp2.2.0` |
| [AppVeyor][app-veyor] | [![Build Status][app-veyor-shield]][app-veyor] | `Windows` | `nestandard2.0` | `netcoreapp3.1` |

Allows to route a `SQS` message to a specific endpoint on the `Worker` instead of having a single endpoint handling all the messages.

Expand All @@ -22,12 +22,12 @@ StronglyTypedMessage model = new StronglyTypedMessage();

var sendMessageRequest = new SendMessageRequest
{
// Serialize your model as JSON
MessageBody = JsonConvert.SerializeObject(model)
// Set the QueueUrl
// Serialize your model as JSON (you can use Newtonsoft.Json if you prefer)
MessageBody = System.Text.Json.JsonSerializer.Serialize(model)
// Set the QueueUrl and other properties as you see fit
};

// AddRoutingAttribute is an extension method
// AddRoutingAttribute is an extension method in the "BeanstalkWorker.SimpleRouting" namespace
sendMessageRequest.MessageAttributes.AddRoutingAttribute("task-name");
```

Expand All @@ -37,19 +37,19 @@ A sample `Web` app is provided in [samples/SampleWeb](samples/SampleWeb).

You can send two distinct types of messages by hitting two different endpoints:

- `GET /send/work`
- `GET /send/nothing`
- `GET http://localhost:5000/send/work`
- `GET http://localhost:5000/send/nothing`

##### Configuration

Create a `iAM` user (if you don't have one already) which has access to `SQS`.

You'll need to configure four settings, either using [user secrets][secret-manager] (preferred way as they'll be shared with the sample worker), `appsettings.json` or via [environment variables][environment-variables]:
You'll need to configure four settings using [user secrets][secret-manager]:

- `Aws:RegionSystemName` - [region code][available-regions], for example `ap-southeast-2`
- `Aws:Queue:WorkerQueueUrl` - `URL` of the `SQS` queue, for example `https://sqs.ap-southeast-2.amazonaws.com/375985941080/dev-gabriel`
- `AWS_ACCESS_KEY_ID` - this is the `Access key ID` of your `iAM user`
- `AWS_SECRET_ACCESS_KEY` - this is the `Secret access key` of your `iAM user`
- `Aws:Queue:AccessKeyId` - this is the `Access key ID` of your `iAM user`
- `Aws:Queue:SecretAccessKey` - this is the `Secret access key` of your `iAM user`

### Worker Tier

Expand All @@ -60,9 +60,12 @@ In the `Configure` method of your `Startup` class:
```csharp
public void Configure(IApplicationBuilder app)
{
// The simple routing middleware needs to be added **before** configuring endpoint routing
app.UseHeaderRouting();

// Abbreviated for clarity
app.UseRouting();

app.UseEndpoints(endpoint => endpoint.MapControllers());
}
```

Expand All @@ -71,9 +74,10 @@ public void Configure(IApplicationBuilder app)
```csharp
// This is important, we do not want a prefix in front of the action's route
[Route("")]
public class SomeController : Controller
[ApiController]
public class SomeController : ControllerBase
{
// The route has to match the argument given to AddRoutingAttribute
// The route template has to match the argument given to AddRoutingAttribute
[HttpPost("task-name")]
public async Task<IActionResult> SomeMethod(StronglyTypedMessage model)
{
Expand Down Expand Up @@ -108,4 +112,3 @@ If you wish to run the `Worker` without deploying to `AWS Beanstalk` you can lev
[app-veyor]: https://ci.appveyor.com/project/GabrielWeyer/simple-routing
[app-veyor-shield]: https://ci.appveyor.com/api/projects/status/github/gabrielweyer/simple-routing?branch=master&svg=true
[secret-manager]: https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.1&tabs=windows#secret-manager
[environment-variables]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1#environment-variables-configuration-provider
10 changes: 5 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
image: Visual Studio 2017
image: Visual Studio 2019
branches:
only:
- master
# We'll also build whenever there is a new commit on any branch starting with `features/`
- /features\/.+/
build_script:
- ps: |
dotnet tool restore
dotnet cake build.cake --bootstrap
dotnet cake build.cake --pack
assembly_info:
Expand Down Expand Up @@ -52,9 +53,9 @@ deploy:
api_key:
# Encrypted `NuGet.org` token - https://www.nuget.org/account/ApiKeys
# https://www.appveyor.com/docs/deployment/nuget/#provider-settings
secure: Sqd52uKYGsHmidz0HCm4Z/aspoRiulxr5U6PbQLL9QytEHQ0Iw2kqzETcvYewDYq
secure: C5GBFhLf/V0BSWI2vozKYgh9imNBcW/8LNBQzHvI/Qw5wPrpQGQNbHOeaorLFKQB
skip_symbols: false
symbol_server: https://nuget.smbsrc.net/
symbol_server: https://www.nuget.org/api/v2/symbolpackage
artifact: packages
on:
branch: master
Expand All @@ -78,5 +79,4 @@ install:
# `SimpleRouting` is targeting `netstandard2.0`, so we can safely install the latest `SDK`
# The `SDK` is required to restore, build, publish... a `.NET Core` application
# https://www.microsoft.com/net/download/windows
- ps: .\build\dotnet-install.ps1 -Channel Current
- ps: dotnet tool install --global Cake.Tool --version 0.31.0
- ps: .\build\dotnet-install.ps1 -InstallDir 'C:\Program Files\dotnet\'
2 changes: 1 addition & 1 deletion bootstrap.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
dotnet tool install Cake.Tool --global --version 0.31.0
dotnet tool restore
dotnet cake build.cake --bootstrap
dotnet cake build.cake
2 changes: 1 addition & 1 deletion bootstrap.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
dotnet tool install Cake.Tool --global --version 0.31.0
dotnet tool restore
dotnet cake build.cake --bootstrap
dotnet cake build.cake
8 changes: 4 additions & 4 deletions build.cake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#module nuget:?package=Cake.DotNetTool.Module&version=0.1.0
#module nuget:?package=Cake.DotNetTool.Module&version=0.4.0

#tool dotnet:?package=GitVersion.Tool&version=4.0.1-beta1-58
#tool dotnet:?package=GitVersion.Tool&version=5.3.5

var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
Expand Down Expand Up @@ -115,9 +115,9 @@ Task("PublishAppVeyor")
.WithCriteria(() => HasArgument("pack") && AppVeyor.IsRunningOnAppVeyor)
.Does(() =>
{
CopyFiles($"{packagesDir}/*.nupkg", MakeAbsolute(Directory("./")), false);
CopyFiles($"{packagesDir}/*nupkg", MakeAbsolute(Directory("./")), false);
GetFiles($"./*.nupkg")
GetFiles($"./*nupkg")
.ToList()
.ForEach(f => AppVeyor.UploadArtifact(f, new AppVeyorUploadArtifactsSettings { DeploymentName = "packages" }));
});
Expand Down
11 changes: 5 additions & 6 deletions samples/Core/Core.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>BeanstalkWorker.SimpleRouting.Core</AssemblyName>
<RootNamespace>BeanstalkWorker.SimpleRouting.Core</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.SQS" Version="3.3.3.44" />
<PackageReference Include="BeanstalkWorker.SimpleRouting" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="AWSSDK.SQS" Version="3.3.102.118" />
<PackageReference Include="BeanstalkWorker.SimpleRouting" Version="1.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.4" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion samples/Core/Models/DoNothingMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace BeanstalkWorker.SimpleRouting.Core.Models
{
public class DoNothingMessage
{
public TimeSpan RestDuration { get; set; }
public DateTimeOffset StartAt { get; set; }
}
}
2 changes: 1 addition & 1 deletion samples/Core/Models/DoWorkMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace BeanstalkWorker.SimpleRouting.Core.Models
public class DoWorkMessage
{
public string NatureOfWork { get; set; }
public TimeSpan ExpectedDurationOfWork { get; set; }
public DateTimeOffset StartsAt { get; set; }
}
}
126 changes: 10 additions & 116 deletions samples/SampleWeb/Program.cs
Original file line number Diff line number Diff line change
@@ -1,129 +1,23 @@
using System;
using Amazon.SQS.Model;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace BeanstalkWorker.SimpleRouting.SampleWeb
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
BuildWebHost(args).Build().Run();
}

private static IWebHost BuildWebHost(string[] args)
private static IHostBuilder BuildWebHost(string[] args)
{
var webHostBuilder = WebHost.CreateDefaultBuilder(args);

var contentRoot = webHostBuilder.GetSetting("contentRoot");
var environment = webHostBuilder.GetSetting("ENVIRONMENT");

var isDevelopment = EnvironmentName.Development.Equals(environment);

var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(contentRoot)
.AddJsonFile("appsettings.json", false, false)
.AddEnvironmentVariables();

if (isDevelopment)
{
configurationBuilder.AddUserSecrets<Program>();
}

var configuration = configurationBuilder.Build();

var serilogLevel = configuration.GetLoggingLevel("MinimumLevel:Default");

var loggerConfiguration = new LoggerConfiguration()
.Destructure.ByTransforming<MessageAttributeValue>(a => new {a.DataType, a.StringValue})
.Enrich.WithDemystifiedStackTraces()
.ReadFrom.Configuration(configuration);

if (isDevelopment)
{
loggerConfiguration = loggerConfiguration.WriteTo.Console(serilogLevel);
}

var logger = loggerConfiguration.CreateLogger();

try
{
logger.Information("Starting Host...");

SetAwsEnvironmentVariables(configuration, logger);

return webHostBuilder
.UseStartup<Startup>()
.UseConfiguration(configuration)
.UseSerilog(logger, true)
.Build();
}
catch (Exception ex)
{
logger.Fatal(ex, "Host terminated unexpectedly");
throw;
}
}

private static void SetAwsEnvironmentVariables(IConfigurationRoot configuration, Logger logger)
{
const string awsAccessKeyIdVariableName = "AWS_ACCESS_KEY_ID";
const string awsSecretAccessKeyVariableName = "AWS_SECRET_ACCESS_KEY";

var accessKeyIdFromEnvironmentVariable = Environment.GetEnvironmentVariable(awsAccessKeyIdVariableName);
var secretAccessKeyFromEnvironmentVariable = Environment.GetEnvironmentVariable(awsSecretAccessKeyVariableName);

if (!string.IsNullOrWhiteSpace(accessKeyIdFromEnvironmentVariable) &&
!string.IsNullOrWhiteSpace(secretAccessKeyFromEnvironmentVariable))
{
logger.Information($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' set via environment variables");

return;
}

var accessKeyIdFromConfiguration = configuration.GetValue<string>(awsAccessKeyIdVariableName);
var secretAccessKeyFromConfiguration = configuration.GetValue<string>(awsSecretAccessKeyVariableName);

if (!string.IsNullOrWhiteSpace(accessKeyIdFromConfiguration) &&
!string.IsNullOrWhiteSpace(secretAccessKeyFromConfiguration))
{
logger.Information($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' present in configuration, setting matching environment variables");

Environment.SetEnvironmentVariable(
awsAccessKeyIdVariableName,
accessKeyIdFromConfiguration,
EnvironmentVariableTarget.Process);

Environment.SetEnvironmentVariable(
awsSecretAccessKeyVariableName,
secretAccessKeyFromConfiguration,
EnvironmentVariableTarget.Process);
}
else
{
throw new InvalidOperationException($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' should either be set as environment variables or configuration, please refer to the README: https://github.com/gabrielweyer/simple-routing/blob/master/README.md#configuration.");
}
}
}

internal static class ConfigurationRootExtensions
{
internal static LogEventLevel GetLoggingLevel(this IConfigurationRoot configuration, string keyName,
LogEventLevel defaultLevel = LogEventLevel.Warning)
{
try
{
return configuration.GetValue($"Serilog:{keyName}", LogEventLevel.Warning);
}
catch (Exception)
{
return defaultLevel;
}
return Host
.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
}
11 changes: 2 additions & 9 deletions samples/SampleWeb/SampleWeb.csproj
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>fa5b7428-c384-484b-bf75-1d9b2d1526a0</UserSecretsId>
<AssemblyName>BeanstalkWorker.SimpleRouting.SampleWeb</AssemblyName>
<RootNamespace>BeanstalkWorker.SimpleRouting.SampleWeb</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.SQS" Version="3.3.3.44" />
<PackageReference Include="BeanstalkWorker.SimpleRouting" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.All" />
<PackageReference Include="Serilog" Version="2.7.1" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
<PackageReference Include="Serilog.Enrichers.Demystify" Version="0.1.0-dev-00016" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="AWSSDK.SQS" Version="3.3.102.118" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
Expand Down
Loading

0 comments on commit 3080a98

Please sign in to comment.