Skip to content

Commit

Permalink
docs: create a documentation and API reference site
Browse files Browse the repository at this point in the history
  • Loading branch information
philasmar committed Dec 6, 2023
1 parent f2a95d7 commit c8711f0
Show file tree
Hide file tree
Showing 19 changed files with 519 additions and 1 deletion.
47 changes: 47 additions & 0 deletions .github/workflows/doc-site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Generate Documentation and API Reference

# Trigger the action on push to main
on:
push:
branches:
- main

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
publish-docs:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Dotnet Setup
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.x

- run: dotnet tool update -g docfx --version 2.74.0
- run: docfx docs/docfx.json

- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
# Upload entire repository
path: 'docs/_site'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -477,4 +477,8 @@ $RECYCLE.BIN/
*.lnk

# JetBrains Rider cache/options directory
.idea/
.idea/

# DocFx
docs/_site/
docs/api/
52 changes: 52 additions & 0 deletions docs/docfx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"metadata": [
{
"src": [
{
"src": "../src",
"files": [
"**/*.csproj"
]
}
],
"dest": "api",
"filter": "filter.yml"
}
],
"build": {
"content": [
{
"files": [
"**/*.{md,yml}"
],
"exclude": [
"_site/**",
"filter.yml"
]
}
],
"resource": [
{
"files": [
"docs/assets/images/**"
]
}
],
"output": "_site",
"template": [
"default",
"modern",
"template"
],
"globalMetadata": {
"_appName": "",
"_appTitle": "AWS Message Processing Framework for .NET",
"_appLogoPath": "docs/assets/images/aws-logo.svg",
"_appFaviconPath": "docs/assets/images/favicon.ico",
"_enableSearch": true,
"pdf": false,
"_disableContribution": true,
"_appFooter": "<div class='text-center'>© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved.</div>"
}
}
}
1 change: 1 addition & 0 deletions docs/docs/assets/images/aws-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/assets/images/favicon.ico
Binary file not shown.
File renamed without changes
File renamed without changes
File renamed without changes.
196 changes: 196 additions & 0 deletions docs/docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Getting Started

Add the `AWS.Messaging` NuGet package to your project
```
dotnet add package AWS.Messaging
```

The framework integrates with Microsoft's dependency injection (DI) container. This can be done in your application startup by calling `AddAWSMessageBus` to add the AWS Message Processing Framework for .NET to the DI container.

```csharp
var builder = WebApplication.CreateBuilder(args);
// Register the AWS Message Processing Framework for .NET
builder.Services.AddAWSMessageBus(builder =>
{
// Register a .NET object to an SQS Queue
builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");
});
```

The message bus allows for adding the necessary configuration to support applications that are publishing messages, processing messages or doing both at the same time.

Sample configuration for a `Publisher`:

```csharp
var builder = WebApplication.CreateBuilder(args);

// Register the AWS Message Processing Framework for .NET
builder.Services.AddAWSMessageBus(builder =>
{
// Register a .NET object to an SQS Queue
builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");

// Register a .NET object to an SNS Topic
builder.AddSNSPublisher<OrderInfo>("arn:aws:sns:us-west-2:012345678910:MyAppProd");

// Register a .NET object to an EventBridge Event Bus
builder.AddEventBridgePublisher<FoodItem>("arn:aws:events:us-west-2:012345678910:event-bus/default");

// Configure serialization options
builder.ConfigureSerializationOptions(options =>
{
options.SystemTextJsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
});
});
```

Once you have registered the framework in the DI container, all you need to publish a message is inject the `IMessagePublisher` into your code and call the `PublishAsync` method.

Here is an example showing a sample publisher for a hypothetical `ChatMessage` message.

```csharp
[ApiController]
[Route("[controller]")]
public class PublisherController : ControllerBase
{
private readonly IMessagePublisher _messagePublisher;

public PublisherController(IMessagePublisher messagePublisher)
{
_messagePublisher = messagePublisher;
}

[HttpPost("chatmessage", Name = "Chat Message")]
public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
{
// Add business and validation logic here
if (message == null)
{
return BadRequest("A chat message was not used.");
}
if (string.IsNullOrEmpty(message.MessageDescription))
{
return BadRequest("The MessageDescription cannot be null or empty.");
}

await _messagePublisher.PublishAsync(message);

return Ok();
}
}
```

If your application is a subscriber, your need to implement a message handler `IMessageHandler` interface for the message you wish to process. The message type and message handler are set up in the project startup.

Sample configuration for a `Subscriber`:

```csharp
await Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
// Register the AWS Message Processing Framework for .NET
services.AddAWSMessageBus(builder =>
{
// Register an SQS Queue for the message pump to poll for messages
builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");

// Register all IMessageHandler implementations with the message type they should process
builder.AddMessageHandler<ChatMessageHandler, ChatMessage>();
});
})
.Build()
.RunAsync();
```

