Skip to content

Commit 7d5ad3f

Browse files
Merge branch 'main' into dev/rubencerna/Add_LogLevel_Filters
2 parents 80dd132 + 97c25db commit 7d5ad3f

35 files changed

+1584
-230
lines changed

schemas/dab.draft.schema.json

Lines changed: 101 additions & 125 deletions
Large diffs are not rendered by default.

src/Cli.Tests/ModuleInitializer.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public static void Init()
1919
{
2020
// Ignore the connection string from the output to avoid committing it.
2121
VerifierSettings.IgnoreMember<DataSource>(dataSource => dataSource.ConnectionString);
22+
// Ignore the IsDatasourceHealthEnabled from the output to avoid committing it.
23+
VerifierSettings.IgnoreMember<DataSource>(dataSource => dataSource.IsDatasourceHealthEnabled);
24+
// Ignore the DatasourceThresholdMs from the output to avoid committing it.
25+
VerifierSettings.IgnoreMember<DataSource>(dataSource => dataSource.DatasourceThresholdMs);
2226
// Ignore the datasource files as that's unimportant from a test standpoint.
2327
VerifierSettings.IgnoreMember<RuntimeConfig>(config => config.DataSourceFiles);
2428
// Ignore the CosmosDataSourceUsed as that's unimportant from a test standpoint.
@@ -31,6 +35,28 @@ public static void Init()
3135
VerifierSettings.IgnoreMember<RuntimeOptions>(options => options.IsCachingEnabled);
3236
// Ignore the entity IsCachingEnabled as that's unimportant from a test standpoint.
3337
VerifierSettings.IgnoreMember<Entity>(entity => entity.IsCachingEnabled);
38+
// Ignore the global IsRestEnabled as that's unimportant from a test standpoint.
39+
VerifierSettings.IgnoreMember<RuntimeConfig>(config => config.IsRestEnabled);
40+
// Ignore the global RuntimeOptions.IsRestEnabled as that's unimportant from a test standpoint.
41+
VerifierSettings.IgnoreMember<RuntimeOptions>(options => options.IsRestEnabled);
42+
// Ignore the entity IsRestEnabled as that's unimportant from a test standpoint.
43+
VerifierSettings.IgnoreMember<Entity>(entity => entity.IsRestEnabled);
44+
// Ignore the global IsGraphQLEnabled as that's unimportant from a test standpoint.
45+
VerifierSettings.IgnoreMember<RuntimeConfig>(config => config.IsGraphQLEnabled);
46+
// Ignore the global RuntimeOptions.IsGraphQLEnabled as that's unimportant from a test standpoint.
47+
VerifierSettings.IgnoreMember<RuntimeOptions>(options => options.IsGraphQLEnabled);
48+
// Ignore the entity IsGraphQLEnabled as that's unimportant from a test standpoint.
49+
VerifierSettings.IgnoreMember<Entity>(entity => entity.IsGraphQLEnabled);
50+
// Ignore the global IsHealthEnabled as that's unimportant from a test standpoint.
51+
VerifierSettings.IgnoreMember<RuntimeConfig>(config => config.IsHealthEnabled);
52+
// Ignore the global RuntimeOptions.IsHealthCheckEnabled as that's unimportant from a test standpoint.
53+
VerifierSettings.IgnoreMember<RuntimeOptions>(options => options.IsHealthCheckEnabled);
54+
// Ignore the entity IsEntityHealthEnabled as that's unimportant from a test standpoint.
55+
VerifierSettings.IgnoreMember<Entity>(entity => entity.IsEntityHealthEnabled);
56+
// Ignore the entity EntityThresholdMs as that's unimportant from a test standpoint.
57+
VerifierSettings.IgnoreMember<Entity>(entity => entity.EntityThresholdMs);
58+
// Ignore the entity EntityFirst as that's unimportant from a test standpoint.
59+
VerifierSettings.IgnoreMember<Entity>(entity => entity.EntityFirst);
3460
// Ignore the entity IsLinkingEntity as that's unimportant from a test standpoint.
3561
VerifierSettings.IgnoreMember<Entity>(entity => entity.IsLinkingEntity);
3662
// Ignore the UserProvidedTtlOptions. They aren't serialized to our config file, enforced by EntityCacheOptionsConverter.

src/Cli/ConfigGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ private static bool TryUpdateConfiguredDataSourceOptions(
569569
{
570570
DatabaseType dbType = runtimeConfig.DataSource.DatabaseType;
571571
string dataSourceConnectionString = runtimeConfig.DataSource.ConnectionString;
572+
DatasourceHealthCheckConfig? datasourceHealthCheckConfig = runtimeConfig.DataSource.Health;
572573

573574
if (options.DataSourceDatabaseType is not null)
574575
{
@@ -611,7 +612,7 @@ private static bool TryUpdateConfiguredDataSourceOptions(
611612
}
612613

613614
dbOptions = EnumerableUtilities.IsNullOrEmpty(dbOptions) ? null : dbOptions;
614-
DataSource dataSource = new(dbType, dataSourceConnectionString, dbOptions);
615+
DataSource dataSource = new(dbType, dataSourceConnectionString, dbOptions, datasourceHealthCheckConfig);
615616
runtimeConfig = runtimeConfig with { DataSource = dataSource };
616617

617618
return runtimeConfig != null;

src/Config/Converters/DataSourceConverterFactory.cs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,55 @@ public DataSourceConverter(bool replaceEnvVar)
4747

4848
public override DataSource? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
4949
{
50-
DataSource dataSource = new(DatabaseType.MSSQL, string.Empty, null);
5150
if (reader.TokenType is JsonTokenType.StartObject)
5251
{
52+
DatabaseType databaseType = DatabaseType.MSSQL;
53+
string connectionString = string.Empty;
54+
DatasourceHealthCheckConfig? health = null;
55+
Dictionary<string, object?>? datasourceOptions = null;
5356

54-
while (reader.Read() && reader.TokenType is not JsonTokenType.EndObject)
57+
while (reader.Read())
5558
{
59+
if (reader.TokenType is JsonTokenType.EndObject)
60+
{
61+
return new DataSource(databaseType, connectionString, datasourceOptions, health);
62+
}
63+
5664
if (reader.TokenType is JsonTokenType.PropertyName)
5765
{
5866
string propertyName = reader.GetString() ?? string.Empty;
5967
reader.Read();
68+
6069
switch (propertyName)
6170
{
6271
case "database-type":
63-
dataSource = dataSource with { DatabaseType = EnumExtensions.Deserialize<DatabaseType>(reader.DeserializeString(_replaceEnvVar)!) };
72+
databaseType = EnumExtensions.Deserialize<DatabaseType>(reader.DeserializeString(_replaceEnvVar)!);
6473
break;
74+
6575
case "connection-string":
66-
dataSource = dataSource with { ConnectionString = reader.DeserializeString(replaceEnvVar: _replaceEnvVar)! };
76+
connectionString = reader.DeserializeString(replaceEnvVar: _replaceEnvVar)!;
6777
break;
68-
case "options":
78+
79+
case "health":
6980
if (reader.TokenType == JsonTokenType.Null)
7081
{
71-
dataSource = dataSource with { Options = null };
72-
break;
82+
health = new();
7383
}
7484
else
85+
{
86+
try
87+
{
88+
health = JsonSerializer.Deserialize<DatasourceHealthCheckConfig>(ref reader, options);
89+
}
90+
catch (Exception e)
91+
{
92+
throw new JsonException($"Error while deserializing DataSource health: {e.Message}");
93+
}
94+
}
95+
96+
break;
97+
case "options":
98+
if (reader.TokenType is not JsonTokenType.Null)
7599
{
76100
Dictionary<string, object?> optionsDict = new();
77101
while (reader.Read() && reader.TokenType is not JsonTokenType.EndObject)
@@ -111,18 +135,18 @@ public DataSourceConverter(bool replaceEnvVar)
111135
optionsDict.Add(optionsSubproperty, optionsSubpropertyValue);
112136
}
113137

114-
dataSource = dataSource with { Options = optionsDict };
115-
break;
138+
datasourceOptions = optionsDict;
116139
}
140+
141+
break;
117142
default:
118143
throw new JsonException($"Unexpected property {propertyName} while deserializing DataSource.");
119144
}
120145
}
121146
}
122-
123147
}
124148

125-
return dataSource;
149+
throw new JsonException("data-source property has a missing }.");
126150
}
127151

128152
public override void Write(Utf8JsonWriter writer, DataSource value, JsonSerializerOptions options)
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System.Text.Json;
5+
using System.Text.Json.Serialization;
6+
using Azure.DataApiBuilder.Config.ObjectModel;
7+
8+
namespace Azure.DataApiBuilder.Config.Converters;
9+
10+
internal class DataSourceHealthOptionsConvertorFactory : JsonConverterFactory
11+
{
12+
// Determines whether to replace environment variable with its
13+
// value or not while deserializing.
14+
private bool _replaceEnvVar;
15+
16+
/// <inheritdoc/>
17+
public override bool CanConvert(Type typeToConvert)
18+
{
19+
return typeToConvert.IsAssignableTo(typeof(DatasourceHealthCheckConfig));
20+
}
21+
22+
/// <inheritdoc/>
23+
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
24+
{
25+
return new HealthCheckOptionsConverter(_replaceEnvVar);
26+
}
27+
28+
/// <param name="replaceEnvVar">Whether to replace environment variable with its
29+
/// value or not while deserializing.</param>
30+
internal DataSourceHealthOptionsConvertorFactory(bool replaceEnvVar)
31+
{
32+
_replaceEnvVar = replaceEnvVar;
33+
}
34+
35+
private class HealthCheckOptionsConverter : JsonConverter<DatasourceHealthCheckConfig>
36+
{
37+
// Determines whether to replace environment variable with its
38+
// value or not while deserializing.
39+
private bool _replaceEnvVar;
40+
41+
/// <param name="replaceEnvVar">Whether to replace environment variable with its
42+
/// value or not while deserializing.</param>
43+
public HealthCheckOptionsConverter(bool replaceEnvVar)
44+
{
45+
_replaceEnvVar = replaceEnvVar;
46+
}
47+
48+
/// <summary>
49+
/// Defines how DAB reads the data-source's health options and defines which values are
50+
/// used to instantiate DatasourceHealthCheckConfig.
51+
/// </summary>
52+
/// <exception cref="JsonException">Thrown when improperly formatted health check options are provided.</exception>
53+
public override DatasourceHealthCheckConfig? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
54+
{
55+
if (reader.TokenType is JsonTokenType.Null)
56+
{
57+
return new DatasourceHealthCheckConfig();
58+
}
59+
60+
if (reader.TokenType is JsonTokenType.StartObject)
61+
{
62+
bool? enabled = null;
63+
string? name = null;
64+
int? threshold_ms = null;
65+
66+
while (reader.Read())
67+
{
68+
if (reader.TokenType is JsonTokenType.EndObject)
69+
{
70+
return new DatasourceHealthCheckConfig(enabled, name, threshold_ms);
71+
}
72+
73+
string? property = reader.GetString();
74+
reader.Read();
75+
76+
switch (property)
77+
{
78+
case "enabled":
79+
if (reader.TokenType is not JsonTokenType.Null)
80+
{
81+
enabled = reader.GetBoolean();
82+
}
83+
84+
break;
85+
case "name":
86+
if (reader.TokenType is not JsonTokenType.Null)
87+
{
88+
name = reader.DeserializeString(_replaceEnvVar);
89+
}
90+
91+
break;
92+
case "threshold-ms":
93+
if (reader.TokenType is not JsonTokenType.Null)
94+
{
95+
int parseThresholdMs = reader.GetInt32();
96+
if (parseThresholdMs <= 0)
97+
{
98+
throw new JsonException($"Invalid value for ttl-seconds: {parseThresholdMs}. Value must be greater than 0.");
99+
}
100+
101+
threshold_ms = parseThresholdMs;
102+
}
103+
104+
break;
105+
106+
default:
107+
throw new JsonException($"Unexpected property {property}");
108+
}
109+
}
110+
}
111+
112+
throw new JsonException("Datasource Health Options has a missing }.");
113+
}
114+
115+
public override void Write(Utf8JsonWriter writer, DatasourceHealthCheckConfig value, JsonSerializerOptions options)
116+
{
117+
if (value?.UserProvidedEnabled is true)
118+
{
119+
writer.WriteStartObject();
120+
writer.WritePropertyName("enabled");
121+
JsonSerializer.Serialize(writer, value.Enabled, options);
122+
if (value?.Name is not null)
123+
{
124+
writer.WritePropertyName("name");
125+
JsonSerializer.Serialize(writer, value.Name, options);
126+
}
127+
128+
if (value?.UserProvidedThresholdMs is true)
129+
{
130+
writer.WritePropertyName("threshold-ms");
131+
JsonSerializer.Serialize(writer, value.ThresholdMs, options);
132+
}
133+
134+
writer.WriteEndObject();
135+
}
136+
}
137+
}
138+
}

src/Config/Converters/EntityCacheOptionsConverterFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ private class EntityCacheOptionsConverter : JsonConverter<EntityCacheOptions>
9090
/// <summary>
9191
/// When writing the EntityCacheOptions back to a JSON file, only write the ttl-seconds
9292
/// property and value when EntityCacheOptions.Enabled is true. This avoids polluting
93-
/// the written JSON file with a property the user most likely ommitted when writing the
93+
/// the written JSON file with a property the user most likely omitted when writing the
9494
/// original DAB runtime config file.
9595
/// This Write operation is only used when a RuntimeConfig object is serialized to JSON.
9696
/// </summary>

0 commit comments

Comments
 (0)