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 }