Here is an example showing a sample message handler for a hypothetical `ChatMessage` message.

```csharp
public class ChatMessageHandler : IMessageHandler<ChatMessage>
{
public Task<MessageProcessStatus> HandleAsync(MessageEnvelope<ChatMessage> messageEnvelope, CancellationToken token = default)
{
// Add business and validation logic here
if (messageEnvelope == null)
{
return Task.FromResult(MessageProcessStatus.Failed());
}

if (messageEnvelope.Message == null)
{
return Task.FromResult(MessageProcessStatus.Failed());
}

var message = messageEnvelope.Message;

Console.WriteLine($"Message Description: {message.MessageDescription}");

return Task.FromResult(MessageProcessStatus.Success());
}
}
```

## Using service-specific publishers

The AWS Message Processing Framework for .NET exposes service-specific publishers for the supported services SQS, SNS and EventBridge. These publishers are accessible through the DI container via the types `ISQSPublisher`, `ISNSPublisher` and `IEventBridgePublisher`. When using these publishers, you have access to service-specific options/configurations that can be set when publishing a message.

An example of using `ISQSPublisher` to set SQS-specific options:
```csharp
public class PublisherController : ControllerBase
{
private readonly ISQSPublisher _sqsPublisher;

public PublisherController(ISQSPublisher sqsPublisher)
{
_sqsPublisher = sqsPublisher;
}

[HttpPost("chatmessage", Name = "Chat Message")]
public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
{
if (message == null)
{
return BadRequest("A chat message was not used.");
}
if (string.IsNullOrEmpty(message.MessageDescription))
{
return BadRequest("The MessageDescription cannot be null or empty.");
}

await _sqsPublisher.PublishAsync(message, new SQSOptions
{
DelaySeconds = <delay-in-seconds>,
MessageAttributes = <message-attributes>,
MessageDeduplicationId = <message-deduplication-id>,
MessageGroupId = <message-group-id>
});

return Ok();
}
}
```

The same can be done for `SNS` and `EventBridge` publishers using `ISNSPublisher` and `IEventBridgePublisher` respectively:
```csharp
await _snsPublisher.PublishAsync(message, new SNSOptions
{
Subject = <subject>,
MessageAttributes = <message-attributes>,
MessageDeduplicationId = <message-deduplication-id>,
MessageGroupId = <message-group-id>
});
```
```csharp
await _eventBridgePublisher.PublishAsync(message, new EventBridgeOptions
{
DetailType = <detail-type>,
Resources = <resources>,
Source = <source>,
Time = <time>,
TraceHeader = <trace-header>
});
```
39 changes: 39 additions & 0 deletions docs/docs/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# AWS Message Processing Framework for .NET

**Notice:** *This library is still in early active development and is not ready for use beyond experimentation.*

The AWS Message Processing Framework for .NET is an AWS native framework that simplifies development of .NET message processing applications using AWS services.

The purpose of the framework is to reduce the amount of boiler-plate code developers need to write. The primary responsibilities of the framework are:

* In a publisher, the framework will handle routing the messages to the correct queue/topic/event bus.
* In a consumer process, the framework will route the particular message type to the appropriate business logic.
* The framework will handle serializing/deserializing the message to .NET objects, keeping track of the message visibility while it is being processed, and deleting the message when completed.

# Project Status

The framework is currently under active development.

Already done:
* Support for publishing to SQS, SNS and EventBridge
* Support for polling messages from an SQS queue
* Support for customizing serialization
* Message manager to manage message lifecycle

Features to be added:
* Polling messages from Lambda
* Performance hardening
* Improve exception handling
* Configure the framework using `IConfiguration`
* Add telemetry to track messages through the framework

# Useful Links
* [AWS Message Processing Framework for .NET Design Document](./design/message-processing-framework-design.md)

# Security

See [CONTRIBUTING](https://github.com/awslabs/aws-dotnet-messaging/blob/main/CONTRIBUTING.md) for more information.

# License

This project is licensed under the Apache-2.0 License.
16 changes: 16 additions & 0 deletions docs/docs/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
- name: Introduction
- name: Overview
href: overview.md
- name: Getting Started
href: getting-started.md
- name: Advanced
- name: Design
items:
- name: AWS Message Processing Framework for .NET
href: ./design/message-processing-framework-design.md
- name: Message Source Computation
href: ./design/message-source-computation-design.md
- name: SQS Message Visibility Timeout Handling
href: ./design/message-visibility-timeout-handling.md
- name: Telemetry
href: ./design/telemetry-design.md
7 changes: 7 additions & 0 deletions docs/filter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiRules:
- exclude:
uidRegex: ^*.Internal
type: Namespace
- exclude:
uidRegex: ^Microsoft.Extensions.DependencyInjection
type: Namespace
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
_layout: landing
redirect_url: docs/overview.html
---
Loading

0 comments on commit c8711f0

Please sign in to comment.