先保存下载任务再下发节点以保留即时状态

This commit is contained in:
root
2026-09-08 09:19:47 +08:00
parent 3c8be3e7c9
commit f65c5ad860
3 changed files with 69 additions and 15 deletions
@@ -16,6 +16,9 @@ public interface CustomConfigurationMapper {
// @Delete("delete from customConfiguration where parameter=#{parameter}")
// void deleteConfiguration(CustomConfiguration configuration);
@Update("update customConfiguration set value=cast(value as integer)+#{amount} where parameter=#{parameter}")
void incrementConfiguration(@Param("parameter") String parameter, @Param("amount") long amount);
@Select("select * from customConfiguration where parameter=#{parameter}")
CustomConfiguration selectConfiguration(String parameter);
}
@@ -93,9 +93,14 @@ public class GalleryManageService {
} else {
taskName = gallery.getName();
log.info("创建任务: {} 目标分辨率:{}", link, targetResolution);
// Persist before dispatch: the node sends its current status before its ACK.
gallery.setDownloader(user.getId());
gallery.set_download(true);
galleryMapper.insertGallery(gallery);
configurationMapper.incrementConfiguration(CustomConfiguration.WEEK_USED_AMOUNT, gallery.getFileSize());
if (remoteService.addGalleryToQueue(gallery) != 0) {
log.error("传送任务{}失败, 未知原因", gallery.getName());
response.failure("任务传送失败,未知原因,尝试点击重连按钮看看");
response.failure("任务已保存,但节点未确认接收;请刷新任务列表后重试");
pushService.taskCreateReport(user.getUsername(), taskName, response);
return response.toJSONString();
}
@@ -111,20 +116,9 @@ public class GalleryManageService {
return response.toJSONString();
}
//处理下载结果,将任务插入数据库并且更新每周用量
if (gallery.getStatus().equals("已提交")) {
response.success(gallery.toString());
gallery.setDownloader(user.getId());
gallery.set_download(true);
galleryMapper.insertGallery(gallery);
long usedAmount = Long.parseLong(configurationMapper.selectConfiguration(CustomConfiguration.WEEK_USED_AMOUNT).getValue());
usedAmount += gallery.getFileSize();
configurationMapper.updateConfiguration(CustomConfiguration.WEEK_USED_AMOUNT, String.valueOf(usedAmount));
} else {
response.failure("提交失败,未知原因");
galleryMapper.deleteGalleryByGid(gallery.getGid());
}
// Do not overwrite an immediate node status with the original submitted state.
Gallery current = galleryMapper.selectGalleryByGid(gallery.getGid());
response.success((current == null ? gallery : current).toString());
pushService.taskCreateReport(user.getUsername(), taskName, response);
return response.toJSONString();
@@ -0,0 +1,57 @@
package com.lion.lionwebsite.Service;
import com.lion.lionwebsite.Dao.normal.*;
import com.lion.lionwebsite.Dao.cache.ImageCacheMapper;
import com.lion.lionwebsite.Domain.*;
import com.lion.lionwebsite.Util.GalleryUtil;
import org.junit.jupiter.api.Test;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class GallerySubmissionTest {
@Test
void immediateCompletionSeesPersistedTask() throws Exception {
checkSubmission((byte) 0);
}
@Test
void timeoutRetainsTaskForRetry() throws Exception {
checkSubmission((byte) -1);
}
private void checkSubmission(byte ack) throws Exception {
GalleryMapper galleries = mock(GalleryMapper.class);
UserMapper users = mock(UserMapper.class);
RemoteService remote = mock(RemoteService.class);
CustomConfigurationMapper configuration = mock(CustomConfigurationMapper.class);
GalleryManageService service = new GalleryManageService(galleries, mock(CollectMapper.class), configuration,
users, mock(ShareFileMapper.class), mock(ImageCacheMapper.class), remote, mock(PushService.class));
User user = new User();
user.setId(7);
user.setUsername("test");
when(users.selectUserByAuthCode("test")).thenReturn(user);
AtomicReference<Gallery> saved = new AtomicReference<>();
when(galleries.selectGalleryByGid(123)).thenAnswer(call -> saved.get());
doAnswer(call -> { saved.set(call.getArgument(0)); return null; }).when(galleries).insertGallery(any());
Gallery gallery = new Gallery();
gallery.setGid(123);
gallery.setName("sample [123]");
gallery.setStatus("已提交");
when(remote.addGalleryToQueue(any())).thenAnswer(call -> {
assertNotNull(saved.get(), "node status must find a persisted record");
assertEquals(7, saved.get().getDownloader());
if (ack == 0) saved.get().setStatus("下载完成");
return ack;
});
try (var parser = mockStatic(GalleryUtil.class)) {
parser.when(() -> GalleryUtil.parse("https://example.org/g/123/key/", true, "original")).thenReturn(gallery);
String response = service.createTask("https://example.org/g/123/key/", "original", "test");
assertNotNull(saved.get());
assertTrue(response.contains(ack == 0 ? "success" : "任务已保存"));
assertEquals(ack == 0 ? "下载完成" : "已提交", saved.get().getStatus());
verify(galleries, never()).deleteGalleryByGid(any());
verify(galleries, times(1)).insertGallery(gallery);
}
}
}