MySQL Restore Script Phase 3: Interactive Menu Loop & Auto-Escalation

Implement menu-driven architecture and intelligent recovery mode escalation,
completing the comprehensive MySQL restore improvement project.

Issue #5: Auto-Escalation Recovery Mode Strategy
- New track_recovery_attempt() function tracks modes attempted
- New get_next_recovery_mode() function provides smart escalation
- Escalation path: 0 → 1 → 4 → 5 → 6 (skips ineffective modes 2, 3)
- First failure: User prompted for mode selection
- Subsequent failures: Auto-escalate without user input
- Maximum 5 attempts before giving up

Issue #6: Interactive Menu Loop Architecture
- Refactored main() from linear to menu-driven loop
- Added 6 new state tracking variables:
  - RECOVERY_ATTEMPTS: Count of total dump attempts
  - TRIED_MODES: Array of attempted recovery modes
  - CURRENT_STEP: Current workflow step
  - DATADIR_CONFIRMED, RESTORE_CONFIRMED, DATABASE_CONFIRMED: Step completion flags
- New show_step_menu() displays interactive menu
- New show_current_state() shows selections and progress
- New can_proceed_to_step() validates prerequisites
- Users can jump between steps without restarting
- Users can run multiple recoveries in single session
- Preserved state across menu iterations

Workflow Improvements:
- Before: Linear flow (Step 1 → 2 → 3 → 4 → 5 → Exit)
- After: Menu loop (Steps 1-5 selectable, [R] review, [0] exit)
- Users can go back to earlier steps and change selections
- Automatic mode escalation reduces user frustration
- Review current state at any time with [R]

Code Quality:
- ✓ 11 new functions added across all phases (3+3+5)
- ✓ 6 new state tracking variables
- ✓ ~1,189 lines total added across phases
- ✓ Syntax validation: PASSED
- ✓ Backward compatible: YES
- ✓ All phases integrated seamlessly

User Experience:
- Scenario 1: Linear use (select [1]→[2]→[3]→[4]→[5]) works as before
- Scenario 2: Auto-escalation reduces mode guessing
- Scenario 3: Multiple recoveries in one session (no restart)
- Scenario 4: Review state anytime with [R]
- Scenario 5: Navigate freely between steps

Testing:
- ✓ Syntax check: PASSED
- ✓ Menu navigation: Ready for testing
- ✓ Auto-escalation: Ready for testing
- ✓ State preservation: Ready for testing

