Skip to content

Commit

Permalink
feat!: Use same type for flag metadata and event metadata
Browse files Browse the repository at this point in the history
The spec describes two types(flag metadata, and event metadata) that are functionally the same. This PR
makes a breaking change to bring both of the types to use a generic ImmutableMetadata type.

- Rename BaseMetadata to Immutable, make sealed class and implement a empty constructor

Fixes: #234

Signed-off-by: Benjamin Evenson <[email protected]>
  • Loading branch information
benjiro committed Feb 24, 2024
1 parent cdc1bee commit ee77da9
Showing 7 changed files with 39 additions and 52 deletions.
4 changes: 2 additions & 2 deletions src/OpenFeature/Model/FlagEvaluationDetails.cs
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ public sealed class FlagEvaluationDetails<T>
/// <summary>
/// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number.
/// </summary>
public FlagMetadata FlagMetadata { get; }
public ImmutableMetadata FlagMetadata { get; }

/// <summary>
/// Initializes a new instance of the <see cref="FlagEvaluationDetails{T}"/> class.
@@ -61,7 +61,7 @@ public sealed class FlagEvaluationDetails<T>
/// <param name="errorMessage">Error message</param>
/// <param name="flagMetadata">Flag metadata</param>
public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, string reason, string variant,
string errorMessage = null, FlagMetadata flagMetadata = null)
string errorMessage = null, ImmutableMetadata flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
26 changes: 0 additions & 26 deletions src/OpenFeature/Model/FlagMetadata.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -5,13 +5,27 @@
namespace OpenFeature.Model;

/// <summary>
/// Represents the base class for metadata objects.
/// Represents the a immutable metadata associated with a feature flags and events.
/// </summary>
public abstract class BaseMetadata
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#flag-metadata"/>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#event-metadata"/>
public sealed class ImmutableMetadata
{
private readonly ImmutableDictionary<string, object> _metadata;

internal BaseMetadata(Dictionary<string, object> metadata)
/// <summary>
/// Constructor for the <see cref="ImmutableMetadata"/> class.
/// </summary>
public ImmutableMetadata()
{
this._metadata = ImmutableDictionary<string, object>.Empty;
}

/// <summary>
/// Constructor for the <see cref="ImmutableMetadata"/> class.
/// </summary>
/// <param name="metadata">The dictionary containing the metadata.</param>
public ImmutableMetadata(Dictionary<string, object> metadata)
{
this._metadata = metadata.ToImmutableDictionary();
}
@@ -21,7 +35,7 @@ internal BaseMetadata(Dictionary<string, object> metadata)
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The boolean value associated with the key, or null if the key is not found.</returns>
public virtual bool? GetBool(string key)
public bool? GetBool(string key)
{
return this.GetValue<bool>(key);
}
@@ -31,7 +45,7 @@ internal BaseMetadata(Dictionary<string, object> metadata)
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The integer value associated with the key, or null if the key is not found.</returns>
public virtual int? GetInt(string key)
public int? GetInt(string key)
{
return this.GetValue<int>(key);
}
@@ -41,7 +55,7 @@ internal BaseMetadata(Dictionary<string, object> metadata)
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The double value associated with the key, or null if the key is not found.</returns>
public virtual double? GetDouble(string key)
public double? GetDouble(string key)
{
return this.GetValue<double>(key);
}
@@ -51,7 +65,7 @@ internal BaseMetadata(Dictionary<string, object> metadata)
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <returns>The string value associated with the key, or null if the key is not found.</returns>
public virtual string? GetString(string key)
public string? GetString(string key)
{
var hasValue = this._metadata.TryGetValue(key, out var value);
if (!hasValue)
3 changes: 1 addition & 2 deletions src/OpenFeature/Model/ProviderEvents.cs
Original file line number Diff line number Diff line change
@@ -36,7 +36,6 @@ public class ProviderEventPayload
/// <summary>
/// Metadata information for the event.
/// </summary>
// TODO: This needs to be changed to a EventMetadata object
public Dictionary<string, object> EventMetadata { get; set; }
public ImmutableMetadata EventMetadata { get; set; }
}
}
4 changes: 2 additions & 2 deletions src/OpenFeature/Model/ResolutionDetails.cs
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ public sealed class ResolutionDetails<T>
/// <summary>
/// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number.
/// </summary>
public FlagMetadata FlagMetadata { get; }
public ImmutableMetadata FlagMetadata { get; }

