2023-05-24 12:42:29 +02:00
package eu.openaire.urls_controller.controllers ;
import eu.openaire.urls_controller.models.WorkerInfo ;
import eu.openaire.urls_controller.services.ShutdownService ;
2023-06-06 15:49:53 +02:00
import eu.openaire.urls_controller.util.GenericUtils ;
2023-05-24 12:42:29 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.http.HttpStatus ;
import org.springframework.http.ResponseEntity ;
import org.springframework.web.bind.annotation.PostMapping ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RequestParam ;
import org.springframework.web.bind.annotation.RestController ;
import javax.servlet.http.HttpServletRequest ;
@RestController
@RequestMapping ( " " )
public class ShutdownController {
private static final Logger logger = LoggerFactory . getLogger ( ShutdownController . class ) ;
@Autowired
ShutdownService shutdownService ;
public static boolean shouldShutdownService = false ;
@PostMapping ( " shutdownService " )
public ResponseEntity < ? > shutdownServiceGracefully ( HttpServletRequest request )
{
2023-06-15 22:19:36 +02:00
String initMsg = " Received a \" shutdownService \" request " ;
String remoteAddr = GenericUtils . getRequestorAddress ( request ) ;
initMsg + = " from [ " + remoteAddr + " ]. " ;
ResponseEntity < ? > responseEntity = shutdownService . passSecurityChecks ( remoteAddr , initMsg ) ;
2023-05-24 12:42:29 +02:00
if ( responseEntity ! = null )
return responseEntity ;
2023-05-29 12:41:37 +02:00
String endingMsg ;
if ( shouldShutdownService ) {
endingMsg = " The controller has already received a \" shutdownService \" (which was not canceled afterwards). " ;
logger . info ( initMsg + endingMsg ) ;
} else {
2023-05-24 12:42:29 +02:00
shouldShutdownService = true ;
2023-05-29 12:41:37 +02:00
endingMsg = " The service will shutdown, after finishing current work. " ;
logger . info ( initMsg + endingMsg ) ;
// Send "shutdownWorker" requests to all active Workers.
2023-05-29 11:42:54 +02:00
for ( String workerId : UrlsController . workersInfoMap . keySet ( ) ) {
2023-05-29 12:41:37 +02:00
WorkerInfo workerInfo = UrlsController . workersInfoMap . get ( workerId ) ;
if ( ! workerInfo . getHasShutdown ( ) ) // A worker may have shutdown on its own (by sending it a shutDown request manually), so it will have told the Controller when it shut down. In case of a Worker-crash, the Controller will not know about it.
shutdownService . postShutdownOrCancelRequestToWorker ( workerId , workerInfo . getWorkerIP ( ) , false ) ;
else
logger . warn ( " Will not post ShutdownRequest to Worker \" " + workerId + " \" , since is it has already shutdown. " ) ;
2023-05-29 11:42:54 +02:00
}
2023-05-24 12:42:29 +02:00
// That's it for now. The workers may take some hours to finish their work (including delivering the full-text files).
2023-05-27 01:36:05 +02:00
// A scheduler monitors the shutdown of the workers. Once all worker have shutdown, the Controller shuts down as well.
2023-05-24 12:42:29 +02:00
}
2023-05-29 12:41:37 +02:00
return ResponseEntity . ok ( ) . body ( endingMsg + " \ n " ) ;
2023-05-24 12:42:29 +02:00
}
@PostMapping ( " cancelShutdownService " )
public ResponseEntity < ? > cancelShutdownServiceGracefully ( HttpServletRequest request )
{
2023-06-15 22:19:36 +02:00
String initMsg = " Received a \" cancelShutdownService \" request " ;
String remoteAddr = GenericUtils . getRequestorAddress ( request ) ;
initMsg + = " from [ " + remoteAddr + " ]. " ;
ResponseEntity < ? > responseEntity = shutdownService . passSecurityChecks ( remoteAddr , initMsg ) ;
2023-05-24 12:42:29 +02:00
if ( responseEntity ! = null )
return responseEntity ;
shouldShutdownService = false ;
2023-05-29 12:41:37 +02:00
String endingMsg = " Any previous \" shutdownService \" -request is canceled. " ;
logger . info ( initMsg + endingMsg ) ;
// Send "cancelShutdownWorker" requests to all active Workers.
for ( String workerId : UrlsController . workersInfoMap . keySet ( ) ) {
WorkerInfo workerInfo = UrlsController . workersInfoMap . get ( workerId ) ;
if ( ! workerInfo . getHasShutdown ( ) ) // A worker may have shutdown on its own (by sending it a shutDown request manually), so it will have told the Controller when it shut down. In case of a Worker-crash, the Controller will not know about it.
shutdownService . postShutdownOrCancelRequestToWorker ( workerId , workerInfo . getWorkerIP ( ) , true ) ;
else
logger . warn ( " Will not post CancelShutdownRequest to Worker \" " + workerId + " \" , since is it has already shutdown. " ) ;
}
2023-05-24 12:42:29 +02:00
2023-05-29 12:41:37 +02:00
return ResponseEntity . ok ( ) . body ( endingMsg + " \ n " ) ;
2023-05-24 12:42:29 +02:00
}
@PostMapping ( " workerShutdownReport " )
public ResponseEntity < ? > workerShutdownReport ( @RequestParam String workerId , HttpServletRequest request )
{
String initMsg = " Received a \" workerShutdownReport \" from worker: \" " + workerId + " \" . " ;
WorkerInfo workerInfo = UrlsController . workersInfoMap . get ( workerId ) ;
if ( workerInfo = = null ) {
2023-06-15 22:19:36 +02:00
String errorMsg = " The worker with id \" " + workerId + " \" has not participated in the PDF-Aggregation-Service! " ;
2023-05-24 12:42:29 +02:00
logger . warn ( initMsg + " \ n " + errorMsg ) ;
return ResponseEntity . badRequest ( ) . body ( errorMsg ) ;
}
2023-06-06 15:49:53 +02:00
String remoteAddr = GenericUtils . getRequestorAddress ( request ) ;
2023-05-24 12:42:29 +02:00
if ( ! remoteAddr . equals ( workerInfo . getWorkerIP ( ) ) ) {
logger . error ( initMsg + " The request came from another IP: " + remoteAddr + " | while this worker was registered with the IP: " + workerInfo . getWorkerIP ( ) ) ;
return ResponseEntity . status ( HttpStatus . FORBIDDEN ) . build ( ) ;
}
logger . info ( initMsg ) ;
workerInfo . setHasShutdown ( true ) ; // This will update the map.
// Return "HTTP-OK" to this worker and wait for the scheduler to check and shutdown the service.
return ResponseEntity . ok ( ) . build ( ) ;
}
}