mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 21:25:38 +00:00
bug6017: introduced a lock map for subscription handling
This commit is contained in:
+19
@@ -1,11 +1,15 @@
|
||||
package com.sap.sailing.server.gateway.subscription;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
|
||||
import com.sap.sse.security.shared.UserManagementException;
|
||||
import com.sap.sse.security.shared.impl.User;
|
||||
import com.sap.sse.security.shared.subscription.Subscription;
|
||||
@@ -17,6 +21,13 @@ public abstract class SubscriptionWebHookHandler {
|
||||
private static final Logger logger = Logger.getLogger(SubscriptionWebHookHandler.class.getName());
|
||||
|
||||
protected SubscriptionWebHookServlet context;
|
||||
|
||||
/**
|
||||
* When working with a user's subscriptions, such as first reading, then changing and updating a user's subscription
|
||||
* based on what was read, a user-specific write lock must be obtained to ensure that no writes can cut in between.
|
||||
* See also {@link #lockSubscriptionsForUser} and {@link #unlockSubscriptionsForUser}.
|
||||
*/
|
||||
private final static ConcurrentMap<User, NamedReentrantReadWriteLock> subscriptionLocksForUsers = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Handle webhook
|
||||
@@ -37,6 +48,14 @@ public abstract class SubscriptionWebHookHandler {
|
||||
protected User getUser(String customerId) {
|
||||
return context.getSecurityService().getUserByName(customerId);
|
||||
}
|
||||
|
||||
protected void lockSubscriptionsForUser(final User user) {
|
||||
LockUtil.lockForWrite(subscriptionLocksForUsers.computeIfAbsent(user, u->new NamedReentrantReadWriteLock("Subscriptions lock for user "+user.getName(), /* fair */ false)));
|
||||
}
|
||||
|
||||
protected void unlockSubscriptionsForUser(final User user) {
|
||||
LockUtil.unlockAfterWrite(subscriptionLocksForUsers.computeIfAbsent(user, u->new NamedReentrantReadWriteLock("Subscriptions lock for user "+user.getName(), /* fair */ false)));
|
||||
}
|
||||
|
||||
protected void updateUserSubscription(User user, Subscription subscription) throws UserManagementException {
|
||||
logger.info(() -> "Update subscription, user " + user.getName() + ", new subscription "
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ public class SubscriptionWebHookHandlerFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return webhook hanlder for request path, return null in case handler could not be found for the request
|
||||
* Return webhook handler for request path, return null in case handler could not be found for the request
|
||||
*/
|
||||
public SubscriptionWebHookHandler getHandlerForPath(String path, SubscriptionWebHookServlet context) {
|
||||
final Class<? extends SubscriptionWebHookHandler> handlerCls = handlers.get(path);
|
||||
@@ -53,7 +53,7 @@ public class SubscriptionWebHookHandlerFactory {
|
||||
}
|
||||
|
||||
private void registerHandler(Class<? extends SubscriptionWebHookHandler> handlerCls) {
|
||||
SubscriptionWebHookHandler inst = createHandlerInstance(handlerCls);
|
||||
final SubscriptionWebHookHandler inst = createHandlerInstance(handlerCls);
|
||||
if (inst != null) {
|
||||
handlers.put(inst.getHandlerPath(), handlerCls);
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@ public class SubscriptionWebHookServlet extends SailingServerHttpServlet {
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String path = getRequestHandlerPath(request);
|
||||
SubscriptionWebHookHandler handler = SubscriptionWebHookHandlerFactory.getInstance().getHandlerForPath(path,
|
||||
final String path = getRequestHandlerPath(request);
|
||||
final SubscriptionWebHookHandler handler = SubscriptionWebHookHandlerFactory.getInstance().getHandlerForPath(path,
|
||||
this);
|
||||
if (handler != null) {
|
||||
handler.handle(request, response);
|
||||
@@ -31,8 +31,8 @@ public class SubscriptionWebHookServlet extends SailingServerHttpServlet {
|
||||
}
|
||||
|
||||
private String getRequestHandlerPath(HttpServletRequest request) {
|
||||
String pathInfo = request.getPathInfo();
|
||||
String[] pathParts = pathInfo.split("/");
|
||||
final String pathInfo = request.getPathInfo();
|
||||
final String[] pathParts = pathInfo.split("/");
|
||||
return pathParts[pathParts.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
+42
-37
@@ -100,50 +100,55 @@ public class ChargebeeWebHookHandler extends SubscriptionWebHookHandler {
|
||||
|| occuredAt.before(subscription.getManualUpdatedAt());
|
||||
}
|
||||
|
||||
private void processEvent(SubscriptionWebHookEvent event, User user) throws UserManagementException {
|
||||
private void processEvent(final SubscriptionWebHookEvent event, final User user) throws UserManagementException {
|
||||
final SubscriptionWebHookEventType eventType = event.getEventType();
|
||||
if (eventType != null) {
|
||||
logger.info(() -> "Start process webhook event \"" + eventType.getName() + "\" for user " + user.getName());
|
||||
final Subscription userSubscription = getCurrentUserSubscriptionFromEvent(user, event);
|
||||
switch (eventType) {
|
||||
case CUSTOMER_DELETED:
|
||||
updateUserSubscription(user, buildEmptySubscription(userSubscription, event));
|
||||
break;
|
||||
case SUBSCRIPTION_DELETED:
|
||||
if (userSubscription != null && userSubscription.getSubscriptionId() != null
|
||||
&& userSubscription.getSubscriptionId().equals(event.getSubscriptionId())) {
|
||||
lockSubscriptionsForUser(user);
|
||||
try {
|
||||
final Subscription userSubscription = getCurrentUserSubscriptionFromEvent(user, event);
|
||||
switch (eventType) {
|
||||
case CUSTOMER_DELETED:
|
||||
updateUserSubscription(user, buildEmptySubscription(userSubscription, event));
|
||||
}
|
||||
break;
|
||||
case SUBSCRIPTION_CREATED:
|
||||
case SUBSCRIPTION_CHANGED:
|
||||
case SUBSCRIPTION_ACTIVATED:
|
||||
case PAYMENT_SUCCEEDED:
|
||||
case PAYMENT_FAILED:
|
||||
case SUBSCRIPTION_PAUSED:
|
||||
case SUBSCRIPTION_RESUMED:
|
||||
case SUBSCRIPTION_CANCELLED:
|
||||
updateUserSubscription(user, buildSubscription(userSubscription, event));
|
||||
break;
|
||||
case PAYMENT_REFUNDED:
|
||||
if (userSubscription.getInvoiceId() != null
|
||||
&& userSubscription.getInvoiceId().equals(event.getInvoiceId())) {
|
||||
break;
|
||||
case SUBSCRIPTION_DELETED:
|
||||
if (userSubscription != null && userSubscription.getSubscriptionId() != null
|
||||
&& userSubscription.getSubscriptionId().equals(event.getSubscriptionId())) {
|
||||
updateUserSubscription(user, buildEmptySubscription(userSubscription, event));
|
||||
}
|
||||
break;
|
||||
case SUBSCRIPTION_CREATED:
|
||||
case SUBSCRIPTION_CHANGED:
|
||||
case SUBSCRIPTION_ACTIVATED:
|
||||
case PAYMENT_SUCCEEDED:
|
||||
case PAYMENT_FAILED:
|
||||
case SUBSCRIPTION_PAUSED:
|
||||
case SUBSCRIPTION_RESUMED:
|
||||
case SUBSCRIPTION_CANCELLED:
|
||||
updateUserSubscription(user, buildSubscription(userSubscription, event));
|
||||
}
|
||||
break;
|
||||
case INVOICE_GENERATED:
|
||||
updateSubscriptionInvoice(user, userSubscription, event);
|
||||
break;
|
||||
case INVOICE_UPDATED:
|
||||
if (userSubscription != null && userSubscription.getInvoiceId() != null
|
||||
&& userSubscription.getInvoiceId().equals(event.getInvoiceId())) {
|
||||
break;
|
||||
case PAYMENT_REFUNDED:
|
||||
if (userSubscription.getInvoiceId() != null
|
||||
&& userSubscription.getInvoiceId().equals(event.getInvoiceId())) {
|
||||
updateUserSubscription(user, buildSubscription(userSubscription, event));
|
||||
}
|
||||
break;
|
||||
case INVOICE_GENERATED:
|
||||
updateSubscriptionInvoice(user, userSubscription, event);
|
||||
break;
|
||||
case INVOICE_UPDATED:
|
||||
if (userSubscription != null && userSubscription.getInvoiceId() != null
|
||||
&& userSubscription.getInvoiceId().equals(event.getInvoiceId())) {
|
||||
updateSubscriptionInvoice(user, userSubscription, event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.warning(
|
||||
() -> "Webhook event type was unknown and will not be processed ");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.warning(
|
||||
() -> "Webhook event type was unknown and will not be processed ");
|
||||
break;
|
||||
} finally {
|
||||
unlockSubscriptionsForUser(user);
|
||||
}
|
||||
logger.info(() -> "Webhook event \"" + eventType.getName() + "\" has been processed for user "
|
||||
+ user.getName());
|
||||
|
||||
Reference in New Issue
Block a user