/// <summary>
/// Initializes a new instance of the <see cref="ResolutionDetails{T}"/> class.
@@ -60,7 +60,7 @@ public sealed class ResolutionDetails<T>
/// <param name="errorMessage">Error message</param>
/// <param name="flagMetadata">Flag metadata</param>
public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorType.None, string reason = null,
string variant = null, string errorMessage = null, FlagMetadata flagMetadata = null)
string variant = null, string errorMessage = null, ImmutableMetadata flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
24 changes: 12 additions & 12 deletions test/OpenFeature.Tests/FlagMetadataTest.cs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ public class FlagMetadataTest
public void GetBool_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
var flagMetadata = new FlagMetadata();
var flagMetadata = new ImmutableMetadata();

// Act
var result = flagMetadata.GetBool("nonexistentKey");
@@ -36,7 +36,7 @@ public void GetBool_Should_Return_Value_If_Key_Found()
"boolKey", true
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetBool("boolKey");
@@ -57,7 +57,7 @@ public void GetBool_Should_Throw_Value_Is_Invalid()
"wrongKey", "11a"
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetBool("wrongKey");
@@ -72,7 +72,7 @@ public void GetBool_Should_Throw_Value_Is_Invalid()
public void GetInt_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
var flagMetadata = new FlagMetadata();
var flagMetadata = new ImmutableMetadata();

// Act
var result = flagMetadata.GetInt("nonexistentKey");
@@ -94,7 +94,7 @@ public void GetInt_Should_Return_Value_If_Key_Found()
"intKey", 1
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetInt("intKey");
@@ -116,7 +116,7 @@ public void GetInt_Should_Throw_Value_Is_Invalid()
"wrongKey", "11a"
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetInt("wrongKey");
@@ -131,7 +131,7 @@ public void GetInt_Should_Throw_Value_Is_Invalid()
public void GetDouble_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
var flagMetadata = new FlagMetadata();
var flagMetadata = new ImmutableMetadata();

// Act
var result = flagMetadata.GetDouble("nonexistentKey");
@@ -153,7 +153,7 @@ public void GetDouble_Should_Return_Value_If_Key_Found()
"doubleKey", 1.2
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetDouble("doubleKey");
@@ -175,7 +175,7 @@ public void GetDouble_Should_Throw_Value_Is_Invalid()
"wrongKey", "11a"
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetDouble("wrongKey");
@@ -190,7 +190,7 @@ public void GetDouble_Should_Throw_Value_Is_Invalid()
public void GetString_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
var flagMetadata = new FlagMetadata();
var flagMetadata = new ImmutableMetadata();

// Act
var result = flagMetadata.GetString("nonexistentKey");
@@ -212,7 +212,7 @@ public void GetString_Should_Return_Value_If_Key_Found()
"stringKey", "11"
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetString("stringKey");
@@ -234,7 +234,7 @@ public void GetString_Should_Throw_Value_Is_Invalid()
"wrongKey", new object()
}
};
var flagMetadata = new FlagMetadata(metadata);
var flagMetadata = new ImmutableMetadata(metadata);

// Act
var result = flagMetadata.GetString("wrongKey");
2 changes: 1 addition & 1 deletion test/OpenFeature.Tests/OpenFeatureEventTests.cs
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ public async Task Event_Executor_Should_Propagate_Events_ToGlobal_Handler()

eventExecutor.AddApiLevelHandler(ProviderEventTypes.ProviderConfigurationChanged, eventHandler);

var eventMetadata = new Dictionary<string, object> { { "foo", "bar" } };
var eventMetadata = new ImmutableMetadata(new Dictionary<string, object> { { "foo", "bar" } });
var myEvent = new Event
{
EventPayload = new ProviderEventPayload

0 comments on commit ee77da9

Please sign in to comment.