Improved progress display

Previously, the progress bar updated only after completing an entire table.

For large tables such as LIBARC, this could make the application appear to have stopped responding.

Phase 10 updates the interface while rows are being exported.
This commit is contained in:
Mark Gregory
2026-10-16 22:28:08 +01:00
parent 37043f316e
commit 788c3373d8
24 changed files with 268 additions and 164 deletions
+88
View File
@@ -292,6 +292,11 @@ struct MainView: View {
pages: [
.dashboard,
.performanceReports,
.slowQueries,
.tableIO,
.innodbMetrics,
.innodbLocks,
.connectionStatistics,
.performanceSchema
]
)
@@ -1274,11 +1279,21 @@ enum WorkbenchAdminPage: String, CaseIterable, Identifiable {
case performanceReports = "Performance Reports"
case performanceSchema = "Performance Schema Setup"
case serverLogs = "Server Error Log"
case slowQueries = "Slow Query Analysis"
case tableIO = "Table I/O Hotspots"
case innodbMetrics = "InnoDB Metrics"
case innodbLocks = "InnoDB Lock Waits"
case connectionStatistics = "Connection Statistics"
var id: String { rawValue }
var icon: String {
switch self {
case .slowQueries: return "tortoise"
case .tableIO: return "externaldrive"
case .innodbMetrics: return "internaldrive"
case .innodbLocks: return "lock.shield"
case .connectionStatistics: return "network"
case .serverLogs: return "text.alignleft"
case .serverStatus: return "server.rack"
case .clientConnections: return "person.2"
@@ -1292,6 +1307,53 @@ enum WorkbenchAdminPage: String, CaseIterable, Identifiable {
var statement: String {
switch self {
case .slowQueries:
return """
SELECT DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT, AVG_TIMER_WAIT,
MAX_TIMER_WAIT, SUM_ROWS_EXAMINED, SUM_ROWS_SENT,
SUM_NO_INDEX_USED, FIRST_SEEN, LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT IS NOT NULL
ORDER BY SUM_TIMER_WAIT DESC LIMIT 100
"""
case .tableIO:
return """
SELECT OBJECT_SCHEMA, OBJECT_NAME, COUNT_READ, COUNT_WRITE,
SUM_TIMER_READ, SUM_TIMER_WRITE
FROM performance_schema.table_io_waits_summary_by_table
WHERE OBJECT_SCHEMA IS NOT NULL
ORDER BY SUM_TIMER_WAIT DESC LIMIT 100
"""
case .innodbMetrics:
return """
SHOW GLOBAL STATUS WHERE Variable_name IN (
'Innodb_buffer_pool_read_requests', 'Innodb_buffer_pool_reads',
'Innodb_buffer_pool_pages_total', 'Innodb_buffer_pool_pages_free',
'Innodb_buffer_pool_pages_dirty', 'Innodb_data_reads',
'Innodb_data_writes', 'Innodb_log_waits',
'Innodb_row_lock_waits', 'Innodb_row_lock_time',
'Innodb_rows_read', 'Innodb_rows_inserted',
'Innodb_rows_updated', 'Innodb_rows_deleted'
)
"""
case .innodbLocks:
return """
SELECT REQUESTING_ENGINE_TRANSACTION_ID, BLOCKING_ENGINE_TRANSACTION_ID,
REQUESTING_ENGINE_LOCK_ID, BLOCKING_ENGINE_LOCK_ID
FROM performance_schema.data_lock_waits
LIMIT 100
"""
case .connectionStatistics:
return """
SHOW GLOBAL STATUS WHERE Variable_name IN (
'Uptime', 'Connections', 'Max_used_connections',
'Threads_connected', 'Threads_running', 'Threads_cached',
'Threads_created', 'Aborted_clients', 'Aborted_connects',
'Connection_errors_max_connections', 'Slow_queries',
'Questions', 'Queries', 'Created_tmp_disk_tables',
'Select_full_join', 'Sort_merge_passes'
)
"""
case .serverLogs:
return "SELECT LOGGED, PRIO, ERROR_CODE, SUBSYSTEM, DATA FROM performance_schema.error_log ORDER BY LOGGED DESC LIMIT 500"
case .serverStatus:
@@ -1382,6 +1444,23 @@ struct WorkbenchAdministrationView: View {
@State private var processActionStatus: String? = nil
@State private var terminatingProcess = false
private var diagnosticGuidance: String? {
switch page {
case .slowQueries:
return "Aggregated statement digests since Performance Schema statistics were last reset. Times are in picoseconds; this is not the server slow-query log. SQL text may be truncated."
case .tableIO:
return "Cumulative Performance Schema table I/O counters since last reset. Times are in picoseconds; refresh to observe changes."
case .innodbMetrics:
return "Cumulative InnoDB status counters; calculate rates from measurements at two different times."
case .innodbLocks:
return "Current InnoDB lock-wait relationships only. An empty result means no waits were visible at the time of the query."
case .connectionStatistics:
return "Server-wide counters since startup. Connections is cumulative, whereas Threads_connected is the current count."
default:
return nil
}
}
private var filteredRows: [[String]] {
guard !searchText.isEmpty else { return result.rows }
return result.rows.filter { row in
@@ -1428,6 +1507,15 @@ struct WorkbenchAdministrationView: View {
resultContent
}
if let guidance = diagnosticGuidance {
Text(guidance)
.font(.caption)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 16)
.padding(.vertical, 8)
}
if page == .clientConnections {
processControls
}