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

Compression and JustSaying 8.0 Changes #1525

Draft
wants to merge 42 commits into
base: main
Choose a base branch
from

Conversation

slang25
Copy link
Member

@slang25 slang25 commented Oct 3, 2024

There is still more to go, but I'm pushing this now to get some feedback.

This PR makes the following changes:

  • Adds message compression
  • Introduces a "Message Body Serializer/Deserializer" to keep the message format separate
  • Adds SNS raw delivery support
  • Fixes missing message attributes for subscribing messages that were directly sent to an SQS queue (i.e. without SNS wrapper)
  • Removes subscription reliance on Subject
  • Allows for publishing override for Subject
  • Removes serialization registry, serializers are flowed through the subscription.
  • Added LocalSqsSnsMessaging to make integration testing instantaneous.
  • Made more types internal

Outstanding actions:

  • Integration tests for subject override
  • Add subject override to all publishers
  • Integration tests for more scenarios
  • Re-introduce LocalStack as a flag for integration tests (have it still run on CI)
  • Revert samples app
  • Add missing XML doc comments
  • Add documentation

@slang25 slang25 requested a review from a team as a code owner October 3, 2024 10:43
@slang25 slang25 marked this pull request as draft October 3, 2024 10:43
var serializerFactory = p.GetRequiredService<IMessageSerializationFactory>();
return new MessageSerializationRegister(config.MessageSubjectProvider, serializerFactory);
});
services.TryAddSingleton((p) => new MessageCompressionRegistry([new GzipMessageBodyCompression()]));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we resolved all the compressions from DI and then just registered GZip as the only one?

})
.Singleton();

For<MessageCompressionRegistry>().Use((p) => new MessageCompressionRegistry(new List<IMessageBodyCompression> { new GzipMessageBodyCompression() })).Singleton();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

/// Gets or sets the compression encoding to be used.
/// </summary>
/// <remarks>
/// This should correspond to a registered compression algorithm in the IMessageCompressionRegistry.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This should correspond to a registered compression algorithm in the IMessageCompressionRegistry.
/// This should correspond to a registered compression algorithm in the <see cref="IMessageCompressionRegistry"/>.

@@ -8,21 +8,18 @@

namespace JustSaying.AwsTools.MessageHandling.Dispatch;

public class MessageDispatcher : IMessageDispatcher
internal class MessageDispatcher : IMessageDispatcher
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we seal it now if it's internal?

/// <summary>
/// Gets all available attribute keys.
/// </summary>
/// <returns>An IReadOnlyCollection of strings representing all attribute keys.</returns>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// <returns>An IReadOnlyCollection of strings representing all attribute keys.</returns>
/// <returns>An <see cref="IReadOnlyCollection{T}"/> of strings representing all attribute keys.</returns>

}

public IMessageSerializer GetSerializer<T>() where T : Message => _serializer;
public IMessageBodySerializer GetSerializer<T>() where T : Message => new NewtonsoftMessageBodySerializer<T>(settings);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want/need to create a new instance every time?

}
}

public sealed class PublishMessage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to own file.

Comment on lines 36 to 39
public string Serialize(Message message)
{
return JsonSerializer.Serialize(message, message.GetType(), _options);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this Serialize<T>(T message)? message.GetType() won't play friendly for native AoT if we add support for that in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can imagine we may not have generic type in all callers. For AoT we can create and store the JTI if available in the constructor (and throw if not available), and use in the serialize and deserialize methods.

Comment on lines 14 to 20
/// <summary>
/// Initializes a new instance of the <see cref="SystemTextJsonMessageBodySerializer{T}"/> class with default JSON serializer options.
/// </summary>
public SystemTextJsonMessageBodySerializer()
{
_options = DefaultJsonSerializerOptions;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to say we should drop this constructor in favour of exposing a default options that can be passed to the other constructor. In AoT this one will have to be an instant throw.

@@ -30,12 +30,12 @@ public ReceivedMessage ConvertForReceive(Amazon.SQS.Model.Message message)
var jsonNode = JsonNode.Parse(body);
if (jsonNode is JsonObject jsonObject && jsonObject.TryGetPropertyValue("Message", out var messageNode))
{
body = messageNode.ToString();
body = messageNode?.ToString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be ToJsonString()?

_queue = CreateSuccessfulTestQueue(Guid.NewGuid().ToString(),
new TestMessage
{
Body = $$"""{"Subject":"SimpleMessage", "Message": "{{JsonEncodedText.Encode("""{ "Content": "Hi" }""")}}"}"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL JsonEncodedText.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants