[AB-xxx] adding locking mechanism for role assignments to work around discord lack of role update locking

This commit is contained in:
Sheldan
2024-04-04 22:54:18 +02:00
parent bff505ef25
commit 82be86e086
3 changed files with 97 additions and 9 deletions

View File

@@ -1,10 +1,7 @@
package dev.sheldan.abstracto.core.models;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.*;
import net.dv8tion.jda.api.entities.Member;
import java.io.Serializable;
@@ -12,10 +9,12 @@ import java.io.Serializable;
@Getter
@Setter
@Builder
@ToString
@EqualsAndHashCode
public class ServerUser implements Serializable {
private Long serverId;
private Long userId;
@EqualsAndHashCode.Exclude
private Boolean isBot;
public static ServerUser fromAUserInAServer(AUserInAServer aUserInAServer) {

View File

@@ -0,0 +1,43 @@
package dev.sheldan.abstracto.core.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
@Component
@Slf4j
// https://www.baeldung.com/java-acquire-lock-by-key
public class LockByKeyService<Key> {
private static class LockWrapper {
private final Semaphore lock = new Semaphore(1);
private final AtomicInteger numberOfThreadsInQueue = new AtomicInteger(1);
private LockWrapper addThreadInQueue() {
numberOfThreadsInQueue.incrementAndGet();
return this;
}
private int removeThreadFromQueue() {
return numberOfThreadsInQueue.decrementAndGet();
}
}
private final ConcurrentHashMap<Key, LockWrapper> locks = new ConcurrentHashMap<>();
public void lock(Key key) throws InterruptedException {
LockWrapper lockWrapper = locks.compute(key, (k, v) -> v == null ? new LockWrapper() : v.addThreadInQueue());
lockWrapper.lock.acquire();
}
public void unlock(Key key) {
LockWrapper lockWrapper = locks.get(key);
lockWrapper.lock.release();
if (lockWrapper.removeThreadFromQueue() == 0) {
locks.remove(key, lockWrapper);
}
}
}