Skip to content

Commit

Permalink
feat!: Use same type for flag metadata and event metadata (open-featu…
Browse files Browse the repository at this point in the history
…re#241)

## This PR

**BREAKING CHANGE**, merge with 2.0

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 ImmutableMetadata, make sealed class and
implement a empty constructor

### Related Issues

Fixes: open-feature#234

---------

Signed-off-by: Benjamin Evenson <2031163+benjiro@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Artyom Tonoyan <artonoyan@servicetitan.com>
  • Loading branch information
2 people authored and arttonoyan committed Nov 17, 2024
1 parent 99aa754 commit f364e63
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 109 deletions.
56 changes: 28 additions & 28 deletions src/OpenFeature/Model/FlagEvaluationDetails.cs
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
using OpenFeature.Constant;

namespace OpenFeature.Model
{
{
/// <summary>
/// The contract returned to the caller that describes the result of the flag evaluation process.
/// </summary>
/// <typeparam name="T">Flag value type</typeparam>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#evaluation-details"/>
public sealed class FlagEvaluationDetails<T>
{
public sealed class FlagEvaluationDetails<T>
{
/// <summary>
/// Feature flag evaluated value
/// </summary>
public T Value { get; }

public T Value { get; }

/// <summary>
/// Feature flag key
/// </summary>
public string FlagKey { get; }

public string FlagKey { get; }

/// <summary>
/// Error that occurred during evaluation
/// </summary>
public ErrorType ErrorType { get; }

public ErrorType ErrorType { get; }

/// <summary>
/// Message containing additional details about an error.
/// <para>
/// Will be <see langword="null" /> if there is no error or if the provider didn't provide any additional error
/// details.
/// </para>
/// </summary>
public string? ErrorMessage { get; }

public string? ErrorMessage { get; }

/// <summary>
/// Describes the reason for the outcome of the evaluation process
/// </summary>
public string? Reason { get; }

public string? Reason { get; }

/// <summary>
/// A variant is a semantic identifier for a value. This allows for referral to particular values without
/// necessarily including the value itself, which may be quite prohibitively large or otherwise unsuitable
/// in some cases.
/// </summary>
public string? Variant { get; }

public string? Variant { get; }

/// <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.
/// </summary>
Expand All @@ -60,16 +60,16 @@ public sealed class FlagEvaluationDetails<T>
/// <param name="variant">Variant</param>
/// <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)
{
this.Value = value;
this.FlagKey = flagKey;
this.ErrorType = errorType;
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
this.FlagMetadata = flagMetadata;
}
public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, string? reason, string? variant,
string? errorMessage = null, ImmutableMetadata? flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
this.ErrorType = errorType;
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
this.FlagMetadata = flagMetadata;
}
}
}
25 changes: 0 additions & 25 deletions src/OpenFeature/Model/FlagMetadata.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
using System.Collections.Generic;
using System.Collections.Immutable;

#nullable enable
namespace OpenFeature.Model;

/// <summary>
/// Represents the base class for metadata objects.
/// Represents immutable metadata associated with 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();
}
Expand All @@ -20,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);
}
Expand All @@ -30,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);
}
Expand All @@ -40,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);
}
Expand All @@ -50,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)
Expand Down
3 changes: 1 addition & 2 deletions src/OpenFeature/Model/ProviderEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
}
56 changes: 28 additions & 28 deletions src/OpenFeature/Model/ResolutionDetails.cs
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
using OpenFeature.Constant;

namespace OpenFeature.Model
{
{
/// <summary>
/// Defines the contract that the <see cref="FeatureProvider"/> is required to return
/// Describes the details of the feature flag being evaluated
/// </summary>
/// <typeparam name="T">Flag value type</typeparam>
/// <seealso href="https://github.com/open-feature/spec/blob/v0.7.0/specification/types.md#resolution-details"/>
public sealed class ResolutionDetails<T>
{
public sealed class ResolutionDetails<T>
{
/// <summary>
/// Feature flag evaluated value
/// </summary>
public T Value { get; }

public T Value { get; }

/// <summary>
/// Feature flag key
/// </summary>
public string FlagKey { get; }

public string FlagKey { get; }

/// <summary>
/// Error that occurred during evaluation
/// <see cref="ErrorType"/>
/// </summary>
public ErrorType ErrorType { get; }

public ErrorType ErrorType { get; }

/// <summary>
/// Message containing additional details about an error.
/// </summary>
public string? ErrorMessage { get; }

public string? ErrorMessage { get; }

/// <summary>
/// Describes the reason for the outcome of the evaluation process
/// <see cref="Reason"/>
/// </summary>
public string? Reason { get; }

public string? Reason { get; }

/// <summary>
/// A variant is a semantic identifier for a value. This allows for referral to particular values without
/// necessarily including the value itself, which may be quite prohibitively large or otherwise unsuitable
/// in some cases.
/// </summary>
public string? Variant { get; }

public string? Variant { get; }

/// <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.
/// </summary>
Expand All @@ -59,16 +59,16 @@ public sealed class ResolutionDetails<T>
/// <param name="variant">Variant</param>
/// <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)
{
this.Value = value;
this.FlagKey = flagKey;
this.ErrorType = errorType;
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
this.FlagMetadata = flagMetadata;
}
public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorType.None, string? reason = null,
string? variant = null, string? errorMessage = null, ImmutableMetadata? flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
this.ErrorType = errorType;
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
this.FlagMetadata = flagMetadata;
}
}
}
Loading

0 comments on commit f364e63

Please sign in to comment.