Skip to content

Commit

Permalink
Feature: Added Qualified and Custom reference name strategy approache…
Browse files Browse the repository at this point in the history
…s 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
  • Loading branch information
RobotechUSA authored Nov 14, 2024
1 parent c8aa462 commit 74da56d
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,5 +274,10 @@ public ReferenceSubjectNameStrategy? ReferenceSubjectNameStrategy
}
}

/// <summary>
/// Custom reference subject name strategy resolver.
/// Ensure <seealso cref="ReferenceSubjectNameStrategy.Custom"/> is set for this to take effect.
/// </summary>
public ICustomReferenceSubjectNameStrategy CustomReferenceSubjectNameStrategy { get; set; } = null;
}
}
95 changes: 90 additions & 5 deletions src/Confluent.SchemaRegistry/ReferenceSubjectNameStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// Refer to LICENSE for more information.

using Confluent.Kafka;
using System;


namespace Confluent.SchemaRegistry
Expand All @@ -38,11 +39,45 @@ namespace Confluent.SchemaRegistry
public enum ReferenceSubjectNameStrategy
{
/// <summary>
/// (default): Use the reference name as the subject name.
/// ReferenceName (default): Use the reference name as the subject name.
/// </summary>
ReferenceName
ReferenceName,
/// <summary>
/// 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.
/// </summary>
Qualified,
/// <summary>
/// Custom: Use a custom reference subject name strategy resolver to determine the subject name.
/// </summary>
Custom
}

/// <summary>
/// Custom Reference Subject Name Strategy Interface
/// </summary>
public interface ICustomReferenceSubjectNameStrategy
{
/// <summary>
/// Gets the subject name.
/// </summary>
/// <param name="context"></param>
/// <param name="referenceName"></param>
/// <returns></returns>
string GetSubjectName(SerializationContext context, string referenceName);
}

/// <summary>
/// Configuration property names specific to the schema registry client.
/// </summary>
public static partial class PropertyNames
{
/// <summary>
/// The subject name strategy to use for registration / lookup of referenced schemas
/// Possible values: <see cref="Confluent.SchemaRegistry.ReferenceSubjectNameStrategy" />
/// </summary>
public const string ReferenceSubjectNameStrategy = "protobuf.serializer.reference.subject.name.strategy";
}


/// <summary>
/// Extension methods for the ReferenceSubjectNameStrategy type.
Expand All @@ -52,7 +87,57 @@ public static class ReferenceSubjectNameStrategyExtensions
/// <summary>
/// Provide a functional implementation corresponding to the enum value.
/// </summary>
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}.");
}
}
};
}

/// <summary>
/// Get Subject Name
/// </summary>
/// <param name="context"></param>
/// <param name="referenceName"></param>
/// <returns></returns>
public static string GetQualifiedSubjectName(SerializationContext context, string referenceName)
{
return referenceName.Replace(".proto", string.Empty).Replace("/", ".");
}

/// <summary>
/// Get Subject Name
/// </summary>
/// <param name="context"></param>
/// <param name="referenceName"></param>
/// <returns></returns>
public static string GetReferenceNameSubjectName(SerializationContext context, string referenceName)
{
return referenceName;
}
}
}

0 comments on commit 74da56d

Please sign in to comment.