From 74da56d2b2e484b0f1559b849b7a4f4503bfc518 Mon Sep 17 00:00:00 2001
From: Robert Schie <54124441+RobotechUSA@users.noreply.github.com>
Date: Wed, 13 Nov 2024 20:52:58 -0800
Subject: [PATCH] Feature: Added Qualified and Custom reference name strategy
approaches for protobuf references (Schema Registry) (#2345)
* Added QualifiedReferenceSubjectNameStrategy implementation to have feature parity with java version.
Added ability to use any custom ReferenceSubjectNameStrategy by implementing ICustomReferenceSubjectNameStrategy and assigning implemented instance to ProtobufSerializerConfig property CustomReferenceSubjectNameStrategy (Note: ReferenceSubjectNameStrategy enumeration value must be set to Custom)
Code for ProtobufSerializer was reformatted
* Empty-Commit
---
.../ProtobufSerializer.cs | 2 +-
.../ProtobufSerializerConfig.cs | 5 +
.../ReferenceSubjectNameStrategy.cs | 95 ++++++++++++++++++-
3 files changed, 96 insertions(+), 6 deletions(-)
diff --git a/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializer.cs b/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializer.cs
index ab0314349..898ec21da 100644
--- a/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializer.cs
+++ b/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializer.cs
@@ -96,7 +96,7 @@ public ProtobufSerializer(ISchemaRegistryClient schemaRegistryClient, ProtobufSe
if (config.SubjectNameStrategy != null) { this.subjectNameStrategy = config.SubjectNameStrategy.Value.ToDelegate(); }
this.referenceSubjectNameStrategy = config.ReferenceSubjectNameStrategy == null
? ReferenceSubjectNameStrategy.ReferenceName.ToDelegate()
- : config.ReferenceSubjectNameStrategy.Value.ToDelegate();
+ : config.ReferenceSubjectNameStrategy.Value.ToDelegate(config.CustomReferenceSubjectNameStrategy);
if (this.useLatestVersion && this.autoRegisterSchema)
{
diff --git a/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializerConfig.cs b/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializerConfig.cs
index 97770451e..b40a0d9ca 100644
--- a/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializerConfig.cs
+++ b/src/Confluent.SchemaRegistry.Serdes.Protobuf/ProtobufSerializerConfig.cs
@@ -274,5 +274,10 @@ public ReferenceSubjectNameStrategy? ReferenceSubjectNameStrategy
}
}
+ ///
+ /// Custom reference subject name strategy resolver.
+ /// Ensure is set for this to take effect.
+ ///
+ public ICustomReferenceSubjectNameStrategy CustomReferenceSubjectNameStrategy { get; set; } = null;
}
}
diff --git a/src/Confluent.SchemaRegistry/ReferenceSubjectNameStrategy.cs b/src/Confluent.SchemaRegistry/ReferenceSubjectNameStrategy.cs
index 492f1c11d..17d80a9a8 100644
--- a/src/Confluent.SchemaRegistry/ReferenceSubjectNameStrategy.cs
+++ b/src/Confluent.SchemaRegistry/ReferenceSubjectNameStrategy.cs
@@ -15,6 +15,7 @@
// Refer to LICENSE for more information.
using Confluent.Kafka;
+using System;
namespace Confluent.SchemaRegistry
@@ -38,11 +39,45 @@ namespace Confluent.SchemaRegistry
public enum ReferenceSubjectNameStrategy
{
///
- /// (default): Use the reference name as the subject name.
+ /// ReferenceName (default): Use the reference name as the subject name.
///
- ReferenceName
+ ReferenceName,
+ ///
+ /// Qualified: Given a reference name, replace slashes with dots, and remove the .proto suffix to obtain the subject name.
+ /// For example, mypackage/myfile.proto becomes mypackage.myfile.
+ ///
+ Qualified,
+ ///
+ /// Custom: Use a custom reference subject name strategy resolver to determine the subject name.
+ ///
+ Custom
+ }
+
+ ///
+ /// Custom Reference Subject Name Strategy Interface
+ ///
+ public interface ICustomReferenceSubjectNameStrategy
+ {
+ ///
+ /// Gets the subject name.
+ ///
+ ///
+ ///
+ ///
+ string GetSubjectName(SerializationContext context, string referenceName);
+ }
+
+ ///
+ /// Configuration property names specific to the schema registry client.
+ ///
+ public static partial class PropertyNames
+ {
+ ///
+ /// The subject name strategy to use for registration / lookup of referenced schemas
+ /// Possible values:
+ ///
+ public const string ReferenceSubjectNameStrategy = "protobuf.serializer.reference.subject.name.strategy";
}
-
///
/// Extension methods for the ReferenceSubjectNameStrategy type.
@@ -52,7 +87,57 @@ public static class ReferenceSubjectNameStrategyExtensions
///
/// Provide a functional implementation corresponding to the enum value.
///
- public static ReferenceSubjectNameStrategyDelegate ToDelegate(this ReferenceSubjectNameStrategy strategy)
- => (context, referenceName) => referenceName;
+ public static ReferenceSubjectNameStrategyDelegate ToDelegate(this ReferenceSubjectNameStrategy strategy, ICustomReferenceSubjectNameStrategy customReferenceSubjectNameStrategy = null)
+ {
+ return (context, referenceName) =>
+ {
+ switch (strategy)
+ {
+ case ReferenceSubjectNameStrategy.ReferenceName:
+ {
+ return GetReferenceNameSubjectName(context, referenceName);
+ }
+ case ReferenceSubjectNameStrategy.Qualified:
+ {
+ return GetQualifiedSubjectName(context, referenceName);
+ }
+ case ReferenceSubjectNameStrategy.Custom:
+ {
+ if (customReferenceSubjectNameStrategy == null)
+ {
+ throw new ArgumentException($"Custom strategy requires a custom {nameof(ICustomReferenceSubjectNameStrategy)} implementation to be specified.");
+ }
+
+ return customReferenceSubjectNameStrategy.GetSubjectName(context, referenceName);
+ }
+ default:
+ {
+ throw new ArgumentException($"Unknown ${PropertyNames.ReferenceSubjectNameStrategy} value: {strategy}.");
+ }
+ }
+ };
+ }
+
+ ///
+ /// Get Subject Name
+ ///
+ ///
+ ///
+ ///
+ public static string GetQualifiedSubjectName(SerializationContext context, string referenceName)
+ {
+ return referenceName.Replace(".proto", string.Empty).Replace("/", ".");
+ }
+
+ ///
+ /// Get Subject Name
+ ///
+ ///
+ ///
+ ///
+ public static string GetReferenceNameSubjectName(SerializationContext context, string referenceName)
+ {
+ return referenceName;
+ }
}
}