Files
MBN_STOCK_WEBVIEW/tools/MBN_STOCK_WEBVIEW.DbSmoke/Program.cs

191 lines
5.6 KiB
C#

using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using MBN_STOCK_WEBVIEW.Infrastructure;
using MMoneyCoderSharp.Data;
Console.OutputEncoding = Encoding.UTF8;
using var cancellation = new CancellationTokenSource(TimeSpan.FromMinutes(10));
Console.CancelKeyPress += (_, eventArgs) =>
{
eventArgs.Cancel = true;
cancellation.Cancel();
};
var configurationPath = GetConfigurationPath(args);
try
{
var runtime = DatabaseRuntime.CreateDefault(configurationPath);
var statuses = await runtime.HealthService.CheckAllAsync(cancellation.Token);
foreach (var status in statuses)
{
Console.WriteLine(FormatHealthStatus(status));
}
if (statuses.Any(status => status.State != DatabaseHealthState.Healthy))
{
Console.Error.WriteLine(
"Smoke test stopped because both database health probes must be healthy.");
return 2;
}
await VerifyOracleServerVersionAsync(runtime.Executor, cancellation.Token);
var service = new LegacyMarketDataService(runtime.Executor);
await VerifySnapshotAsync(service, MarketDataView.Kospi, cancellation.Token);
await VerifySnapshotAsync(service, MarketDataView.Kosdaq, cancellation.Token);
await VerifySnapshotAsync(service, MarketDataView.Index, cancellation.Token);
await VerifySnapshotAsync(service, MarketDataView.Overseas, cancellation.Token);
await RealSceneDbSmoke.RunAsync(runtime.Executor, cancellation.Token);
Console.WriteLine("REAL_DB_SMOKE: PASS");
return 0;
}
catch (OperationCanceledException)
{
Console.Error.WriteLine("REAL_DB_SMOKE: CANCELED_OR_TIMED_OUT");
return 3;
}
catch (DatabaseOperationException exception)
{
Console.Error.WriteLine(
"REAL_DB_SMOKE: FAIL - " +
$"Source={exception.DataSource} " +
$"IsTransient={FormatNullableBoolean(exception.IsTransient)} " +
$"ProviderErrorCode={FormatProviderErrorCode(exception.ProviderErrorCode)}");
return 1;
}
catch (DatabaseInfrastructureException)
{
Console.Error.WriteLine(
"REAL_DB_SMOKE: FAIL - A database infrastructure error occurred. " +
"No provider details were printed.");
return 1;
}
catch
{
Console.Error.WriteLine(
"REAL_DB_SMOKE: FAIL - An unexpected error occurred. No provider details were printed.");
return 1;
}
static string FormatHealthStatus(DatabaseHealthStatus status)
{
var summary =
$"{status.Source}: {status.State} " +
$"({status.Elapsed.TotalMilliseconds.ToString("F0", CultureInfo.InvariantCulture)} ms)";
if (status.State == DatabaseHealthState.Healthy)
{
return summary;
}
return summary +
$" IsTransient={FormatNullableBoolean(status.IsTransient)}" +
$" ProviderErrorCode={FormatProviderErrorCode(status.ProviderErrorCode)}";
}
static string FormatNullableBoolean(bool? value) => value switch
{
true => "true",
false => "false",
null => "none"
};
static string FormatProviderErrorCode(int? value) =>
value?.ToString(CultureInfo.InvariantCulture) ?? "none";
static string? GetConfigurationPath(string[] arguments)
{
if (arguments.Length == 0)
{
return null;
}
if (arguments.Length == 2 &&
arguments[0].Equals("--config", StringComparison.OrdinalIgnoreCase))
{
return arguments[1];
}
throw new DatabaseConfigurationException(
"Usage: MBN_STOCK_WEBVIEW.DbSmoke [--config <path>]");
}
static async Task VerifyOracleServerVersionAsync(
IDataQueryExecutor executor,
CancellationToken cancellationToken)
{
const string query =
"SELECT VERSION FROM PRODUCT_COMPONENT_VERSION " +
"WHERE PRODUCT LIKE 'Oracle Database%' FETCH FIRST 1 ROWS ONLY";
var table = await executor.ExecuteAsync(
DataSourceKind.Oracle,
"OracleVersion",
query,
cancellationToken);
if (table.Rows.Count == 0 || table.Columns.Count == 0)
{
throw new DatabaseConfigurationException(
"The Oracle server version query returned no version.");
}
var version = Convert.ToString(
table.Rows[0][0],
CultureInfo.InvariantCulture) ?? string.Empty;
var match = Regex.Match(
version,
@"(?<!\d)(?<major>\d{2})(?:\.\d+)",
RegexOptions.CultureInvariant);
if (!match.Success ||
!int.TryParse(
match.Groups["major"].Value,
NumberStyles.None,
CultureInfo.InvariantCulture,
out var major))
{
throw new DatabaseConfigurationException(
"The Oracle server major version could not be determined.");
}
Console.WriteLine($"Oracle server major version: {major}");
if (major < 19)
{
throw new DatabaseConfigurationException(
"Oracle.ManagedDataAccess.Core requires Oracle Database 19c or newer.");
}
}
static async Task VerifySnapshotAsync(
IMarketDataService service,
MarketDataView view,
CancellationToken cancellationToken)
{
var snapshot = await service.GetAsync(
view,
maximumRowsPerTable: 5,
cancellationToken);
if (snapshot.Tables.Count == 0)
{
throw new DatabaseConfigurationException(
$"{view} returned no database result set.");
}
foreach (var table in snapshot.Tables)
{
if (table.Columns.Count == 0)
{
throw new DatabaseConfigurationException(
$"{view}/{table.Name} returned no columns.");
}
Console.WriteLine(
$"{view}/{table.Source}/{table.Name}: " +
$"{table.TotalRowCount.ToString(CultureInfo.InvariantCulture)} rows");
}
}