github.com/companieshouse/lfp-pay-api@v0.0.0-20230203133422-0ca455cd79f9/handlers/healthcheck_finance.go (about)

     1  package handlers
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/companieshouse/chs.go/log"
    10  	"github.com/companieshouse/lfp-pay-api-core/models"
    11  	"github.com/companieshouse/lfp-pay-api/config"
    12  	"github.com/companieshouse/lfp-pay-api/utils"
    13  )
    14  
    15  // HandleHealthCheckFinanceSystem checks whether the e5 system is available to take requests
    16  func HandleHealthCheckFinanceSystem(w http.ResponseWriter, r *http.Request) {
    17  	cfg, err := config.Get()
    18  	if err != nil {
    19  		log.ErrorR(r, fmt.Errorf("error returning config: [%v]", err))
    20  		m := models.NewMessageResponse("failed to get maintenance times from config")
    21  		utils.WriteJSONWithStatus(w, r, m, http.StatusInternalServerError)
    22  		return
    23  	}
    24  
    25  	currentTime := time.Now()
    26  	var systemUnavailable bool
    27  	var systemAvailableTime time.Time
    28  
    29  	// Check for weekly downtime
    30  	systemAvailableTime, systemUnavailable = checkWeeklyDownTime(cfg,
    31  		currentTime, systemAvailableTime, systemUnavailable)
    32  
    33  	// Check for planned maintenance
    34  	systemAvailableTime, systemUnavailable, parseError := checkPlannedMaintenance(w, r, cfg, currentTime, systemAvailableTime, systemUnavailable)
    35  	if parseError {
    36  		return
    37  	}
    38  
    39  	if systemUnavailable {
    40  		m := models.NewMessageTimeResponse("UNHEALTHY - PLANNED MAINTENANCE", systemAvailableTime)
    41  		utils.WriteJSONWithStatus(w, r, m, http.StatusServiceUnavailable)
    42  		log.TraceR(r, "Planned maintenance")
    43  		return
    44  	}
    45  
    46  	m := models.NewMessageResponse("HEALTHY")
    47  	utils.WriteJSON(w, r, m)
    48  }
    49  
    50  func checkPlannedMaintenance(w http.ResponseWriter,
    51  	r *http.Request,
    52  	cfg *config.Config,
    53  	currentTime time.Time,
    54  	systemAvailableTime time.Time,
    55  	systemUnavailable bool) (time.Time, bool, bool) {
    56  	if isPlannedMaintenanceCheckRequired(cfg) {
    57  		timeDateLayout := "02 Jan 06 15:04 MST"
    58  		maintenanceStart, err := time.Parse(timeDateLayout, cfg.PlannedMaintenanceStart)
    59  		if err != nil {
    60  			log.ErrorR(r, fmt.Errorf("error parsing Maintenance Start time: [%v]", err))
    61  			w.WriteHeader(http.StatusInternalServerError)
    62  			return time.Time{}, false, true
    63  		}
    64  		maintenanceEnd, err := time.Parse(timeDateLayout, cfg.PlannedMaintenanceEnd)
    65  		if err != nil {
    66  			log.ErrorR(r, fmt.Errorf("error parsing Maintenance End time: [%v]", err))
    67  			w.WriteHeader(http.StatusInternalServerError)
    68  			return time.Time{}, false, true
    69  		}
    70  
    71  		if maintenanceEnd.After(currentTime) && maintenanceStart.Before(currentTime) && maintenanceEnd.After(systemAvailableTime) {
    72  			systemAvailableTime = maintenanceEnd
    73  			systemUnavailable = true
    74  		}
    75  	}
    76  	return systemAvailableTime, systemUnavailable, false
    77  }
    78  
    79  func checkWeeklyDownTime(cfg *config.Config,
    80  	currentTime time.Time,
    81  	systemAvailableTime time.Time,
    82  	systemUnavailable bool) (time.Time, bool) {
    83  	if isWeeklyMaintenanceTimeCheckRequired(cfg) {
    84  		// If the weekday is maintenance day
    85  		if currentTime.Weekday() == cfg.WeeklyMaintenanceDay {
    86  
    87  			weeklyMaintenanceStartTime := returnWeeklyMaintenanceTime(cfg.WeeklyMaintenanceStartTime[:2], cfg.WeeklyMaintenanceStartTime[2:])
    88  
    89  			weeklyMaintenanceEndTime := returnWeeklyMaintenanceTime(cfg.WeeklyMaintenanceEndTime[:2], cfg.WeeklyMaintenanceEndTime[2:])
    90  
    91  			// Check if time is within maintenance time
    92  			if isWithinMaintenanceTime(weeklyMaintenanceEndTime, currentTime, weeklyMaintenanceStartTime) {
    93  				systemAvailableTime = weeklyMaintenanceEndTime
    94  				systemUnavailable = true
    95  			}
    96  		}
    97  	}
    98  	return systemAvailableTime, systemUnavailable
    99  }
   100  
   101  func isPlannedMaintenanceCheckRequired(cfg *config.Config) bool {
   102  	return cfg.PlannedMaintenanceStart != "" && cfg.PlannedMaintenanceEnd != ""
   103  }
   104  
   105  func isWithinMaintenanceTime(weeklyMaintenanceEndTime time.Time, currentTime time.Time, weeklyMaintenanceStartTime time.Time) bool {
   106  	return weeklyMaintenanceEndTime.After(currentTime) && weeklyMaintenanceStartTime.Before(currentTime)
   107  }
   108  
   109  func isWeeklyMaintenanceTimeCheckRequired(cfg *config.Config) bool {
   110  	return cfg.WeeklyMaintenanceStartTime != "" && cfg.WeeklyMaintenanceEndTime != ""
   111  }
   112  
   113  // returnWeeklyMaintenanceTime returns a time.Time format for the current date with the hour and minute set to the arguments passed
   114  func returnWeeklyMaintenanceTime(hour, minute string) time.Time {
   115  	currentTime := time.Now()
   116  
   117  	intHour, _ := strconv.Atoi(hour)
   118  	timeDifferenceInHours := time.Duration(intHour - currentTime.Hour())
   119  
   120  	intMinute, _ := strconv.Atoi(minute)
   121  	timeDifferenceInMinutes := time.Duration(intMinute - currentTime.Minute())
   122  
   123  	return currentTime.Add(time.Hour*timeDifferenceInHours + time.Minute*timeDifferenceInMinutes).Round(time.Second)
   124  }