J'ai une ressource Class
, avec une classe de méthode @ManagedAsync
qui ressemble à ceci:JAX-RS dans Dropwizard: Gestion des appels async avec réponse immédiate
@Path("my-resource")
public class MyResource extends BaseResource{
private DatumDAO datumDAO;
public MyResource(DatumDAO datumDAO){
this.datumDAO = datumDAO;
}
public void cleanDatum(Datum datum){
//time taking operations
}
@GET
@ManagedAsync
@Path("/cleanup/{from}/{till}/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@UnitOfWork
public void cleanupDirtyData(@Suspended final AsyncResponse asyncResponse, @PathParam("from") DateTimeParam from,
@PathParam("till") DateTimeParam till) throws IOException{
logger.debug("will try to cleanup dirty data in range: " + from + " " + till);
List<Datum> data = datumDAO.getALlDirtyDatumInRange(from.get().toDate(), till.get().toDate());
Map<Long,String> cleanupMap = new HashMap<Long,String>();
for(Datum datum: data){
cleanDatum(datum);
cleanupMap.put(datum.getId(), "cleaned");
}
// this response need to be sent [can be ignored]
asyncResponse.resume(Response.status(HttpStatus.OK_200).entity(cleanupMap).build());
}
}
Depuis l'appel à cleanupDirtyData
peut prendre un certain temps, je ne Je ne veux pas que les clients l'attendent complètement, je comprends que le travail d'exécution est déchargé sur un thread de travail différent.
Ce que je suis en train de réaliser est de donner une réponse immédiate au client et continuer à faire l'exécution de la fonction cleanupDirtyData
de manière asynchrone.
donc essayé la chose suivante:
Mettre un délai d'attente de force, et de donner une réponse prématurée au client, mais cela ne semble pas être le moyen idéal et il arrête l'exécution.
qui ressemblerait à quelque chose comme ceci:
@Path("my-resource")
public class MyResource extends BaseResource{
private DatumDAO datumDAO;
public MyResource(DatumDAO datumDAO){
this.datumDAO = datumDAO;
}
public void cleanDatum(Datum datum){
//time taking operations
}
@GET
@ManagedAsync
@Path("/cleanup/{from}/{till}/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@UnitOfWork
public void cleanupDirtyData(@Suspended final AsyncResponse asyncResponse, @PathParam("from") DateTimeParam from,
@PathParam("till") DateTimeParam till) throws IOException{
// Register handler and set timeout
asyncResponse.setTimeoutHandler(new TimeoutHandler() {
public void handleTimeout(AsyncResponse ar) {
asyncResponse.resume(Response.status(SERVICE_UNAVAILABLE).entity(
"Operation timed out -- please try again").build());
}
});
ar.setTimeout(15, TimeUnit.SECONDS);
logger.debug("will try to cleanup dirty data in range: " + from + " " + till);
List<Datum> data = datumDAO.getALlDirtyDatumInRange(from.get().toDate(), till.get().toDate());
Map<Long,String> cleanupMap = new HashMap<Long,String>();
for(Datum datum: data){
cleanDatum(datum);
cleanupMap.put(datum.getId(), "cleaned");
}
// this response need to be sent [can be ignored]
asyncResponse.resume(Response.status(HttpStatus.OK_200).entity(cleanupMap).build());
}
}
_ "Étant donné que l'appel de cleanupDirtyData peut prendre un certain temps, je ne veux pas que les clients l'attendent complètement" _ - Vous voulez savoir pourquoi cela n'a pas de sens? Parce que dans votre code, vous renvoyez un corps de réponse au client. Si ce corps de réponse fait partie de "l'exécution longue", comment voulez-vous renvoyer la réponse au client lorsque l'exécution pour obtenir le corps n'est pas terminée? Si je me trompe, quelle est exactement la tâche à long terme dans votre code? –
@peeskillet c'était un code d'espace réservé, je n'ai pas besoin de retourner une réponse une fois le travail terminé. Les tâches de longue durée impliquent beaucoup d'E/S de disques, ce qui peut prendre jusqu'à 15 minutes. – anand