Skip to content

Commit 0ebe56a

Browse files
committed
Adding CloudEvents samples for ASB and SQS.
1 parent f22e29f commit 0ebe56a

File tree

15 files changed

+354
-0
lines changed

15 files changed

+354
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 18
3+
VisualStudioVersion = 18.3.11222.16 d18.3
4+
MinimumVisualStudioVersion = 15.0.26730.12
5+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Endpoint", "Endpoint\Endpoint.csproj", "{7081E12A-888F-4506-A435-970E50BA4C0B}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
EndGlobalSection
11+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
12+
{7081E12A-888F-4506-A435-970E50BA4C0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13+
{7081E12A-888F-4506-A435-970E50BA4C0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
14+
{22B1E205-B713-45C3-A041-62CCDDA9646B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{22B1E205-B713-45C3-A041-62CCDDA9646B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
EndGlobalSection
17+
GlobalSection(SolutionProperties) = preSolution
18+
HideSolutionNode = FALSE
19+
EndGlobalSection
20+
GlobalSection(ExtensibilityGlobals) = postSolution
21+
SolutionGuid = {6E692BB9-1D3D-4DA0-B777-DB9C754E7342}
22+
EndGlobalSection
23+
EndGlobal
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#region cloudevents-message-definition
2+
public class AwsBlobNotification :
3+
IMessage
4+
{
5+
public string Key { get; set; }
6+
public int Size { get; set; }
7+
public string ETag { get; set; }
8+
public string Sequencer { get; set; }
9+
}
10+
#endregion
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
public class AwsBlobNotificationHandler(ILogger<AwsBlobNotification> logger) :
4+
IHandleMessages<AwsBlobNotification>
5+
{
6+
public Task Handle(AwsBlobNotification message, IMessageHandlerContext context)
7+
{
8+
logger.LogInformation("Blob {Key} created!", message.Key);
9+
return Task.CompletedTask;
10+
}
11+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<OutputType>Exe</OutputType>
6+
<LangVersion>14.0</LangVersion>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="NServiceBus.Envelope.CloudEvents" Version="1.0.0-alpha.3" />
12+
<PackageReference Include="NServiceBus.AmazonSQS" Version="9.0.0-alpha.3" />
13+
<PackageReference Include="NServiceBus.Extensions.Hosting" Version="4.0.0-alpha.3" />
14+
</ItemGroup>
15+
16+
</Project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Text.Json;
2+
using Microsoft.Extensions.Hosting;
3+
4+
Console.Title = "CloudEvents";
5+
6+
var builder = Host.CreateApplicationBuilder(args);
7+
8+
var endpointConfiguration = new EndpointConfiguration("Samples.Sqs.CloudEvents");
9+
endpointConfiguration.EnableInstallers();
10+
11+
#region cloudevents-serialization
12+
endpointConfiguration.UseSerialization<SystemJsonSerializer>().Options(new JsonSerializerOptions
13+
{
14+
PropertyNameCaseInsensitive = true,
15+
IncludeFields = true
16+
});
17+
#endregion
18+
19+
#region cloudevents-configuration
20+
endpointConfiguration.EnableCloudEvents().TypeMappings = new Dictionary<string, Type[]>
21+
{
22+
["ObjectCreated:Put"] = [typeof(AwsBlobNotification)]
23+
};
24+
#endregion
25+
26+
var transport = new SqsTransport();
27+
endpointConfiguration.UseTransport(transport);
28+
29+
30+
Console.WriteLine("Press any key, the application is starting");
31+
Console.ReadKey();
32+
Console.WriteLine("Starting...");
33+
34+
builder.UseNServiceBus(endpointConfiguration);
35+
await builder.Build().RunAsync();

samples/aws/cloud-events/Sqs_9/prerelease.txt

Whitespace-only changes.

samples/aws/cloud-events/sample.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
title: AmazonSQS CloudEvents Sample
3+
summary: Demonstrates how to consume CloudEvents via the Amazon SQS
4+
reviewed: 2025-12-10
5+
component: Sqs
6+
related:
7+
- transports/sqs
8+
---
9+
10+
## Prerequisites
11+
12+
### Security and access configuration
13+
14+
Add the [AWS Access Key ID and AWS Secret Access Key](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) to the following environment variables:
15+
16+
* Access Key ID in `AWS_ACCESS_KEY_ID`
17+
* Secret Access Key in `AWS_SECRET_ACCESS_KEY`
18+
* Default Region in `AWS_REGION`
19+
20+
See also [AWS Account Identifiers](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html), [Managing Access Keys for an AWS Account](https://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html), and [IAM Security Credentials](https://console.aws.amazon.com/iam/home#/security_credential).
21+
22+
See also [AWS Regions](https://docs.aws.amazon.com/general/latest/gr/rande.html) for a list of available regions.
23+
24+
### S3 configuration
25+
26+
The S3 bucket should be configured to generate notifications that are ultimately delivered to the SQS queue matching the endpoint. There are many ways to configure the setup. One example configuration includes:
27+
28+
- Configuring S3 bucket to [send notifications to SQS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types)
29+
- Creating [Amazon EventBridge Pipe](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-event-target.html) that picks up the messages from the SQS queue
30+
- Configuring the Pipe to [transform](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-input-transformation.html) the messages to the CloudEvents schema as specified in the [CloudEvents specification](https://github.com/cloudevents/spec/blob/main/cloudevents/adapters/aws-s3.md).
31+
- Configuring the Pipe to call AWS Lambda that would enrich the message with the proper `content-type` property and send the message to the SQS queue matching the endpoint.
32+
33+
## Code walk-through
34+
35+
This sample shows an endpoint receiving a CloudEvents message from the Amazon Simple Queue Service (Amazon SQS)
36+
37+
* The `Endpoint` defines the schema for the CloudEvents message.
38+
* The `Endpoint` enables CloudEvents support and configures the type mapping.
39+
* The `Endpoint` configures the serializer to support fields and properties with different casing.
40+
* The `Endpoint` receives the message and calls the proper handler.
41+
42+
### CloudEvents message schema
43+
44+
The message schema is defined as follows:
45+
46+
snippet: cloudevents-message-definition
47+
48+
This schema must match the schema of the [notification generated by S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types).
49+
50+
### CloudEvents support configuration
51+
52+
CloudEvents support must be explicitly enabled, including the type mapping to match the messages with the classes:
53+
54+
snippet: cloudevents-configuration
55+
56+
To support the differences between uppercase letters and lowercase letters in the schema definition and content, the serializer is configured to use case insensitive mapping:
57+
58+
snippet: cloudevents-serialization
59+
60+
61+
### Running the sample
62+
63+
1. Run the sample.
64+
2. Generate the `ObjectCreated:Put` event by creating a new file in the S3 bucket.
65+
3. Observe that the sample prints out the URL of the newly created file.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 18
3+
VisualStudioVersion = 18.3.11222.16 d18.3
4+
MinimumVisualStudioVersion = 15.0.26730.12
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Endpoint", "Endpoint\Endpoint.csproj", "{1874F4C3-9250-8342-8F1E-4E2692AD6BE3}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
Release|Any CPU = Release|Any CPU
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14+
{1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
15+
{1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
16+
{1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Release|Any CPU.Build.0 = Release|Any CPU
17+
EndGlobalSection
18+
GlobalSection(SolutionProperties) = preSolution
19+
HideSolutionNode = FALSE
20+
EndGlobalSection
21+
EndGlobal
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using NServiceBus;
2+
3+
#region cloudevents-message-definition
4+
public class BlobCreated :
5+
IMessage
6+
{
7+
public string Api { get; set; }
8+
public string ClientRequestId { get; set; }
9+
public string RequestId { get; set; }
10+
public string ETag { get; set; }
11+
public string ContentType { get; set; }
12+
public int ContentLength { get; set; }
13+
public string BlobType { get; set; }
14+
public string Url { get; set; }
15+
public string Sequencer { get; set; }
16+
public StorageDiagnostics StorageDiagnostics { get; set; }
17+
}
18+
19+
public class StorageDiagnostics
20+
{
21+
public string BatchId { get; set; }
22+
}
23+
#endregion
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.Extensions.Logging;
3+
using NServiceBus;
4+
5+
public class BlobCreatedHandler(ILogger<BlobCreated> logger) :
6+
IHandleMessages<BlobCreated>
7+
{
8+
public Task Handle(BlobCreated message, IMessageHandlerContext context)
9+
{
10+
logger.LogInformation("Blob {Url} created!", message.Url);
11+
return Task.CompletedTask;
12+
}
13+
}

0 commit comments

Comments
 (0)