feat: initialize school default tasks asynchronously

main
chenyuan 1 month ago
parent a20905f638
commit b760a5cfee

@ -7,6 +7,7 @@ import com.sztzjy.linkCommerce.config.security.TokenProvider;
import com.sztzjy.linkCommerce.entity.*;
import com.sztzjy.linkCommerce.mapper.*;
import com.sztzjy.linkCommerce.service.PlatformAdminService;
import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService;
import com.sztzjy.linkCommerce.service.SchoolProductConfigService;
import com.sztzjy.linkCommerce.service.UserInfoService;
import com.sztzjy.linkCommerce.util.ResultEntity;
@ -31,6 +32,8 @@ public class PlatformAdminController {
@Autowired
private SchoolProductConfigService schoolProductConfigService;
@Autowired
private SchoolDefaultTaskService schoolDefaultTaskService;
@Autowired
private UserInfoService userInfoService;
@Autowired
private SchoolMapper schoolMapper;
@ -84,6 +87,7 @@ public class PlatformAdminController {
int count = schoolMapper.insertSelective(school);
if (count > 0) {
schoolProductConfigService.createDefaultConfig(school.getSchoolId());
schoolDefaultTaskService.enqueueInitialization(school.getSchoolId());
}
return writeResult(count, "新增成功", "新增失败");
}

@ -14,6 +14,8 @@ public interface SchoolDefaultTaskService {
SchoolDefaultTaskInitialization getInitialization(String schoolId);
void enqueueInitialization(String schoolId);
void replaceSchoolDefault(String schoolId, List<TaskAllocation> tasks);
void initializeSchoolDefault(String schoolId);

@ -10,6 +10,8 @@ import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Service;
import java.util.Collections;
@ -27,6 +29,9 @@ public class SchoolDefaultTaskServiceImpl implements SchoolDefaultTaskService {
SchoolClassMapper schoolClassMapper;
@Autowired(required = false)
SchoolDefaultTaskInitializationMapper initializationMapper;
@Autowired(required = false)
@Qualifier("asyncTaskExecutor")
AsyncTaskExecutor taskExecutor;
public static String schoolDefaultClassId(String schoolId) {
return SCHOOL_DEFAULT_PREFIX + schoolId;
@ -62,6 +67,24 @@ public class SchoolDefaultTaskServiceImpl implements SchoolDefaultTaskService {
? null : initializationMapper.selectByPrimaryKey(schoolId);
}
@Override
public void enqueueInitialization(String schoolId) {
if (StringUtils.isBlank(schoolId)) {
throw new IllegalArgumentException("学校不能为空");
}
markPending(schoolId);
if (taskExecutor == null) {
initializeInBackground(schoolId);
return;
}
try {
taskExecutor.execute(() -> initializeInBackground(schoolId));
} catch (RuntimeException ex) {
markFailed(schoolId, ex);
throw ex;
}
}
@Override
public void replaceSchoolDefault(String schoolId, List<TaskAllocation> tasks) {
if (StringUtils.isBlank(schoolId)) {
@ -82,9 +105,13 @@ public class SchoolDefaultTaskServiceImpl implements SchoolDefaultTaskService {
@Override
public void initializeSchoolDefault(String schoolId) {
if (StringUtils.isBlank(schoolId) || hasSchoolDefault(schoolId)) {
markReady(schoolId);
return;
}
List<TaskAllocation> platformTasks = listByClassId(PLATFORM_DEFAULT_CLASS_ID);
if (platformTasks.isEmpty()) {
throw new IllegalStateException("平台基线实训任务为空");
}
for (TaskAllocation source : platformTasks) {
TaskAllocation copy = new TaskAllocation();
copy.setId(UUID.randomUUID().toString());
@ -98,6 +125,15 @@ public class SchoolDefaultTaskServiceImpl implements SchoolDefaultTaskService {
markReady(schoolId);
}
private void initializeInBackground(String schoolId) {
markRunning(schoolId);
try {
initializeSchoolDefault(schoolId);
} catch (RuntimeException ex) {
markFailed(schoolId, ex);
}
}
private boolean hasSchoolDefault(String schoolId) {
TaskAllocationExample example = new TaskAllocationExample();
example.createCriteria().andClassIdEqualTo(schoolDefaultClassId(schoolId));
@ -116,12 +152,49 @@ public class SchoolDefaultTaskServiceImpl implements SchoolDefaultTaskService {
}
private void markReady(String schoolId) {
updateInitialization(schoolId, "READY", null);
}
private void markPending(String schoolId) {
if (initializationMapper == null) {
return;
}
SchoolDefaultTaskInitialization existing = initializationMapper.selectByPrimaryKey(schoolId);
Date now = new Date();
if (existing == null) {
SchoolDefaultTaskInitialization record = new SchoolDefaultTaskInitialization();
record.setSchoolId(schoolId);
record.setStatus("PENDING");
record.setAttemptCount(1);
record.setCreateTime(now);
record.setUpdateTime(now);
initializationMapper.insert(record);
return;
}
SchoolDefaultTaskInitialization record = new SchoolDefaultTaskInitialization();
record.setSchoolId(schoolId);
record.setStatus("PENDING");
record.setAttemptCount((existing.getAttemptCount() == null ? 0 : existing.getAttemptCount()) + 1);
record.setUpdateTime(now);
initializationMapper.updateByPrimaryKeySelective(record);
}
private void markRunning(String schoolId) {
updateInitialization(schoolId, "RUNNING", null);
}
private void markFailed(String schoolId, RuntimeException ex) {
updateInitialization(schoolId, "FAILED", StringUtils.abbreviate(ex.getMessage(), 1000));
}
private void updateInitialization(String schoolId, String status, String error) {
if (initializationMapper == null || StringUtils.isBlank(schoolId)) {
return;
}
SchoolDefaultTaskInitialization record = new SchoolDefaultTaskInitialization();
record.setSchoolId(schoolId);
record.setStatus("READY");
record.setStatus(status);
record.setLastError(error);
record.setUpdateTime(new Date());
initializationMapper.updateByPrimaryKeySelective(record);
}

@ -0,0 +1,50 @@
package com.sztzjy.linkCommerce.controller.platformadmin;
import com.sztzjy.linkCommerce.config.security.JwtUser;
import com.sztzjy.linkCommerce.config.security.TokenProvider;
import com.sztzjy.linkCommerce.entity.School;
import com.sztzjy.linkCommerce.mapper.SchoolMapper;
import com.sztzjy.linkCommerce.service.PlatformAdminService;
import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService;
import com.sztzjy.linkCommerce.service.SchoolProductConfigService;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.util.ReflectionTestUtils;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
class PlatformAdminControllerDefaultTaskTest {
@Test
void queuesDefaultTaskInitializationAfterSchoolCreationSucceeds() {
PlatformAdminController controller = new PlatformAdminController();
PlatformAdminService platformAdminService = mock(PlatformAdminService.class);
SchoolProductConfigService configService = mock(SchoolProductConfigService.class);
SchoolDefaultTaskService defaultTaskService = mock(SchoolDefaultTaskService.class);
SchoolMapper schoolMapper = mock(SchoolMapper.class);
ReflectionTestUtils.setField(controller, "platformAdminService", platformAdminService);
ReflectionTestUtils.setField(controller, "schoolProductConfigService", configService);
ReflectionTestUtils.setField(controller, "schoolDefaultTaskService", defaultTaskService);
ReflectionTestUtils.setField(controller, "schoolMapper", schoolMapper);
when(schoolMapper.insertSelective(any())).thenReturn(1);
School school = new School();
school.setSchoolName("异步初始化学校");
controller.addSchool(school, platformAdminRequest());
verify(defaultTaskService).enqueueInitialization(school.getSchoolId());
}
private MockHttpServletRequest platformAdminRequest() {
JwtUser user = new JwtUser();
user.setUserId("platform-1");
user.setRoleId(1);
user.setUsername("platform-admin");
MockHttpServletRequest request = new MockHttpServletRequest();
request.setUserPrincipal(new UsernamePasswordAuthenticationToken(user, null));
request.addHeader("Authorization", "Bearer " + TokenProvider.createToken(user));
return request;
}
}

@ -3,9 +3,11 @@ package com.sztzjy.linkCommerce.service.impl;
import com.sztzjy.linkCommerce.entity.SchoolClass;
import com.sztzjy.linkCommerce.entity.TaskAllocation;
import com.sztzjy.linkCommerce.mapper.SchoolClassMapper;
import com.sztzjy.linkCommerce.mapper.SchoolDefaultTaskInitializationMapper;
import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.core.task.AsyncTaskExecutor;
import java.util.Collections;
import java.util.List;
@ -50,6 +52,22 @@ class SchoolDefaultTaskServiceImplTest {
verify(taskMapper, never()).insert(any());
}
@Test
void enqueueInitializationRecordsPendingStateBeforeSubmittingBackgroundWork() {
TaskAllocationMapper taskMapper = mock(TaskAllocationMapper.class);
SchoolDefaultTaskInitializationMapper statusMapper = mock(SchoolDefaultTaskInitializationMapper.class);
AsyncTaskExecutor executor = mock(AsyncTaskExecutor.class);
SchoolDefaultTaskServiceImpl service = new SchoolDefaultTaskServiceImpl();
ReflectionTestUtils.setField(service, "taskAllocationMapper", taskMapper);
ReflectionTestUtils.setField(service, "initializationMapper", statusMapper);
ReflectionTestUtils.setField(service, "taskExecutor", executor);
service.enqueueInitialization("school-1");
verify(statusMapper).insert(argThat(row -> "school-1".equals(row.getSchoolId()) && "PENDING".equals(row.getStatus())));
verify(executor).execute(any(Runnable.class));
}
private TaskAllocation task(String module) {
TaskAllocation task = new TaskAllocation();
task.setModule(module);

Loading…
Cancel
Save