Reputation: 225
I'm developing a REST service (using RESTeasy) that performs heavy calculations and produces large results (that will be downloaded to a file). In order protect the system, we decided to limit the execution by the same user by preventing concurrent invocations.
I thought to put a variable on the session, like this:
//check if service is running before execution
if (Boolean.parseBoolean((String) session.getAttribute("isRunning"))) {
throw new WebApplicationException(Response.status(
Response.Status.FORBIDDEN).entity("Service is currently running!").build());
}
//on execution
session.setAttribute("isRunning", "true");
//after execution
finally {
session.setAttribute("isRunning", "false");
}
but this limits usage per session, not per user.
Upvotes: 1
Views: 1062
Reputation: 225
Building on the approach suggested by @dwb, here is my answer:
//globally defined set holding ids of users currently executing the service
private static Set<String> currentUsers = Collections.synchronizedSortedSet(new TreeSet<String>());
//check if service is running before execution
if (isCurrentlyRunningByUser(request.getRemoteUser())) {
throw new WebApplicationException(Response.status(Response.Status.FORBIDDEN).entity("Service is currently running!").build());
}
//after execution
finally {
currentUsers.remove(user);
}
/**
* checks if user is currently running the service. if yes, returns true.
* if no, add user to current users set, and returns false
* @param remoteUser user asking to execute the service
* @return true if service is being run by the user
*/
private boolean isCurrentlyRunningByUser(String user) {
synchronized (currentUsers) {
Iterator it = currentUsers.iterator();
while (it.hasNext()) {
if (user.equals(it.next())) {
return true;
}
}
currentUsers.add(user);
}
return false;
}
Upvotes: 0
Reputation: 38300
You are on the right track.
Store a set in the session (I'll call this the UserSet).
When you get a request, do the following:
Edit: corrected scope based on John Wu comment.
Upvotes: 1