@
Log@
RestController@
SpringBootApplicationpublic class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
static final String CREATED = "create";
static final String PROCESS = "process";
static final String COMPLETE = "complete";
@
PostMapping("generate")
public ResponseEntity<Response> generate(@RequestBody Request request) {
return ResponseEntity.ok(generate(request.input, request.taskId));
}
@
Autowired private RedisTemplate<Object, Object> redisTemplate;
@
Autowired private ThreadPoolTaskExecutor executor;
@
PostConstruct public void init() {
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
}
Function<UUID, String> valKeyFunc = uuid -> "value::" + uuid;
Duration expire = Duration.ofMinutes(30L);
public Response generate(Integer input, UUID taskId) {
if (taskId == null) {
check(input != null, "请输入值");
UUID uuid = createTask(input);
return new Response(CREATED, null, uuid, expire.getSeconds());
}
String key = valKeyFunc.apply(taskId);
Long expire = redisTemplate.getExpire(key);
Entity value;
try {
value = (Entity) redisTemplate.opsForValue().get(key);
} catch (ClassCastException e) {
log.warning(e.getMessage());
e.printStackTrace();
throw new RuntimeException("服务器内部错误");
}
check(value != null, "任务 " + taskId + " 不存在或者已经过期");
assert value != null;
check(value.complete != null, "服务器内部错误");
if (!value.complete) {
return new Response(PROCESS, null, taskId, expire);
}
return new Response(COMPLETE, value, taskId, expire);
}
private static void check(Boolean condition, String msg) {
if (!Boolean.TRUE.equals(condition)) {
throw new RuntimeException(msg);
}
}
private UUID createTask(Integer input) {
UUID uuid = UUID.randomUUID();
executor.execute(() -> {
try {
Entity entity = new Entity(uuid, false, new Date(), null, input, null);
log.info(String.format("begin task: %s, input: %s", uuid, input));
String key = valKeyFunc.apply(uuid);
redisTemplate.opsForValue().set(key, entity, expire);
log.info(String.format("set task: %s, input: %s, key: %s", uuid, input, key));
TimeUnit.SECONDS.sleep(RandomUtil.randomInt(10, 20));
String value = RandomUtil.randomString(Math.abs(input));
entity.complete = true;
entity.completeTime = new Date();
entity.output = value;
log.info(String.format("end task: %s, input: %s, generated: %s", uuid, input, value));
redisTemplate.opsForValue().set(key, entity, expire);
} catch (InterruptedException e) {
log.warning(e.getMessage());
e.printStackTrace();
}
});
return uuid;
}
@
Data static class Request {
Integer input;
UUID taskId;
}
@
AllArgsConstructor @
NoArgsConstructor @
Data static class Response {
String status;
Object data;
UUID taskId;
Long expire;
}
@
Data @
AllArgsConstructor @
NoArgsConstructor static class Entity {
UUID taskId;
Boolean complete;
Date beginTime;
Date completeTime;
Integer input;
String output;
}
}