mirror of
https://github.com/LamGC/ContentGrabbingJi.git
synced 2025-07-03 05:47:26 +00:00
[Fix] Issue #1 修复了ImageCache对重复缓存请求的策略(忽略并返回)导致的后续处理发生NPE的问题;
[Update] ImageCache 更新了ImageCache, 将该部分单独分离到 ImageCacheStore; [Update] BotCommandProcess 适配新的ImageCache, 调整内容检查的时机以减少不必要的API访问;
This commit is contained in:
@ -28,9 +28,9 @@ public class ImageCacheHandler implements EventHandler {
|
||||
private final static Set<ImageCacheObject> cacheQueue = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void getImageToCache(ImageCacheObject event) {
|
||||
public void getImageToCache(ImageCacheObject event) throws Exception {
|
||||
if(cacheQueue.contains(event)) {
|
||||
log.debug("图片 {} 已存在相同缓存任务, 跳过.", event.getStoreFile().getName());
|
||||
log.warn("图片 {} 已存在相同缓存任务, 跳过.", event.getStoreFile().getName());
|
||||
return;
|
||||
} else {
|
||||
cacheQueue.add(event);
|
||||
@ -43,11 +43,11 @@ public class ImageCacheHandler implements EventHandler {
|
||||
try {
|
||||
if(!storeFile.exists() && !storeFile.createNewFile()) {
|
||||
log.error("无法创建文件(Path: {})", storeFile.getAbsolutePath());
|
||||
return;
|
||||
throw new IOException("Failed to create file");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("无法创建文件(Path: {})", storeFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
|
||||
HttpGet request = new HttpGet(event.getDownloadLink());
|
||||
@ -57,11 +57,11 @@ public class ImageCacheHandler implements EventHandler {
|
||||
response = httpClient.execute(request);
|
||||
} catch (IOException e) {
|
||||
log.error("Http请求时发生异常", e);
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
if(response.getStatusLine().getStatusCode() != 200) {
|
||||
log.warn("Http请求异常:{}", response.getStatusLine());
|
||||
return;
|
||||
throw new IOException("Http Response Error: " + response.getStatusLine());
|
||||
}
|
||||
|
||||
log.debug("正在下载...(Content-Length: {}KB)", response.getEntity().getContentLength() / 1024);
|
||||
@ -69,7 +69,7 @@ public class ImageCacheHandler implements EventHandler {
|
||||
IOUtils.copy(response.getEntity().getContent(), fos);
|
||||
} catch (IOException e) {
|
||||
log.error("下载图片时发生异常", e);
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
event.getImageCache().put(URLs.getResourceName(event.getDownloadLink()), storeFile);
|
||||
} finally {
|
||||
|
109
src/main/java/net/lamgc/cgj/bot/cache/ImageCacheStore.java
vendored
Normal file
109
src/main/java/net/lamgc/cgj/bot/cache/ImageCacheStore.java
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
package net.lamgc.cgj.bot.cache;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public final class ImageCacheStore {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(ImageCacheStore.class.getName());
|
||||
|
||||
private final static Map<ImageCacheObject, Task> cacheMap = new Hashtable<>();
|
||||
|
||||
private final static ThreadPoolExecutor imageCacheExecutor = new ThreadPoolExecutor(
|
||||
4, 6,
|
||||
30L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(100),
|
||||
new ThreadFactoryBuilder()
|
||||
.setNameFormat("ImageCacheThread-%d")
|
||||
.build()
|
||||
);
|
||||
|
||||
private final static ImageCacheHandler handler = new ImageCacheHandler();
|
||||
|
||||
private ImageCacheStore() {}
|
||||
|
||||
/**
|
||||
* 传递图片缓存任务, 并等待缓存完成.
|
||||
* @param cacheObject 缓存任务组
|
||||
*/
|
||||
public static void executeCacheRequest(ImageCacheObject cacheObject) throws InterruptedException {
|
||||
Task task = getTaskState(cacheObject);
|
||||
if(task.taskState.get() == TaskState.COMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean locked = false;
|
||||
try {
|
||||
if(task.taskState.get() == TaskState.COMPLETE) {
|
||||
return;
|
||||
}
|
||||
task.lock.lock();
|
||||
locked = true;
|
||||
// 双重检查
|
||||
if(task.taskState.get() == TaskState.COMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 置任务状态
|
||||
task.taskState.set(TaskState.RUNNING);
|
||||
|
||||
try {
|
||||
Throwable throwable = imageCacheExecutor.submit(() -> {
|
||||
try {
|
||||
handler.getImageToCache(cacheObject);
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}).get();
|
||||
|
||||
if(throwable == null) {
|
||||
task.taskState.set(TaskState.COMPLETE);
|
||||
} else {
|
||||
task.taskState.set(TaskState.ERROR);
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
log.error("执行图片缓存任务时发生异常", e);
|
||||
}
|
||||
} finally {
|
||||
if(locked) {
|
||||
task.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Task getTaskState(ImageCacheObject cacheObject) {
|
||||
if(!cacheMap.containsKey(cacheObject)) {
|
||||
cacheMap.put(cacheObject, new Task());
|
||||
}
|
||||
return cacheMap.get(cacheObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
private enum TaskState {
|
||||
READY, RUNNING, COMPLETE, ERROR
|
||||
}
|
||||
|
||||
private static class Task {
|
||||
|
||||
public final ReentrantLock lock = new ReentrantLock(true);
|
||||
|
||||
public final AtomicReference<TaskState> taskState = new AtomicReference<>(TaskState.READY);
|
||||
|
||||
public final Condition condition = lock.newCondition();
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user