Skip to content

Commit

Permalink
Improve packages
Browse files Browse the repository at this point in the history
  • Loading branch information
arkiaconsulting committed May 26, 2024
1 parent 3647921 commit 8b548aa
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 33 deletions.
183 changes: 183 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# ActiveMQ Extension for Azure Functions

## Introduction
This repository contains the bindings and extension for ActiveMQ in Azure Functions. It's based on the [Apache.NMS](https://www.nuget.org/packages/Apache.NMS.AMQP) library.

These extensions has been tested with Artemis ActiveMQ.

There are two types of bindings in this extension:
- `ActiveMQTrigger`: This binding allows you to listen to a queue
- `ActiveMQ`: This binding allows you to send messages to a queue

## Usage

### `ActiveMQTrigger`

The `ActiveMQTrigger` binding allows you to listen to a queue.

> ***Note:***
> The `ActiveMQTrigger` binding is not supported in the Consumption plan. You can use it in the Premium plan or the Dedicated (App Service) plan.
> ***Note:***
> Scaling out to multiple instances is not yet implemented
#### Configuration
- `queueName`: The name of the queue to listen to. Settings placeholders are supported, eg. `%MyQueue%`
- `Connection`: The raw endpoint (eg. amqp://localhost:5672/) or the name of the setting that contains it (eg. `ActiveMQ:Endpoint`)
- `UserName`: The username to use when connecting to the ActiveMQ server, or the setting that contains it (eg. `ActiveMQ:UserName`)
- `Password`: The password to use when connecting to the ActiveMQ server, or the setting that contains it (eg. `ActiveMQ:Password`)

#### Available parameter types
- `string`
- `Custom`: the content of the message is deserialized to the specified type

#### Example
The following example shows a function that listens to a queue, by using a string input

```csharp
[FunctionName("ActiveMQTrigger")]
public static void Run(
[ActiveMQTrigger("myqueue", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")] string message)
{
Console.WriteLine(message);
}
```

The following example shows a function that listens to a queue, by using a custom input

```csharp
[FunctionName("ActiveMQTrigger")]
public static void Run(
[ActiveMQTrigger("myqueue", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")] Order order)
{
Console.WriteLine(message);
}
```

### `ActiveMQ`

The `ActiveMQ` binding allows you to send messages to a queue.

#### Configuration
- `queueName`: The name of the queue to listen to. Settings placeholders are supported, eg. `%MyQueue%`
- `Connection`: The raw endpoint (eg. amqp://localhost:5672/) or the name of the setting that contains it (eg. `ActiveMQ:Endpoint`)
- `UserName`: The username to use when connecting to the ActiveMQ server, or the setting that contains it (eg. `ActiveMQ:UserName`)
- `Password`: The password to use when connecting to the ActiveMQ server, or the setting that contains it (eg. `ActiveMQ:Password`)

#### Available parameter types
- Types available in-process: `string`, `NmsTextMessage`, `NmsBytesMessage` and `ActiveMQOutputMessage`.
- Types available in isolated mode: `string` and `ActiveMQOutputMessage`.

*The `ActiveMQOutputMessage` is a type provided by the extension, and allows the client to set the content of the message and its properties*

#### Example
The following examples shows a function that sends a message to a queue in an Azure Function in-process:

```csharp
[FunctionName("MyFunction")]
public static void Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
[ActiveMQ("myqueue", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")] out string text)
{
text = "Hello, world!";
}
```

```csharp
[FunctionName("MyFunction")]
[return: ActiveMQ("myqueue", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")]
public static string Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)
{
return "Hello, world!";
}
```

```csharp
[FunctionName("MyFunction")]
[return: ActiveMQ("myqueue", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")]
public static NmsTextMessage Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
INmsMessageFactory messageFactory)
{
var message = messageFactory.CreateTextMessage("Hello, world!");
message.Properties.SetString("OrderId", Guid.NewGuid().ToString());

return message;
}
```

```csharp
[FunctionName("MyFunction")]
public static void Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
[ActiveMQ("myqueue", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")] out NmsBytesMessage message,
INmsMessageFactory messageFactory)
{
var message = messageFactory.CreateBytesMessage("Hello, world!");
message.Properties.SetString("OrderId", Guid.NewGuid().ToString());
}
```

```csharp
[Function("MyFunction")]
[return: ActiveMQOutput("%ActiveMQ:Queue%", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")]
public ActiveMQOutputMessage Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)
{
var json = JsonSerializer.Serialize(new { Text = "Hello, world!" });

return new ActiveMQOutputMessage
{
Text = json,
Properties = { { "OrderId", Guid.NewGuid().ToString() } }
};
}
```

The following examples shows a function that sends a message to a queue in an Azure Function isolated:

```csharp
[Function("MyFunction")]
[ActiveMQOutput("%ActiveMQ:Queue%", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")]
public string Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)
{
return JsonSerializer.Serialize(new { Text = "Hello, world!" });
}
```

```csharp
[Function("MyFunction")]
[ActiveMQOutput("%ActiveMQ:Queue%", Connection = "ActiveMQ:Endpoint", UserName = "ActiveMQ:UserName", Password = "ActiveMQ:Password")]
public ActiveMQOutputMessage Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)
{
var json = JsonSerializer.Serialize(new { Text = "Hello, world!" });

return new ActiveMQOutputMessage
{
Text = json,
Properties = { { "OrderId", Guid.NewGuid().ToString() } }
};
}
```

## Extension Configuration

The extension can be configured using the `host.json` file. Here is an example of the configuration:

```json
{
"version": "2.0",
"extensions": {
"activeMQ": {
"transportTimeout": 5000,
"transportStartupMaxReconnectAttempts": 1
}
}
}
```

## Contributing
This project welcomes contributions and suggestions.
66 changes: 36 additions & 30 deletions azure-pipelines.yaml
Original file line number Diff line number Diff line change
@@ -1,81 +1,87 @@
parameters:
- name: previewBuild
- name: previewRelease
type: boolean
default: true
- name: majorVersion
type: number
default: 0
- name: minorVersion
type: number
default: 0
- name: patchVersion
type: number
default: 0

pr:
branches:
include:
- main
trigger: none

trigger:
pr:
branches:
include:
- main

schedules:
- cron: "0 0 * * SAT"
branches:
include:
- main


variables:
Codeql.Enabled: true
# It is a release build if it is triggered by the main branch.
isReleaseBuild: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/main') }}
majorVersion: 0
minorVersion: 0
patchVersion: $[ counter(format('{0}.{1}-{2}', variables['majorVersion'], variables['minorVersion'], variables['isReleaseBuild']), 0) ]
majorVersion: ${{ parameters['majorVersion'] }}
minorVersion: ${{ parameters['minorVersion'] }}
patchVersion: ${{ parameters['patchVersion'] }}
shouldPublish: $[ eq(variables['Build.Reason'], 'Manual') ]
fullVersion: $[ format('{0}.{1}.{2}', variables['majorVersion'], variables['minorVersion'], variables['patchVersion']) ]
${{ if parameters['previewBuild'] }}:
releaseVersion: $[ format('{0}-{1}', variables['fullVersion'], 'preview') ]
${{ if parameters['previewRelease'] }}:
releaseVersion: $[ format('{0}-{1}.{2}', variables['fullVersion'], 'preview', variables['Build.BuildId']) ]
${{ else }}:
releaseVersion: $[ format('{0}', variables['fullVersion']) ]

jobs:
- job: Extension
displayName: dotnet and dotnet-isolated NuGet packages
displayName: in-process and isolated NuGet packages
steps:
- task: UseDotNet@2
displayName: Install .NET SDK
inputs:
packageType: sdk
version: 6.x
version: 8.x
performMultiLevelLookup: true

- task: DotNetCoreCLI@2
displayName: Build Akc.Azure.WebJobs.Extensions.ActiveMQ Release
condition: eq(variables.isReleaseBuild, 'True')
inputs:
command: build
arguments: $(Build.SourcesDirectory)/src/ActiveMQBinding/ActiveMQBinding.csproj --configuration Release -property:Version=$(releaseVersion)
arguments: $(Build.SourcesDirectory)/src/ActiveMQBinding/ActiveMQBinding.csproj --configuration Release -property:Version=$(releaseVersion) -property:ContinuousIntegrationBuild=true

- task: DotNetCoreCLI@2
displayName: Build Akc.Azure.Functions.Worker.Extensions.ActiveMQ Release
condition: eq(variables.isReleaseBuild, 'True')
inputs:
command: build
arguments: $(Build.SourcesDirectory)/src/ActiveMQ.WorkerBinding/ActiveMQ.WorkerBinding.csproj --configuration Release -property:Version=$(releaseVersion)
arguments: $(Build.SourcesDirectory)/src/ActiveMQ.WorkerBinding/ActiveMQ.WorkerBinding.csproj --configuration Release -property:Version=$(releaseVersion) -property:ContinuousIntegrationBuild=true

- task: DotNetCoreCLI@2
displayName: Pack Akc.Azure.WebJobs.Extensions.ActiveMQ Release
condition: eq(variables.isReleaseBuild, 'True')
condition: eq(variables['shouldPublish'], 'True')
inputs:
command: custom
custom: pack
arguments: $(Build.SourcesDirectory)/src/ActiveMQBinding/ActiveMQBinding.csproj --configuration Release --no-build -property:Version=$(releaseVersion) --output $(Build.ArtifactStagingDirectory)/dotnet/$(releaseVersion)

- task: DotNetCoreCLI@2
displayName: Pack Akc.Azure.Functions.Worker.Extensions.ActiveMQ Release
condition: eq(variables.isReleaseBuild, 'True')
condition: eq(variables['shouldPublish'], 'True')
inputs:
command: custom
custom: pack
arguments: $(Build.SourcesDirectory)/src/ActiveMQ.WorkerBinding/ActiveMQ.WorkerBinding.csproj --configuration Release --no-build -property:Version=$(releaseVersion) --output $(Build.ArtifactStagingDirectory)/dotnet/$(releaseVersion)

- task: PublishBuildArtifacts@1
displayName: Publish Extension
condition: eq(variables.isReleaseBuild, 'True')
condition: eq(variables['shouldPublish'], 'True')
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'

- task: NuGetCommand@2
displayName: 'NuGet push packages'
condition: eq(variables['shouldPublish'], 'True')
inputs:
command: push
nuGetFeedType: external
publishFeedCredentials: nuget.org
packagesToPush: '$(Build.ArtifactStagingDirectory)/dotnet/$(releaseVersion)/*.nupkg'

13 changes: 11 additions & 2 deletions src/ActiveMQ.WorkerBinding/ActiveMQ.WorkerBinding.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
<RepositoryUrl>https://github.com/arkiaconsulting/akc-azure-functions-worker-extensions-activemq</RepositoryUrl>
<PackageProjectUrl>https://github.com/arkiaconsulting/akc-azure-functions-worker-extensions-activemq</PackageProjectUrl>
<PackageTags>Azure WebJobs AzureFunctions ActiveMQ Isolated Akc</PackageTags>

<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl>https://aka.ms/azure-functions-package-icon</PackageIconUrl>

<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>

<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<PackageOutputPath>../.nupkg</PackageOutputPath>
</PropertyGroup>

<ItemGroup>
Expand All @@ -41,4 +44,10 @@
</AssemblyAttribute>
</ItemGroup>

<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
<None Include="icon.png" Pack="true" PackagePath="/">
<Visible>false</Visible>
</None>
</ItemGroup>
</Project>
Binary file added src/ActiveMQ.WorkerBinding/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion src/ActiveMQBinding/ActiveMQBinding.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
<RepositoryUrl>https://github.com/arkiaconsulting/akc-azure-functions-worker-extensions-activemq</RepositoryUrl>
<PackageProjectUrl>https://github.com/arkiaconsulting/akc-azure-functions-worker-extensions-activemq</PackageProjectUrl>
<PackageTags>Azure WebJobs AzureFunctions ActiveMQ Akc</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl>https://aka.ms/azure-functions-package-icon</PackageIconUrl>

<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>

<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
Expand All @@ -40,4 +42,11 @@
<PackageReference Include="System.Threading.Channels" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
<None Include=".\icon.png" Pack="true" PackagePath="/">
<Visible>false</Visible>
</None>
</ItemGroup>

</Project>
Binary file added src/ActiveMQBinding/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8b548aa

Please sign in to comment.