in src/Core/Generator/SchemaGeneratorFactory.cs [39:136]
public static async Task<string> Create(RuntimeConfig config, string mode, int? sampleCount, string? partitionKeyPath, int? days, int? groupCount, ILogger logger, Container? container = null)
{
// Validate the configuration parameters.
if ((days.HasValue && days < 1) || (groupCount.HasValue && groupCount < 1) || (sampleCount.HasValue && sampleCount < 1))
{
logger.LogError("Invalid Configuration Found");
throw new ArgumentException("Invalid Configuration Found");
}
if (config.DataSource == null)
{
logger.LogError("Runtime Config file doesn't have Data Source configured");
throw new ArgumentException("DataSource not found");
}
if (config.DataSource.DatabaseType != DatabaseType.CosmosDB_NoSQL)
{
logger.LogError("Config file passed is not compatible with this feature. Please make sure datasource type is configured as {0}", DatabaseType.CosmosDB_NoSQL);
throw new ArgumentException($"Config file passed is not compatible with this feature. Please make sure datasource type is configured as {DatabaseType.CosmosDB_NoSQL}");
}
string? connectionString = config.DataSource?.ConnectionString;
object? globalDatabaseName = null;
object? globalContainerName = null;
config.DataSource?.Options?.TryGetValue("database", out globalDatabaseName);
config.DataSource?.Options?.TryGetValue("container", out globalContainerName);
if (string.IsNullOrEmpty(connectionString) || globalDatabaseName is null)
{
logger.LogError("Connection String and Database name must be provided in the config file");
throw new ArgumentException("Connection String and Database name must be provided in the config file");
}
HashSet<string> dbAndContainerToProcess = new();
if (globalDatabaseName != null && globalContainerName != null)
{
dbAndContainerToProcess.Add($"{globalDatabaseName}.{globalContainerName}");
}
foreach (KeyValuePair<string, Entity> entity in config.Entities)
{
string entitySourceObject = entity.Value.Source.Object;
string[]? databaseContainerInfo = entitySourceObject?.Split('.');
string result = databaseContainerInfo switch
{
null or { Length: 0 } when globalDatabaseName != null && globalContainerName != null => $"{globalDatabaseName}.{globalContainerName}",
{ Length: 2 } => entity.Value.Source.Object,
{ Length: 1 } when globalDatabaseName != null => $"{globalDatabaseName}.{entity.Value.Source.Object}",
_ => throw new InvalidOperationException("Unexpected Source format")
};
dbAndContainerToProcess.Add(result);
}
StringBuilder schema = new();
foreach (string dbAndContainer in dbAndContainerToProcess)
{
if (string.IsNullOrEmpty(dbAndContainer)) // Safety check
{
continue;
}
string[] dbContainer = dbAndContainer.Split('.');
logger.LogInformation("Connecting to Cosmos DB Database: {0}, Container: {1}", dbContainer[0], dbContainer[1]);
// Connect to the Azure Cosmos DB container.
container ??= ConnectToCosmosDB(connectionString, dbContainer[0], dbContainer[1]);
SamplingModes samplingMode = (SamplingModes)Enum.Parse(typeof(SamplingModes), mode);
// Determine the appropriate sampler based on the sampling mode.
ISchemaGeneratorSampler schemaGeneratorSampler = samplingMode switch
{
SamplingModes.TopNExtractor => new TopNExtractor(container, sampleCount, days, logger),
SamplingModes.EligibleDataSampler => new EligibleDataSampler(container, partitionKeyPath, sampleCount, days, logger),
SamplingModes.TimePartitionedSampler => new TimePartitionedSampler(container, groupCount, sampleCount, days, logger),
_ => throw new ArgumentException($"Invalid sampling mode: {mode}, Valid Sampling Modes are: {SamplingModes.TopNExtractor}, {SamplingModes.EligibleDataSampler}, {SamplingModes.TimePartitionedSampler}")
};
logger.LogInformation("Sampling Started using {0}", schemaGeneratorSampler.GetType().Name);
List<JsonDocument> dataArray = await schemaGeneratorSampler.GetSampleAsync();
logger.LogInformation("{0} records collected as Sample", dataArray.Count);
logger.LogInformation("GraphQL schema generation started.");
string generatedSchema = SchemaGenerator.Generate(dataArray, dbContainer[1], config, logger);
if (!string.IsNullOrEmpty(generatedSchema))
{
schema.AppendLine(generatedSchema);
}
}
// Generate and return the GraphQL schema based on the sampled data.
return schema.ToString();
}