diff --git a/pom.xml b/pom.xml index 5aac308..89b75f6 100644 --- a/pom.xml +++ b/pom.xml @@ -51,14 +51,25 @@ org.springframework.boot spring-boot-starter-jdbc - + org.springframework.boot spring-boot-starter-data-redis + + org.hibernate + hibernate-core + 6.4.5.Final + + + org.jboss.logging + jboss-logging + + + @@ -122,6 +133,81 @@ 3.0.4 test + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + + + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.kafka + spring-kafka + 3.2.4 + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.4 + + + org.apache.commons + commons-lang3 + 3.17.0 + + + org.mapstruct + mapstruct + 1.5.5.Final + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.7 + + + org.springframework.boot + spring-boot-starter-redis + 1.4.7.RELEASE + + + org.springframework.boot + spring-boot-starter-data-redis + 3.2.0 + + + com.mysql + mysql-connector-j + + + org.springframework.boot + spring-boot-starter-actuator + + + com.baomidou + mybatis-plus-generator + 3.5.6 + + + com.baomidou + mybatis-plus-boot-starter + 3.5.6 + + + com.fasterxml.jackson.core + jackson-databind + @@ -154,6 +240,28 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.mapstruct + mapstruct-processor + 1.5.5.Final + + + + + + + src/main/resources + + **/*.xml + **/*.properties + + + \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheInitTask.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheInitTask.java new file mode 100644 index 0000000..f494fa8 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheInitTask.java @@ -0,0 +1,37 @@ +package com.bipt.intelligentapplicationorchestrationservice.cache; + +import com.bipt.intelligentapplicationorchestrationservice.service.CacheManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +public class CacheInitTask { + + private final CacheManager cacheManager; + + @Value("${cache.init-batch-size:500}") + private int batchSize; + + @Autowired + public CacheInitTask(CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + /** + * 应用启动后执行全量缓存加载 + * 使用@EventListener替代@PostConstruct确保数据库连接就绪 + */ + @EventListener(ApplicationReadyEvent.class) + public void initCacheOnStartup() { + try { + cacheManager.loadFullCache(batchSize); + System.out.println("✅ 缓存全量初始化完成 | Total loaded: " + cacheManager.getCacheCount()); + } catch (Exception e) { + System.err.println("❌ 缓存初始化失败: " + e.getMessage()); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java new file mode 100644 index 0000000..40c2de2 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java @@ -0,0 +1,63 @@ +package com.bipt.intelligentapplicationorchestrationservice.cache; + +import com.bipt.intelligentapplicationorchestrationservice.service.CacheManager; +import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuResourceDao; +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import java.time.LocalDateTime; +import java.util.List; + +//@Slf4j +@Component +public class CacheSyncTask { + private final GpuResourceDao gpuResourceDao; + private final CacheManager cacheManager; + private LocalDateTime lastSyncTime = LocalDateTime.MIN; + private static final Logger log = LoggerFactory.getLogger(CacheSyncTask.class); + + @Autowired + public CacheSyncTask(GpuResourceDao gpuResourceDao, CacheManager cacheManager) { + this.gpuResourceDao = gpuResourceDao; + this.cacheManager = cacheManager; + } + + /** + * 定时同步缓存(默认每10分钟) + */ + @Scheduled(fixedDelayString = "${cache.sync-interval:600000}") + public void syncCache() { + try { + LocalDateTime currentSyncTime = LocalDateTime.now(); + log.info("🔄 开始缓存同步 | 时间范围: {} - {}", lastSyncTime, currentSyncTime); + + // 1. 查询增量数据 + List modifiedGpus = gpuResourceDao.findModifiedSince(lastSyncTime); + if (modifiedGpus.isEmpty()) { + log.info("✅ 无数据变更,跳过本次同步"); + return; + } + + // 2. 处理数据变更 + modifiedGpus.forEach(gpu -> { + if (gpu.getIsDeleted()) { + cacheManager.evictCache(gpu.getGPUId()); + log.debug("🗑️ 删除缓存 | GPU ID: {}", gpu.getGPUId()); + } else { + cacheManager.refreshCache(gpu.getGPUId()); + log.debug("🔄 更新缓存 | GPU ID: {}", gpu.getGPUId()); + } + }); + + // 3. 更新同步时间戳 + lastSyncTime = currentSyncTime; + log.info("✅ 缓存同步完成 | 共处理 {} 条记录", modifiedGpus.size()); + + } catch (Exception e) { + log.error("❌ 缓存同步失败: {}", e.getMessage(), e); + } + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java new file mode 100644 index 0000000..7a9c410 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java @@ -0,0 +1,48 @@ +package com.bipt.intelligentapplicationorchestrationservice.config; + + +import com.bipt.intelligentapplicationorchestrationservice.service.CacheManager; +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +@Aspect +@Component +public class CacheAopConfig { + private final CacheManager cacheManager; + + public CacheAopConfig(CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + // 定义写操作切点 + @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional) && " + + "execution(* com.bipt.intelligentapplicationorchestrationservice.service..*.*(..))") + public void writeOperation() {} + + // 事务提交后操作 + @AfterReturning(pointcut = "writeOperation()", returning = "result") + public void afterWriteCommit(JoinPoint joinPoint, Object result) { + TransactionSynchronizationManager.registerSynchronization( + new TransactionSynchronization() { + @Override + public void afterCommit() { + processCacheUpdate(result); + } + }); + } + + private void processCacheUpdate(Object result) { + if (result instanceof GpuResource) { + GpuResource gpu = (GpuResource) result; + cacheManager.refreshCache(gpu.getGPUId()); + } else if (result instanceof Long) { // 处理删除操作返回ID的情况 + cacheManager.evictCache((Long) result); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java new file mode 100644 index 0000000..95ef6cb --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java @@ -0,0 +1,88 @@ +package com.bipt.intelligentapplicationorchestrationservice.config; + +import io.lettuce.core.ClientOptions; +import io.lettuce.core.SocketOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +@Configuration +public class RedisConfig { + @Value("${spring.data.redis.host}") + private String redisHost; + + @Value("${spring.data.redis.port}") + private int redisPort; + + @Value("${spring.data.redis.username}") + private String redisUsername; + + @Value("${spring.data.redis.password}") + private String redisPassword; + + @Value("${spring.data.redis.ssl:false}") + private boolean useSsl; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + // 1. 创建 SocketOptions + SocketOptions socketOptions = SocketOptions.builder() + .connectTimeout(Duration.ofSeconds(15)) // 连接超时 + .keepAlive(true) // 启用 TCP Keep-Alive + .build(); + + // 2. 构建 ClientOptions + ClientOptions clientOptions = ClientOptions.builder() + .socketOptions(socketOptions) + .autoReconnect(true) // 启用自动重连 + .build(); + + // 3. 集成到 Lettuce 配置 + LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() + .clientOptions(clientOptions) // 注入 ClientOptions + .commandTimeout(Duration.ofSeconds(30)) // 全局命令超时 + .build(); + RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); + config.setHostName(redisHost); + config.setPort(redisPort); + config.setUsername(redisUsername); // Redis 6.0+ 支持用户名 + config.setPassword(RedisPassword.of(redisPassword)); + +// LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() +// .commandTimeout(Duration.ofSeconds(30)) // 增加命令超时 +// .socketOptions(SocketOptions.builder() +// .connectTimeout(Duration.ofSeconds(15)) // TCP连接超时 +// .build()) +// .build(); + + return new LettuceConnectionFactory(config, clientConfig); + } + + +// @Bean +// public RedisConnectionFactory redisConnectionFactory() { +// RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); +// config.setPassword(""); +// return new LettuceConnectionFactory(config); +// } + + @Bean + public RedisTemplate redisTemplate(){ + RedisTemplate template = new RedisTemplate<>(); + //RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(redisConnectionFactory()); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + return template; + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java new file mode 100644 index 0000000..507cde1 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java @@ -0,0 +1,48 @@ +package com.bipt.intelligentapplicationorchestrationservice.controller; + +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import com.bipt.intelligentapplicationorchestrationservice.service.GpuManageService; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping +public class GpuResourceController { + @Autowired + private GpuManageService gpuManageService; + + @PostMapping + public ResponseVO addGpu(@Valid @RequestBody GpuCreateDTO dto){ + return gpuManageService.createGpuResource(dto); + } + + @DeleteMapping("/{gpuId}") + public ResponseVO removeGpu(@PathVariable("gpuId") Long gpuId){ + return gpuManageService.deleteGpuResource(gpuId); + } + + @PutMapping("/{gpuId}") + public void updateGpuResource( + @PathVariable Long gpuId, + @Valid @RequestBody GpuUpdateDTO dto){ + dto.setGPUId(gpuId); + gpuManageService.updateGpuResource(dto); + } + + @GetMapping("/search") + public ResponseVO> searchGpuResources( + @RequestParam(required = false) String model, + @RequestParam(required = false) Integer memorySize, + @RequestParam(required = false) String ip){ + + List resources = gpuManageService.searchByCriteria(model, memorySize,ip); + + return ResponseVO.success(resources); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/deployment/ResourceAllocator.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/deployment/ResourceAllocator.java new file mode 100644 index 0000000..ec05ce7 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/deployment/ResourceAllocator.java @@ -0,0 +1,73 @@ +package com.bipt.intelligentapplicationorchestrationservice.deploy.deployment; + +import com.bipt.intelligentapplicationorchestrationservice.deploy.entity.DeploymentResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.utils.ConfigConstants; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.ResourceAccessException; + +import java.util.Comparator; +import java.util.List; + +@Component +public class ResourceAllocator { + + @Autowired + private ConfigConstants config; + + //获取剩余内存 + private int getRemainingMemory(GpuResource resource){ + return resource.getGPUMaxMemory()-resource.getGPUMemorySize(); + } + + public DeploymentResource allocate( + List resources, + int requiredMemory, + String modelId, + boolean isGray + ){ + resources.sort(Comparator.comparingInt(GpuResource::getGPUMemorySize)); + + //第一轮分配 + for(GpuResource resource:resources){ + if(getRemainingMemory(resource) >= requiredMemory) { + return createResource(resource, modelId, isGray); + } + } + + //第二轮分配 + return defragmentation(resources,requiredMemory, modelId, isGray); + } + + + private DeploymentResource defragmentation( + List resources, + int requiredMemory, + String modelId, + boolean isGray + ){ + //按内存碎片大小排序(最小碎片优先) + resources.sort(Comparator.comparingDouble( + r -> (double)getRemainingMemory(r) / r.getGPUMaxMemory())); + + for(GpuResource resource:resources){ + if(getRemainingMemory(resource) >= requiredMemory){ + return createResource(resource, modelId, isGray); + } + } + throw new ResourceAccessException("GPU资源不足"); + } + + private DeploymentResource createResource(GpuResource gpu, String modelId, boolean isGray){ + String urlType = isGray ? "gray":"prod"; + String url = String.format( + config.URL_TEMPLATE, + gpu.getIp(), + config.MODEL_PORT, + modelId, + urlType + ); + return new DeploymentResource(gpu, url); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployRequest.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployRequest.java new file mode 100644 index 0000000..b7a4282 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployRequest.java @@ -0,0 +1,4 @@ +package com.bipt.intelligentapplicationorchestrationservice.deploy.entity; + +public class DeployRequest { +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployResponse.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployResponse.java new file mode 100644 index 0000000..28a9481 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployResponse.java @@ -0,0 +1,25 @@ +package com.bipt.intelligentapplicationorchestrationservice.deploy.entity; + +public class DeployResponse { + private boolean isSuccess; + private String errorInfo; + private int status; + private T data; + + public DeployResponse(boolean b, String s, int i, T data) { + isSuccess = b; + errorInfo = s; + status = i; + this.data = data; + } + + // 成功响应 + public static DeployResponse success(T data) { + return new DeployResponse<>(true, "", 200, data); + } + + // 失败响应 + public static DeployResponse fail(int status, String error) { + return new DeployResponse<>(false, error, status, null); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java new file mode 100644 index 0000000..08935ef --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java @@ -0,0 +1,12 @@ +package com.bipt.intelligentapplicationorchestrationservice.deploy.entity; + +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DeploymentResource { + private final GpuResource gpu; + private final String url; +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuCreateDTO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuCreateDTO.java new file mode 100644 index 0000000..48b901e --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuCreateDTO.java @@ -0,0 +1,27 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.*; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Getter +public class GpuCreateDTO { + @NotBlank(message = "GPU型号不能为空") + @Pattern(regexp = "^([A-Z][A-Z0-9-]+)-\\w+", + message = "型号格式应为 [厂商(大写字母开头)]-[型号],如 Intel-Xe_GPU") + private String GPUModel; + + @NotNull(message = "显存容量不能为空") + private Integer GPUMemorySize; + + @NotBlank(message = "IP地址不能为空") + @Pattern(regexp = "^\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}$", + message = "IP地址格式无效") + private String Ip; + +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuResponseDTO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuResponseDTO.java new file mode 100644 index 0000000..66312b4 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuResponseDTO.java @@ -0,0 +1,57 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class GpuResponseDTO { + private Long id; + private String GPUModel; + private Integer GPUMemorySize; + private String Ip; + private LocalDateTime createTime; + // Builder类 + public static class Builder { + private Long id; + private String model; + private Integer memory; + private String ip; + private LocalDateTime createdTime; + + public Builder id(Long id) { + this.id = id; + return this; + } + + public Builder model(String model) { + this.model = model; + return this; + } + + public Builder memory(Integer memory) { + this.memory = memory; + return this; + } + + public Builder ip(String ip) { + this.ip = ip; + return this; + } + + public Builder createdTime(LocalDateTime createdTime) { + this.createdTime = createdTime; + return this; + } + public GpuResponseDTO build() { + // 必填字段校验(如网页2的推荐) + if (id == null) { + throw new IllegalArgumentException("GPU ID必须填写"); + } + return new GpuResponseDTO(); + } + } + public String getCreateTimeStr(){ + return "GPU创建时间:" + createTime.toString(); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuUpdateDTO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuUpdateDTO.java new file mode 100644 index 0000000..3ca1dbc --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuUpdateDTO.java @@ -0,0 +1,44 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity.dto; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.*; + +@Data +@AllArgsConstructor +@NoArgsConstructor +//@Setter +//@Getter +public class GpuUpdateDTO { + public @NotNull(message = "GPU ID cannot be null") Long getGPUId() { + return GPUId; + } + + public void setGPUId(@NotNull(message = "GPU ID cannot be null") Long GPUId) { + this.GPUId = GPUId; + } + + public void setGPUModel(@Pattern(regexp = "^([A-Z][A-Z0-9-]+)-\\w+", + message = "型号格式应为 [厂商(大写字母开头)]-[型号],如 Intel-Xe_GPU") String GPUModel) { + this.GPUModel = GPUModel; + } + + public void setIp(@Pattern(regexp = "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$", + message = "IP地址格式无效") String ip) { + Ip = ip; + } + + @NotNull(message = "GPU ID cannot be null") + private Long GPUId; + + @Pattern(regexp = "^([A-Z][A-Z0-9-]+)-\\w+", + message = "型号格式应为 [厂商(大写字母开头)]-[型号],如 Intel-Xe_GPU") + private String GPUModel; + + @Setter + private Integer GPUMemorySize; + + @Pattern(regexp = "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$", + message = "IP地址格式无效") + private String Ip; +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/entity/GpuResource.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/entity/GpuResource.java new file mode 100644 index 0000000..c1e5802 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/entity/GpuResource.java @@ -0,0 +1,96 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Setter +@Data +public class GpuResource { + @Getter + @TableField("GPUId") + private Long GPUId; + + @Getter + @TableField("GPUModel") + private String GPUModel; + + @Getter + @TableField("GPUMemorySize") + private Integer GPUMemorySize; + + @TableField("is_deleted") + private Integer isDeleted = 0; + + @TableField("Ip") + private String Ip; + + @Getter + @TableField("CreatedTime") + private LocalDateTime CreateTime; + + @Getter + @TableField("update_time") + private LocalDateTime UpdateTime; + + @Getter + @TableField("GPUMaxMemory") + private Integer GPUMaxMemory; + + public GpuResource(long l, String s, boolean b) { + this.GPUId = l; + this.GPUModel = s; + this.isDeleted = b ? 1 : 0; + } +// public @Pattern(regexp = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$") String getIp() { +// return Ip; +// } + + public Boolean getIsDeleted() { + return isDeleted != 0; + } + + + + public GpuResource(Long Id, String Model, Integer MemorySize, String ip, LocalDateTime create_time) { + this.GPUId = Id; + this.GPUModel = Model; + this.GPUMemorySize = MemorySize; + this.Ip = ip; + this.CreateTime = create_time; + } + + public GpuResource() {} + +// public void setGPUId(Long GPUId) { +// this.GPUId = GPUId; +// } +// +// public void setGPUModel(String GPUModel) { +// this.GPUModel = GPUModel; +// } +// +// public void setGPUMemorySize(Integer GPUMemorySize) { +// this.GPUMemorySize = GPUMemorySize; +// } +// +// public void setIsDeleted(Integer isDeleted) { +// this.isDeleted = isDeleted; +// } +// +// public void setIp(String ip) { +// Ip = ip; +// } +// +// public void setCreateTime(LocalDateTime createTime) { +// CreateTime = createTime; +// } +// +// public void setUpdateTime(LocalDateTime updateTime) { +// UpdateTime = updateTime; +// } + +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/enums/ErrorCodeEnum.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/enums/ErrorCodeEnum.java new file mode 100644 index 0000000..9f28c98 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/enums/ErrorCodeEnum.java @@ -0,0 +1,45 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity.enums; + +import lombok.Getter; + +@Getter +public enum ErrorCodeEnum { + SUCCESS(200, "操作成功"), + SYSTEM_ERROR(500, "系统错误"), + + PARAM_INVALID(400, "参数无效"), + PARAM_MISSING(401, "缺少参数"), + IP_FORMAT_ERROR(402, "IP地址格式错误"), + GPU_MODEL_ERROR(403, "GPU型号格式应为[厂商]-[型号]"), + + PERMISSION_DENIED(501, "无操作权限"), + + GPU_NOT_FOUND(601, "GPU资源不存在"), + + DB_CONNECTION_FAILED(701, "数据库连接错误"), + VALIDATION_ERROR(801,"参数校验异常" ), + + CACHE_INIT_ERROR(901, "缓存初始化失败"); + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } + + private final int code; + private final String message; + ErrorCodeEnum(int code, String message) { + this.code = code; + this.message = message; + } + + public String toString() { + return "ErrorCodeEnum{" + + "code=" + code + + ", message='" + message + '\''+ + '}'; + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/vo/ResponseVO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/vo/ResponseVO.java new file mode 100644 index 0000000..e7ab79b --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/vo/ResponseVO.java @@ -0,0 +1,38 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity.vo; + +import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; + + +import java.io.Serializable; + +public class ResponseVO implements Serializable { + private Integer code; //状态码 + private String message; //描述信息 + private T data; //业务数据 + + + //私有构造方法 + private ResponseVO(Integer code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + //静态工厂方法 + //成功响应(无数据) + public static ResponseVO success() { + return new ResponseVO<>(200, "OK", null); + } + //成功响应(有数据) + public static ResponseVO success(T data) { + return new ResponseVO<>(200, "OK", data); + } + //失败响应(自定义错误码和消息) + public static ResponseVO error(Integer code, String message) { + return new ResponseVO<>(code, message, null); + } + //失败响应(基于预定义错误枚举) + public static ResponseVO error(ErrorCodeEnum errorCode) { + return new ResponseVO<>(errorCode.getCode(), errorCode.getMessage(), null); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/CacheInitException.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/CacheInitException.java new file mode 100644 index 0000000..fd83490 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/CacheInitException.java @@ -0,0 +1,10 @@ +package com.bipt.intelligentapplicationorchestrationservice.exception; + +public class CacheInitException extends RuntimeException{ + public CacheInitException(String message) { + super(message); + } + public CacheInitException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GlobalExceptionHandler.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..d300d77 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GlobalExceptionHandler.java @@ -0,0 +1,34 @@ +package com.bipt.intelligentapplicationorchestrationservice.exception; + +import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; +import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(DataAccessResourceFailureException.class) + public ResponseVO handleDBConnectionError() { + return ResponseVO.error(ErrorCodeEnum.DB_CONNECTION_FAILED); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseVO handleValidationError(MethodArgumentNotValidException e) { + return ResponseVO.error(ErrorCodeEnum.VALIDATION_ERROR); + } + + @ExceptionHandler(PermissionDeniedException.class) + public ResponseVO handlePermissionDenied(PermissionDeniedException ex) { + return ResponseVO.error(ex.getCode(), ex.getMessage()); + } + + @ExceptionHandler(CacheInitException.class) + public ResponseVO handleCacheInitException(CacheInitException ex) { + return ResponseVO.error( + ErrorCodeEnum.CACHE_INIT_ERROR.getCode(), + "缓存初始化失败: " + ex.getMessage() + ); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java new file mode 100644 index 0000000..fcb4513 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java @@ -0,0 +1,32 @@ +package com.bipt.intelligentapplicationorchestrationservice.exception; + +import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; +import lombok.Getter; + +@Getter +public class PermissionDeniedException extends RuntimeException { + private final Integer code; + + public String getMessage() { + return message; + } + + public Integer getCode() { + return code; + } + + private final String message; + + public PermissionDeniedException(ErrorCodeEnum errorCode) { + super(errorCode.getMessage()); + this.code = errorCode.getCode(); + this.message = errorCode.getMessage(); + } + + public PermissionDeniedException(ErrorCodeEnum errorCode, String appendMessage) { + super(errorCode.getMessage()+": "+appendMessage); + this.code = errorCode.getCode(); + this.message = errorCode.getMessage()+": "+appendMessage; + } + +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java new file mode 100644 index 0000000..4f52841 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java @@ -0,0 +1,16 @@ +package com.bipt.intelligentapplicationorchestrationservice.mapper; + +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface GpuMapper { + GpuResource toEntity(GpuCreateDTO dto); + GpuResource toEntity(GpuUpdateDTO dto); + GpuResource toEntity(GpuResponseDTO dto); + GpuResponseDTO toDTO(GpuResource entity); +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java new file mode 100644 index 0000000..e415e25 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java @@ -0,0 +1,93 @@ +package com.bipt.intelligentapplicationorchestrationservice.mapper; + +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.jdbc.SQL; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +@Mapper +public interface GpuResourceDao { + //---------------------- 基础CRUD ------------------------ + @Insert("INSERT INTO Ipz.public.gpu_resource (GPUModel, GPUMemorySize, Ip) " + + "VALUES (#{model}, #{memory}, #{ip})") + @Options(useGeneratedKeys = true, keyProperty = "GPUId") + Integer insert(GpuResource entity); + + //物理删除 + @Delete("DELETE FROM Ipz.public.gpu_resource WHERE GPUId = #{gpuId}") + Integer deleteById(@Param("gpuId") Long gpuId); + + // 逻辑删除 + @Update("UPDATE Ipz.public.gpu_resource" + + " SET is_deleted = 1, update_time = NOW() " + + " WHERE GPUId = #{gpuId}") + Integer isDeleted(@Param("gpuId") Long gpuId); + + @Update("UPDATE Ipz.public.gpu_resource " + + "SET GPUModel = #{model}, GPUMemorySize = #{memory}, Ip = #{ip} " + + "WHERE GPUId = #{GPUId}") + Integer updateById(GpuResource entity); + + @Select("SELECT * FROM Ipz.public.gpu_resource WHERE GPUId = #{gpuId} AND is_deleted = 0") + GpuResource selectById(@Param("gpuId") Long gpuId); + + //---------------------- 缓存相关扩展 ------------------------ + + /** + * 分页全量查询(缓存初始化用) + * @param offset 起始位置 + * @param limit 每页数量 + */ +// @Select("SELECT * FROM ipz.gpu_resource " + +// "ORDER BY GPUId ASC LIMIT #{limit} OFFSET #{offset}") + List findByPage(@Param("offset") int offset, + @Param("limit") int limit); + + /** + * 增量数据查询(缓存同步用) + * @param since 起始时间 + */ +// @Select("SELECT *, is_deleted FROM ipz.gpu_resource " + +// "WHERE update_time > #{since} " + +// "ORDER BY update_time ASC") + List findModifiedSince(@Param("since") LocalDateTime since); + + /** + * 带锁查询(防缓存击穿) + */ +// @Select("SELECT * FROM ipz.gpu_resource " + +// "WHERE GPUId = #{gpuId} FOR UPDATE NOWAIT") + GpuResource selectByIdWithLock(@Param("gpuId") Long gpuId); + + /** + * 动态条件查询(管理界面筛选用) + */ + // @SelectProvider(type = GpuSqlBuilder.class, method = "buildDynamicQuery") + List selectByFields(@Param("params") Map params); +} + +// 动态SQL构造器 +class GpuSqlBuilder { + public static String buildDynamicQuery(Map params) { + return new SQL() {{ + SELECT("*"); + FROM("Ipz.public.gpu_resource"); + if (params.containsKey("model")) { + WHERE("GPUModel LIKE #{params.model}"); + } + if (params.containsKey("memoryMin")) { + WHERE("GPUMemorySize >= #{params.memoryMin}"); + } + if (params.containsKey("ip")) { + WHERE("Ip = #{params.ip}"); + } + if (params.containsKey("isDeleted")) { + WHERE("is_deleted = #{params.isDeleted}"); + } + }}.toString(); + } + +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java new file mode 100644 index 0000000..b39d307 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java @@ -0,0 +1,169 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuResourceDao; +import com.bipt.intelligentapplicationorchestrationservice.exception.CacheInitException; +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import jakarta.annotation.PostConstruct; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.RedisConnectionFailureException; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +@Transactional // 添加类级别事务管理 +@Component +public class CacheManager { + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private GpuResourceDao gpuResourceDao; + + private final ReentrantLock lock = new ReentrantLock(); + + @Value("${cache.redis-key-prefix:gpu:}") + private String keyPrefix; + + @Value("${cache.ttl-base:7200}") + private int ttlBase; + + @Value("${cache.init-batch-size:500}") + private int initBatchSize; + + private static final Logger log = org.slf4j.LoggerFactory.getLogger(CacheManager.class); + // 全量加载(带分页和分布式锁) + @Transactional(propagation = Propagation.REQUIRED) // 方法级别覆盖 + @PostConstruct + public void loadFullCache() { + if (tryLock()) { + try { + int page = 0; + while (true) { + List batch = gpuResourceDao.findByPage(page * initBatchSize, initBatchSize); + if (batch.isEmpty()) break; + + batch.forEach(this::setCacheWithTTL); + page++; + } + } finally { + unlock(); + } + } + } + + // 单条缓存刷新(带版本控制) + public void refreshCache(Long gpuId) { + GpuResource latest = gpuResourceDao.selectByIdWithLock(gpuId); + if (latest != null) { + setCacheWithTTL(latest); + } + } + + // 批量增量同步 + public void syncCache(LocalDateTime lastSyncTime) { + List updates = gpuResourceDao.findModifiedSince(lastSyncTime); + updates.forEach(entity -> { + if (entity.getIsDeleted()) { + redisTemplate.delete(buildKey(entity.getGPUId().toString())); + } else { + setCacheWithTTL(entity); + } + }); + } + + // 带随机TTL的缓存设置 + private void setCacheWithTTL(GpuResource entity) { + String key = buildKey(entity.getGPUId().toString()); + GpuResource cached = (GpuResource) redisTemplate.opsForValue().get(key); + + // 保留原有内存字段值 + if (cached != null && cached.getGPUMemorySize() != null) { + entity.setGPUMemorySize(cached.getGPUMemorySize()); + } + redisTemplate.opsForValue().set( + key, + entity, + ttlBase + (int)(Math.random() * 600), // 随机TTL防止雪崩 + TimeUnit.SECONDS + ); + } + + // 构建缓存键 + private String buildKey(String gpuId) { + return keyPrefix + gpuId; + } + + // 分布式锁操作 + private boolean tryLock() { + try { + return lock.tryLock(30, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + + private void unlock() { + lock.unlock(); + } + // 分页加载入口 + public void loadFullCache(int batchSize) { + int page = 0; + while (true) { + List batch = gpuResourceDao.findByPage(page * batchSize, batchSize); + if (batch.isEmpty()) break; + + batch.forEach(this::refreshWithRetry); // 带重试的刷新逻辑 + page++; + } + } + + + // 带重试机制的缓存刷新 + public void refreshWithRetry(GpuResource entity) { + try { + setCacheWithTTL(entity); + } catch (RedisConnectionFailureException ex) { + // 3次重试逻辑 + for (int i = 0; i < 3; i++) { + try { + log.info("重试第 {} 次", i + 1); // 添加日志 + Thread.sleep(1000); + setCacheWithTTL(entity); + return; + } catch (InterruptedException e) { + if (i == 2) { + throw new CacheInitException("缓存刷新失败: " + entity.getGPUId().toString()); + } + + log.error("重试失败", e); + Thread.currentThread().interrupt(); + } + } + + } + } + + // 获取当前缓存数量(调试用) + public long getCacheCount() { + return redisTemplate.keys(keyPrefix + "*").size(); + } + + public void evictCache(Long gpuId) { + String key = buildKey(gpuId.toString()); + redisTemplate.delete(key); + } + + public GpuResource getFromCache(String gpuId) { + return (GpuResource) redisTemplate.opsForValue().get("gpu:" + gpuId); + } + +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java new file mode 100644 index 0000000..870af09 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java @@ -0,0 +1,15 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; + +import java.util.List; + +public interface GpuManageService { + public ResponseVO createGpuResource(GpuCreateDTO dto); + public ResponseVO deleteGpuResource(Long gpuId); + public void updateGpuResource(GpuUpdateDTO entity); + public List searchByCriteria(String model, Integer memorySize, String ip); +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java new file mode 100644 index 0000000..7661d6d --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java @@ -0,0 +1,127 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + + +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Service; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@Service +public class RedisCacheService { + + private final RedisTemplate redisTemplate; + + @Value("${cache.redis-key-prefix:gpu:}") + private String keyPrefix; + + @Value("${cache.ttl-base:7200}") + private int baseTTL; + private final RedisSerializer valueSerializer; + +// @Autowired +// public RedisCacheService(RedisTemplate redisTemplate) { +// this.redisTemplate = redisTemplate; +// } + + // 核心方法 ------------------------------------------------------------ + @Autowired + public RedisCacheService(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + this.valueSerializer = (RedisSerializer) redisTemplate.getValueSerializer(); + } + + /** + * 批量写入GPU资源数据(带管道优化) + * @param resources GPU资源列表 + */ + public void batchPut(List resources) { + redisTemplate.executePipelined((RedisCallback) connection -> { + resources.forEach(resource -> { + String key = buildKey(resource.getGPUId().toString()); + byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); + byte[] valueBytes = valueSerializer.serialize(resource); + connection.stringCommands().setEx( + keyBytes, + calculateTTL(), + valueBytes + ); + }); + return null; + }); + } + + /** + * 设置单条缓存(含随机TTL防雪崩) + * @param gpuId 资源ID + * @param resource 资源对象 + */ + public void put(String gpuId, GpuResource resource) { + String key = buildKey(gpuId); + redisTemplate.opsForValue().set( + key, + resource, + calculateTTL(), + TimeUnit.SECONDS + ); + } + + /** + * 获取单个缓存项 + * @param gpuId 资源ID + * @return 缓存对象或null + */ + public GpuResource get(String gpuId) { + return (GpuResource) redisTemplate.opsForValue().get(buildKey(gpuId)); + } + + /** + * 删除指定缓存 + * @param gpuId 资源ID + */ + public void delete(Long gpuId) { + redisTemplate.delete(buildKey(gpuId.toString())); + } + + // 辅助方法 ------------------------------------------------------------ + + private String buildKey(String gpuId) { + return keyPrefix + gpuId; + } + + private long calculateTTL() { + return baseTTL + (long)(Math.random() * 600); // 7200-7800秒随机值 + } + + /** + * 批量删除缓存(事务处理) + * @param gpuIds 资源ID列表 + */ + public void batchDelete(List gpuIds) { + redisTemplate.execute((RedisCallback) connection -> { + connection.multi(); + gpuIds.forEach(id -> connection.del(buildKey(id).getBytes())); + connection.exec(); + return null; + }); + } + + /** + * 缓存健康检查 + * @return 是否连通 + */ + public boolean healthCheck() { + try { + return "PONG".equals(Objects.requireNonNull(redisTemplate.getConnectionFactory()) + .getConnection().ping()); + } catch (Exception e) { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java new file mode 100644 index 0000000..81957a1 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java @@ -0,0 +1,72 @@ +package com.bipt.intelligentapplicationorchestrationservice.service.impl; + +import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuResourceDao; +import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuMapper; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; +import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import com.bipt.intelligentapplicationorchestrationservice.service.GpuManageService; +import jakarta.transaction.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class GpuManageServiceImpl implements GpuManageService { + @Autowired + private GpuResourceDao gpuDao; + + @Autowired + private GpuMapper gpuMapper; + @Autowired + private GpuResourceDao gpuResourceDao; + + @Transactional + //创建GPU资源 + public ResponseVO createGpuResource(GpuCreateDTO dto) { + GpuResource entity = gpuMapper.toEntity(dto); + gpuDao.insert(entity); + return ResponseVO.success(entity); + } + + @Transactional + //删除GPU资源(逻辑删除) + public ResponseVO deleteGpuResource(Long gpuId) { + GpuResource entity = gpuDao.selectById(gpuId); + if (entity == null) { + return ResponseVO.error(ErrorCodeEnum.GPU_NOT_FOUND); + } + gpuDao.isDeleted(gpuId); + return ResponseVO.success(); + } + + @Transactional + //更新GPU资源 + public void updateGpuResource(GpuUpdateDTO dto) { + GpuResource entity = gpuMapper.toEntity(dto); + gpuDao.updateById(entity); + } + + @Override + //模糊匹配查询 + public List searchByCriteria(String model, Integer memorySize, String ip) { + // PermissionCheckUtil.checkTenantAccess(); + + Map params = new HashMap<>(); + if(model != null) params.put("model","%" + model + "%"); + if(memorySize!=null) params.put("memorySize", memorySize); + if(ip!=null) params.put("ip", ip); + + List entities = gpuResourceDao.selectByFields(params); + + return entities.stream().map(gpuMapper::toDTO).collect(Collectors.toList()); + + } +} diff --git a/src/main/resources/mapper/GpuResourceMapper.xml b/src/main/resources/mapper/GpuResourceMapper.xml new file mode 100644 index 0000000..7950d7f --- /dev/null +++ b/src/main/resources/mapper/GpuResourceMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file