Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a new major version of the MQTT package, to adopt MQTTnet v4.x #295

Merged
merged 2 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,28 @@ acts as encouragement to use the latest version of the core package.

Within this repository, this is achieved by the following mechanisms:

- Individual csproj files do not specify a version
- Most individual csproj files do not specify a version
- The [Directory.Build.props](src/Directory.Build.props) file has a `<Version>` element
specifying the version of all packages
specifying the version of all packages which don't need a separate
major version

A single GitHub release (and tag) will be created for each beta release, to cover all packages.
A single GitHub release (and tag) will be created for each release,
to cover all packages.

- Example tag name: "CloudNative.CloudEvents.All-2.0.0"
- Example release title: "All packages version 2.0.0"

### Exception: packages with different major versions

For some "satellite" packages, we need a different major version
number, typically to adopt a new major version of a dependency. In
this case, the satellite package will have its own major version,
but keep the minor and patch version of everything else.

For example, in order to take a new major version of the `MQTTnet`
dependency, `CloudNative.CloudEvents.Mqtt` 3.8.0 was released with
version 2.8.0 of all other packages.

## New / unstable package versioning

New packages are introduced with alpha and beta versions as would
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
<Description>MQTT extensions for CloudNative.CloudEvents</Description>
<PackageTags>cncf;cloudnative;cloudevents;events;mqtt</PackageTags>
<LangVersion>8.0</LangVersion>
<Version>3.$(MinorVersion).$(PatchVersion)</Version>
<!-- After the first release of v3, we'll change the major here to 3. -->
<PackageValidationBaselineVersion>2.$(PackageValidationMinor).0</PackageValidationBaselineVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MQTTnet" Version="3.0.15" />
<PackageReference Include="MQTTnet" Version="4.3.6.1152" />
<ProjectReference Include="..\CloudNative.CloudEvents\CloudNative.CloudEvents.csproj" />
</ItemGroup>

Expand Down
10 changes: 5 additions & 5 deletions src/CloudNative.CloudEvents.Mqtt/MqttExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Cloud Native Foundation.
// Copyright (c) Cloud Native Foundation.
// Licensed under the Apache 2.0 license.
// See LICENSE file in the project root for full license information.

Expand Down Expand Up @@ -39,10 +39,10 @@ public static CloudEvent ToCloudEvent(this MqttApplicationMessage message,
Validation.CheckNotNull(message, nameof(message));

// TODO: Determine if there's a sensible content type we should apply.
return formatter.DecodeStructuredModeMessage(message.Payload, contentType: null, extensionAttributes);
return formatter.DecodeStructuredModeMessage(message.PayloadSegment, contentType: null, extensionAttributes);
}

// TODO: Update to a newer version of MQTTNet and support both binary and structured mode?
// TODO: Support both binary and structured mode.
/// <summary>
/// Converts a CloudEvent to <see cref="MqttApplicationMessage"/>.
/// </summary>
Expand All @@ -61,11 +61,11 @@ public static MqttApplicationMessage ToMqttApplicationMessage(this CloudEvent cl
return new MqttApplicationMessage
{
Topic = topic,
Payload = BinaryDataUtilities.AsArray(formatter.EncodeStructuredModeMessage(cloudEvent, out _))
PayloadSegment = BinaryDataUtilities.GetArraySegment(formatter.EncodeStructuredModeMessage(cloudEvent, out _))
};
default:
throw new ArgumentOutOfRangeException(nameof(contentMode), $"Unsupported content mode: {contentMode}");
}
}
}
}
}
11 changes: 10 additions & 1 deletion src/CloudNative.CloudEvents/Core/BinaryDataUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,16 @@ public static byte[] AsArray(ReadOnlyMemory<byte> memory)
}

// Note: when this returns, the Array property of the returned segment is guaranteed not to be null.
private static ArraySegment<byte> GetArraySegment(ReadOnlyMemory<byte> memory) =>

