using System.Data; using System.Globalization; using MMoneyCoderSharp.Data; internal static class NxtThemeRestoreDbAudit { private const string ActiveRowsQueryName = "AUDIT_ACTIVE_NXT_THEME_ROWS"; private const string ActiveRowsSql = """ SELECT LIST_TEXT FROM ( SELECT p.LIST_TEXT FROM DC_LIST d JOIN PLAY_LIST p ON p.PG_CODE = d.DC_CODE WHERE p.LIST_TEXT LIKE '1^테마_NXT^%' ORDER BY d.DC_CODE, TO_NUMBER(p.ITEM_INDEX) ) WHERE ROWNUM <= :row_limit """; internal static async Task RunAsync( IDataQueryExecutor executor, CancellationToken cancellationToken) { const int maximumRows = 1_000; var spec = new DataQuerySpec( ActiveRowsSql, [new DataQueryParameter("row_limit", maximumRows + 1, DbType.Int32)]); spec.ValidateFor(DataSourceKind.Oracle); var table = await executor.ExecuteAsync( DataSourceKind.Oracle, ActiveRowsQueryName, spec, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); if (table.Columns.Count != 1 || table.Columns[0].ColumnName != "LIST_TEXT" || table.Columns[0].DataType != typeof(string) || table.Rows.Count > maximumRows) { throw new InvalidDataException("The active NXT-theme audit boundary is invalid."); } var rows = new List(table.Rows.Count); var grammar = new Dictionary(StringComparer.Ordinal); foreach (DataRow dataRow in table.Rows) { if (dataRow[0] is not string text) { throw new InvalidDataException("An active NXT-theme row is not text."); } var fields = text.Split('^'); if (fields.Length != 7 || fields[0] != "1" || fields[1] != "테마_NXT") { throw new InvalidDataException("An active NXT-theme row has an invalid shape."); } var pageText = fields[5].Replace(" ", string.Empty, StringComparison.Ordinal); rows.Add(new LegacyNamedNxtThemeRestoreRow( rows.Count, IsEnabled: true, fields[1], fields[2], fields[3], fields[4], pageText, fields[6])); var key = string.Join('|', fields[3], fields[4]); grammar[key] = grammar.GetValueOrDefault(key) + 1; } if (rows.Count == 0) { Console.WriteLine("NXT_THEME_RESTORE_AUDIT: active=0"); return; } var result = await new LegacyNamedNxtThemeRestoreService(executor) .ResolveAsync(rows, cancellationToken); var resolved = result.Rows.Count(row => row.IsResolved); var identityMapped = result.Rows.Count(row => row.ObservedCurrentThemeCode is not null); var remapped = result.Rows .Select((row, index) => row.ObservedCurrentThemeCode is not null && !string.Equals( row.ObservedCurrentThemeCode, rows[index].DataCode, StringComparison.Ordinal)) .Count(static value => value); var failures = result.Rows .Where(row => row.Failure.HasValue) .GroupBy(row => row.Failure!.Value) .OrderBy(group => group.Key) .Select(group => $"{group.Key}={group.Count().ToString(CultureInfo.InvariantCulture)}") .ToArray(); var actions = result.Rows .Where(row => row.IsResolved) .GroupBy(row => row.Identity!.ActionId) .OrderBy(group => group.Key, StringComparer.Ordinal) .Select(group => $"{group.Key}={group.Count().ToString(CultureInfo.InvariantCulture)}") .ToArray(); var liveCounts = result.Rows .Where(row => row.IsResolved) .Select(row => row.Identity!.LiveItemCount) .ToArray(); Console.WriteLine( "NXT_THEME_RESTORE_AUDIT: " + $"active={rows.Count.ToString(CultureInfo.InvariantCulture)} " + $"distinctTitles={rows.Select(row => row.Subject).Distinct(StringComparer.Ordinal).Count().ToString(CultureInfo.InvariantCulture)} " + $"grammarVariants={grammar.Count.ToString(CultureInfo.InvariantCulture)} " + $"identityMapped={identityMapped.ToString(CultureInfo.InvariantCulture)} " + $"resolved={resolved.ToString(CultureInfo.InvariantCulture)} " + $"remapped={remapped.ToString(CultureInfo.InvariantCulture)} " + $"blocked={(rows.Count - resolved).ToString(CultureInfo.InvariantCulture)} " + $"session={LegacyNamedNxtThemeRestoreService.SessionForLocalHour(DateTime.Now.Hour)}"); Console.WriteLine("NXT_THEME_RESTORE_GRAMMAR: " + string.Join(",", grammar .OrderBy(pair => pair.Key, StringComparer.Ordinal) .Select(pair => $"{pair.Key}={pair.Value.ToString(CultureInfo.InvariantCulture)}"))); Console.WriteLine("NXT_THEME_RESTORE_ACTIONS: " + (actions.Length == 0 ? "none" : string.Join(",", actions))); Console.WriteLine("NXT_THEME_RESTORE_FAILURES: " + (failures.Length == 0 ? "none" : string.Join(",", failures))); Console.WriteLine("NXT_THEME_RESTORE_LIVE_ITEMS: " + (liveCounts.Length == 0 ? "none" : $"min={liveCounts.Min().ToString(CultureInfo.InvariantCulture)}," + $"max={liveCounts.Max().ToString(CultureInfo.InvariantCulture)}," + $"sum={liveCounts.Sum().ToString(CultureInfo.InvariantCulture)}")); } }