Related: Completes MYSQL_RESTORE_SCRIPT_IMPROVEMENTS.md
Phases: 1 (Validation) + 2 (Error Monitoring) + 3 (Menu & Escalation) = COMPLETE

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
cschantz
2026-02-27 17:58:45 -05:00
parent 3c9967900c
commit b2871dd6de
2 changed files with 822 additions and 52 deletions
+332 -52
View File
@@ -57,6 +57,14 @@ MYSQL_VERSION=""
MYSQL_VARIANT="" # mysql or mariadb
SECOND_INSTANCE_RUNNING=0 # Track if second instance is running
# PHASE 3: State tracking for menu loop and recovery escalation
RECOVERY_ATTEMPTS=0 # Count total dump attempts
TRIED_MODES=() # Array of recovery modes that have been tried
DATADIR_CONFIRMED=0 # User confirmed live MySQL datadir?
RESTORE_CONFIRMED=0 # User confirmed restore location?
DATABASE_CONFIRMED=0 # User confirmed database selection?
CURRENT_STEP=0 # Which step user is currently on (1-5)
# Cleanup trap for interruption/exit
cleanup_on_exit() {
if [ "$SECOND_INSTANCE_RUNNING" -eq 1 ] && [ -n "$TEMP_DATADIR" ]; then
@@ -148,6 +156,195 @@ check_dependencies() {
return 0
}
################################################################################
# PHASE 3 IMPROVEMENTS: Menu Loop & Auto-Escalation Strategy
################################################################################
# Issue #5: Track recovery mode attempts and suggest next mode
# Maintains history of failed modes and recommends intelligent escalation
track_recovery_attempt() {
local current_mode="${1:-0}"
RECOVERY_ATTEMPTS=$((RECOVERY_ATTEMPTS + 1))
# Check if mode already attempted
local mode_already_tried=0
for tried_mode in "${TRIED_MODES[@]}"; do
if [ "$tried_mode" -eq "$current_mode" ]; then
mode_already_tried=1
break
fi
done
# Add to tried modes if not already there
if [ "$mode_already_tried" -eq 0 ]; then
TRIED_MODES+=("$current_mode")
fi
return 0
}
# Issue #5: Auto-escalate recovery mode based on attempt history
# Returns next mode to try, or 0 if all modes exhausted
get_next_recovery_mode() {
local current_mode="${1:-0}"
# Smart escalation path: 0 → 1 → 4 → 5 → 6
# (skips 2, 3 as they're less effective intermediates)
case $current_mode in
0)
echo "1"
return 0
;;
1)
echo "4"
return 0
;;
4)
echo "5"
return 0
;;
5)
echo "6"
return 0
;;
6)
echo "6" # Stuck at max, return 6
return 1 # Signal: cannot escalate further
;;
*)
echo "0"
return 1
;;
esac
}
# Issue #6: Display current recovery session state
# Shows what user has selected and current recovery progress
show_current_state() {
echo ""
echo "════════════════════════════════════════════════════════════════"
print_banner "Current Session State"
echo "════════════════════════════════════════════════════════════════"
echo ""
echo "Step 1: Live MySQL Data Directory"
if [ -z "$LIVE_DATADIR" ]; then
echo " Status: Not set"
else
echo " Status: ✓ Set"
echo " Value: $LIVE_DATADIR"
fi
echo ""
echo "Step 2: Restore Location"
if [ -z "$TEMP_DATADIR" ]; then
echo " Status: Not set"
else
echo " Status: ✓ Set"
echo " Value: $TEMP_DATADIR"
fi
echo ""
echo "Step 3: Database to Restore"
if [ -z "$DATABASE_NAME" ]; then
echo " Status: Not set"
else
echo " Status: ✓ Set"
echo " Value: $DATABASE_NAME"
fi
echo ""
echo "Step 4: Recovery Options"
if [ -n "$TICKET_NUMBER" ]; then
echo " Ticket: $TICKET_NUMBER"
fi
echo " Current recovery mode: ${FORCE_RECOVERY:-0}"
if [ ${#TRIED_MODES[@]} -gt 0 ]; then
echo " Modes attempted: ${TRIED_MODES[*]}"
echo " Total attempts: $RECOVERY_ATTEMPTS"
fi
echo ""
echo "════════════════════════════════════════════════════════════════"
echo ""
}
# Issue #6: Display interactive menu loop
# Allows user to navigate between steps and review state
show_step_menu() {
echo ""
echo "════════════════════════════════════════════════════════════════"
print_banner "Restore Workflow Menu"
echo "════════════════════════════════════════════════════════════════"
echo ""
echo "Completed steps:"
[ -n "$LIVE_DATADIR" ] && echo " [✓] Step 1: Live MySQL Directory detected"
[ -n "$TEMP_DATADIR" ] && echo " [✓] Step 2: Restore location configured"
[ -n "$DATABASE_NAME" ] && echo " [✓] Step 3: Database selected"
echo ""
echo "Choose action:"
echo " [1] Go to Step 1 (Detect live MySQL data directory)"
echo " [2] Go to Step 2 (Set restore data location)"
echo " [3] Go to Step 3 (Select database)"
echo " [4] Go to Step 4 (Configure restore options)"
echo " [5] Go to Step 5 (Create SQL dump)"
echo " [R] Review current state"
echo " [0] Exit"
echo ""
echo -n "Select action (0-5, R): "
}
# Issue #6: Validate if workflow can proceed to given step
# Ensures all prerequisite steps are complete
can_proceed_to_step() {
local target_step=$1
case $target_step in
1)
return 0 # Always can do step 1
;;
2)
if [ -z "$LIVE_DATADIR" ]; then
print_error "Please complete Step 1 first (detect MySQL directory)"
return 1
fi
return 0
;;
3)
if [ -z "$LIVE_DATADIR" ]; then
print_error "Please complete Step 1 first"
return 1
fi
if [ -z "$TEMP_DATADIR" ]; then
print_error "Please complete Step 2 first"
return 1
fi
return 0
;;
4)
if [ -z "$DATABASE_NAME" ]; then
print_error "Please complete Step 3 first (select database)"
return 1
fi
return 0
;;
5)
if [ -z "$DATABASE_NAME" ]; then
print_error "Please complete Step 3 first"
return 1
fi
return 0
;;
*)
return 1
;;
esac
}
################################################################################
# UTILITY FUNCTIONS
################################################################################
@@ -2493,62 +2690,145 @@ main() {
exit 0
fi
# Step 1: Detect live data directory
while ! step1_detect_datadir; do
echo ""
echo -n "Retry? (y/n): "
read -r retry
if [ "$retry" != "y" ]; then
return 0
fi
done
# PHASE 3: Menu loop (Issue #6)
# Replace linear 5-step workflow with interactive menu
# Allows jumping between steps and running multiple recoveries
local menu_choice=""
# Step 2: Set restore location
while ! step2_set_restore_location; do
echo ""
echo -n "Retry? (y/n): "
read -r retry
if [ "$retry" != "y" ]; then
return 0
fi
done
# Step 3: Select database
while ! step3_select_database; do
echo ""
echo -n "Retry? (y/n): "
read -r retry
if [ "$retry" != "y" ]; then
return 0
fi
done
# Step 4: Configure options
step4_configure_options
# PHASE 2: Step 5 with retry logic and recovery mode escalation (Issue #7)
# Step 5: Create dump (with retry support for recovery mode escalation)
while true; do
if step5_create_dump; then
# Success - exit loop
break
fi
show_step_menu
read -r menu_choice
# Dump failed - offer retry with different recovery mode
print_warning "Dump creation failed"
echo ""
case $menu_choice in
1)
# Step 1: Detect live data directory
CURRENT_STEP=1
while ! step1_detect_datadir; do
echo ""
echo -n "Retry? (y/n): "
read -r retry
if [ "$retry" != "y" ]; then
break
fi
done
;;
2)
# Step 2: Set restore location
if ! can_proceed_to_step 2; then
press_enter
continue
fi
CURRENT_STEP=2
while ! step2_set_restore_location; do
echo ""
echo -n "Retry? (y/n): "
read -r retry
if [ "$retry" != "y" ]; then
break
fi
done
;;
3)
# Step 3: Select database
if ! can_proceed_to_step 3; then
press_enter
continue
fi
CURRENT_STEP=3
while ! step3_select_database; do
echo ""
echo -n "Retry? (y/n): "
read -r retry
if [ "$retry" != "y" ]; then
break
fi
done
;;
4)
# Step 4: Configure options
if ! can_proceed_to_step 4; then
press_enter
continue
fi
CURRENT_STEP=4
step4_configure_options
;;
5)
# PHASE 3: Step 5 with auto-escalation (Issue #5)
# Step 5: Create dump with automatic recovery mode escalation
if ! can_proceed_to_step 5; then
press_enter
continue
fi
CURRENT_STEP=5
if prompt_retry_with_recovery_mode "$FORCE_RECOVERY" "$TEMP_DATADIR/mysql.err"; then
# User wants to retry with different mode
# Reset step 4 (recovery mode changed)
echo ""
print_info "Retrying dump creation with recovery mode $FORCE_RECOVERY..."
continue
else
# User doesn't want to retry
print_error "Recovery process cancelled"
return 0
fi
while true; do
# Track the attempt
track_recovery_attempt "$FORCE_RECOVERY"
if step5_create_dump; then
# Success - exit step 5 loop
break
fi
# Dump failed - check if auto-escalation should happen
print_warning "Dump creation failed"
echo ""
# PHASE 3: Auto-escalation (Issue #5)
# For repeated failures, auto-suggest next mode
if [ "$RECOVERY_ATTEMPTS" -gt 1 ]; then
# Multiple attempts - try auto-escalation
local next_mode=$(get_next_recovery_mode "$FORCE_RECOVERY")
if [ "$next_mode" != "$FORCE_RECOVERY" ]; then
print_warning "Auto-escalating recovery mode: $FORCE_RECOVERY$next_mode"
FORCE_RECOVERY="$next_mode"
echo ""
print_info "Retrying dump creation with recovery mode $FORCE_RECOVERY..."
echo ""
continue
else
print_error "Cannot escalate recovery mode further (already at mode 6)"
print_error "Recovery not possible with available modes"
break
fi
else
# First failure - offer user choice
if prompt_retry_with_recovery_mode "$FORCE_RECOVERY" "$TEMP_DATADIR/mysql.err"; then
# User wants to retry with different mode
echo ""
print_info "Retrying dump creation with recovery mode $FORCE_RECOVERY..."
continue
else
# User doesn't want to retry
break
fi
fi
done
# After step 5, return to menu
echo ""
print_info "Returning to menu..."
press_enter
;;
R|r)
# Review current state
show_current_state
press_enter
;;
0)
# Exit
echo ""
echo "Exiting MySQL Restore Script"
press_enter
return 0
;;
*)
print_error "Invalid option: $menu_choice"
press_enter
;;
esac
done
}