Skip to content

Commit

Permalink
Merge pull request #4404 from Particular/webjobsample
Browse files Browse the repository at this point in the history
Webjob sample
  • Loading branch information
danielmarbach committed Jun 27, 2019
2 parents 8e10aa7 + 5f1f81e commit 6b24df2
Show file tree
Hide file tree
Showing 13 changed files with 279 additions and 0 deletions.
87 changes: 87 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/ContinuousJob.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using NServiceBus;
using NServiceBus.Logging;

public class ContinuousJob : IJobHost
{
public ContinuousJob(IConfiguration configuration, IServiceCollection services)
{
this.configuration = configuration;
this.services = services;
}

#region WebJobHost_Start
public async Task StartAsync(CancellationToken cancellationToken)
{
endpointConfiguration = new EndpointConfiguration("receiver");
endpointConfiguration.SendFailedMessagesTo("error");
endpointConfiguration.AuditProcessedMessagesTo("audit");
endpointConfiguration.DefineCriticalErrorAction(OnCriticalError);
endpointConfiguration.UsePersistence<InMemoryPersistence>();
endpointConfiguration.EnableInstallers();
endpointConfiguration.UseSerialization<NewtonsoftSerializer>();
endpointConfiguration.EnableInstallers();

var transportConnectionString = configuration.GetConnectionString("TransportConnectionString");

var transport = endpointConfiguration.UseTransport<AzureStorageQueueTransport>();
transport.ConnectionString(transportConnectionString);

endpoint = await Endpoint.Start(endpointConfiguration);
#endregion

_ = SimulateWork();
}

private async Task SimulateWork()
{
// sending here to simulate work
await endpoint.SendLocal(new MyMessage());
await endpoint.SendLocal(new MyMessage());
}

#region WebJobHost_Stop

public async Task StopAsync()
{
await endpoint.Stop();
}
#endregion

public Task CallAsync(string name, IDictionary<string, object> arguments = null, CancellationToken cancellationToken = default)
{
// this method is not needed for NServiceBus to run
throw new NotImplementedException();
}

#region WebJobHost_CriticalError
static async Task OnCriticalError(ICriticalErrorContext context)
{
var fatalMessage =
$"The following critical error was encountered:\n{context.Error}\nProcess is shutting down.";
Logger.Fatal(fatalMessage, context.Exception);

if (Environment.UserInteractive)
{
// so that user can see on their screen the problem
await Task.Delay(10_000);
}

Environment.FailFast(fatalMessage, context.Exception);

}
#endregion


readonly IConfiguration configuration;
readonly IServiceCollection services;
EndpointConfiguration endpointConfiguration;
IEndpointInstance endpoint;
static ILog Logger = LogManager.GetLogger<ContinuousJob>();
}
34 changes: 34 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public static class HostBuilderExtensions
{
public static IHostBuilder ConfigureHost(this IHostBuilder hostBuilder)
{
hostBuilder.ConfigureHostConfiguration(builder =>
{
builder.AddEnvironmentVariables("DOTNET_");
builder.AddEnvironmentVariables();
});

hostBuilder.ConfigureAppConfiguration((context, builder) =>
{
builder.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName.ToLowerInvariant()}.json", optional: true);
});

hostBuilder.ConfigureWebJobs(builder => { builder.AddAzureStorageCoreServices(); });

hostBuilder.ConfigureLogging((context, builder) => { builder.AddConsole(); });

hostBuilder.ConfigureServices((context, services) =>
{
services.AddSingleton<IJobHost, ContinuousJob>();
services.AddSingleton(services);
});

return hostBuilder;
}
}
4 changes: 4 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/MyMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using NServiceBus;
public class MyMessage : ICommand
{
}
14 changes: 14 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/MyMessageHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Threading.Tasks;
using NServiceBus;
using NServiceBus.Logging;

public class MyMessageHandler : IHandleMessages<MyMessage>
{
public Task Handle(MyMessage message, IMessageHandlerContext context)
{
Logger.Info("Received message");
return Task.CompletedTask;
}

private static ILog Logger = LogManager.GetLogger<MyMessageHandler>();
}
19 changes: 19 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Hosting;

class Program
{
static async Task Main(string[] args)
{
var host = new HostBuilder()
.ConfigureHost()
.Build();

var cancellationToken = new WebJobsShutdownWatcher().Token;
using (host)
{
await host.RunAsync(cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"profiles": {
"Receiver": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}
31 changes: 31 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/Receiver.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.9" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="3.0.2" />
<PackageReference Include="NServiceBus.Azure.Transports.WindowsAzureStorageQueues " Version="8.1.4" />
<PackageReference Include="NServiceBus.Newtonsoft.Json" Version="2.2.0" />
</ItemGroup>
<ItemGroup Label="To disable Dashboard logging (https://docs.microsoft.com/en-us/azure/app-service/webjobs-sdk-get-started#enable-console-logging)">
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Settings.job">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="run.cmd">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/Settings.job
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"stopping_wait_time": 60
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"TransportConnectionString": "UseDevelopmentStorage=true"
}
}
2 changes: 2 additions & 0 deletions samples/azure/webjob-host/Core_7/Receiver/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
1 change: 1 addition & 0 deletions samples/azure/webjob-host/Core_7/Receiver/run.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dotnet Notifications.dll
25 changes: 25 additions & 0 deletions samples/azure/webjob-host/Core_7/WebJobHost.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.12
MinimumVisualStudioVersion = 15.0.26730.12
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Receiver", "Receiver\Receiver.csproj", "{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}.Debug|x64.ActiveCfg = Debug|Any CPU
{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}.Debug|x64.Build.0 = Debug|Any CPU
{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}.Debug|x86.ActiveCfg = Debug|Any CPU
{52DEA2AF-D7EC-48EB-96E5-4C852C0136CD}.Debug|x86.Build.0 = Debug|Any CPU
EndGlobalSection
EndGlobal
44 changes: 44 additions & 0 deletions samples/azure/webjob-host/sample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: Self Hosting in Web Jobs
summary: Uses NServiceBus self-hosting capability to host an endpoint in a web job.
component: Core
reviewed: 2019-06-26
tags:
- Azure
- Hosting
related:
- nservicebus/dependency-injection/msdependencyinjection
- samples/dependency-injection/aspnetcore

---

This sample is compatible with WebJobs SDK 3.0

## Running in development mode

1. Start [Azure Storage Emulator](https://docs.microsoft.com/en-us/azure/storage/storage-use-emulator)
1. Run the solution

## Code walk-through

This sample contains one project:

- Receiver - Self-hosted endpoint running in a continuous web job

### Receiver project

The receiver project uses the self-hosting capability to start an end endpoint inside a continuously running web job.

The snippet below illustrates how the `StartAsync` method of `IJobHost` can be used to configure and start the endpoint

snippet: WebJobHost_Start

If dependencies need to be shared between the service collection and NServiceBus infrastructure like handlers the [MSDependencyInjection nuget package](/nservicebus/dependency-injection/msdependencyinjection.md) needs to be configured.

A critical error action needs to be defined to restart the host when a critical error is raised.

snippet: WebJobHost_CriticalError

When the job host stops the endpoint needs to be shutdown to properly release all acquired ressources.

snippet: WebJobHost_Stop

0 comments on commit 6b24df2

Please sign in to comment.