完成菜单权限添加和软件菜单改造
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package com.nanri.aiimage.common.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DistributedJobLockService {
|
||||
|
||||
private static final DefaultRedisScript<Long> RELEASE_SCRIPT = new DefaultRedisScript<>(
|
||||
"if redis.call('get', KEYS[1]) == ARGV[1] then "
|
||||
+ "return redis.call('del', KEYS[1]) "
|
||||
+ "else return 0 end",
|
||||
Long.class
|
||||
);
|
||||
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
private final String ownerPrefix;
|
||||
|
||||
public DistributedJobLockService(StringRedisTemplate stringRedisTemplate) {
|
||||
this.stringRedisTemplate = stringRedisTemplate;
|
||||
this.ownerPrefix = resolveOwnerPrefix();
|
||||
}
|
||||
|
||||
public LockHandle tryLock(String jobName, Duration ttl) {
|
||||
if (jobName == null || jobName.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
Duration actualTtl = (ttl == null || ttl.isNegative() || ttl.isZero()) ? Duration.ofMinutes(10) : ttl;
|
||||
String key = buildLockKey(jobName);
|
||||
String token = ownerPrefix + ":" + UUID.randomUUID();
|
||||
Boolean locked = stringRedisTemplate.opsForValue().setIfAbsent(key, token, actualTtl);
|
||||
if (!Boolean.TRUE.equals(locked)) {
|
||||
return null;
|
||||
}
|
||||
return new LockHandle(key, token, jobName);
|
||||
}
|
||||
|
||||
public final class LockHandle implements AutoCloseable {
|
||||
|
||||
private final String key;
|
||||
private final String token;
|
||||
private final String jobName;
|
||||
private boolean released;
|
||||
|
||||
private LockHandle(String key, String token, String jobName) {
|
||||
this.key = key;
|
||||
this.token = token;
|
||||
this.jobName = jobName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
released = true;
|
||||
try {
|
||||
stringRedisTemplate.execute(RELEASE_SCRIPT, Collections.singletonList(key), token);
|
||||
} catch (Exception ex) {
|
||||
log.warn("[job-lock] release failed jobName={} key={} msg={}", jobName, key, ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String buildLockKey(String jobName) {
|
||||
return "job-lock:" + jobName;
|
||||
}
|
||||
|
||||
private String resolveOwnerPrefix() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
} catch (Exception ignored) {
|
||||
return "unknown-host";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user