/// <summary>
/// Returns the data from <paramref name="memory"/> as a byte array, return the underlying array
/// if there is one, or creating a copy otherwise. This method should be used with care, due to the
/// "sometimes shared, sometimes not" nature of the result. (It is generally safe to use this with the result
/// of encoding a CloudEvent, assuming the same memory is not used elsewhere.)
/// </summary>
/// <param name="memory">The memory to obtain the data from.</param>
/// <returns>The data in <paramref name="memory"/> as an array segment.</returns>
public static ArraySegment<byte> GetArraySegment(ReadOnlyMemory<byte> memory) =>
MemoryMarshal.TryGetArray(memory, out var segment) && segment.Array is not null
? segment
: new ArraySegment<byte>(memory.ToArray());
Expand Down
19 changes: 15 additions & 4 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
<Project>
<PropertyGroup>
<!--
- We use the same version number for all stable
- packages. See RELEASING.md for details.
- We use the same minor/patch version number for all stable
- packages, and the same major for most packages.
- See RELEASING.md for details.
-->
<Version>2.7.1</Version>
<PackageValidationBaselineVersion>2.7.0</PackageValidationBaselineVersion>
<MajorVersion>2</MajorVersion>
<MinorVersion>7</MinorVersion>
<PatchVersion>1</PatchVersion>
<PackageValidationMinor>7</PackageValidationMinor>
<Version>$(MajorVersion).$(MinorVersion).$(PatchVersion)</Version>
<!--
- The version used for detecting breaking changes.
- This is always older than the current version (except when creating a new major)
- and is the patch-0 of either the current minor (if the current patch is non-zero)
- or the previous minor (if the current patch is zero).
-->
<PackageValidationBaselineVersion>2.$(PackageValidationMinor).0</PackageValidationBaselineVersion>

<!-- Make the repository root available for other properties -->
<RepoRoot>$([System.IO.Path]::GetDirectoryName($([MSBuild]::GetPathOfFileAbove('.gitignore', '$(MSBuildThisFileDirectory)'))))</RepoRoot>
Expand Down
22 changes: 12 additions & 10 deletions test/CloudNative.CloudEvents.UnitTests/Mqtt/MqttTest.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Copyright (c) Cloud Native Foundation.
// Copyright (c) Cloud Native Foundation.
// Licensed under the Apache 2.0 license.
// See LICENSE file in the project root for full license information.

using CloudNative.CloudEvents.NewtonsoftJson;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Client.Receiving;
using MQTTnet.Server;
using System;
using System.Net.Mime;
Expand All @@ -18,16 +16,17 @@ namespace CloudNative.CloudEvents.Mqtt.UnitTests
{
public class MqttTest : IDisposable
{
private readonly IMqttServer mqttServer;
private readonly MqttServer mqttServer;

public MqttTest()
{
var optionsBuilder = new MqttServerOptionsBuilder()
.WithConnectionBacklog(100)
.WithDefaultEndpoint()
.WithDefaultEndpointPort(52355);

this.mqttServer = new MqttFactory().CreateMqttServer();
mqttServer.StartAsync(optionsBuilder.Build()).GetAwaiter().GetResult();
this.mqttServer = new MqttFactory().CreateMqttServer(optionsBuilder.Build());
mqttServer.StartAsync().GetAwaiter().GetResult();
}

public void Dispose()
Expand Down Expand Up @@ -55,14 +54,17 @@ public async Task MqttSendTest()

var options = new MqttClientOptionsBuilder()
.WithClientId("Client1")
.WithTcpServer("localhost", 52355)
.WithTcpServer("127.0.0.1", 52355)
.WithCleanSession()
.Build();

TaskCompletionSource<CloudEvent> tcs = new TaskCompletionSource<CloudEvent>();
await client.ConnectAsync(options);
client.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(
args => tcs.SetResult(args.ApplicationMessage.ToCloudEvent(jsonEventFormatter)));
client.ApplicationMessageReceivedAsync += args =>
{
tcs.SetResult(args.ApplicationMessage.ToCloudEvent(jsonEventFormatter));
return Task.CompletedTask;
};

var result = await client.SubscribeAsync("abc");
await client.PublishAsync(cloudEvent.ToMqttApplicationMessage(ContentMode.Structured, new JsonEventFormatter(), topic: "abc"));
Expand All @@ -79,4 +81,4 @@ public async Task MqttSendTest()
Assert.Equal("value", (string?) receivedCloudEvent["comexampleextension1"]);
}
}
}
}
Loading