| | |
| | | import java.util.UUID; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ConcurrentMap; |
| | | import java.util.function.LongSupplier; |
| | | |
| | | @Component |
| | | @RequiredArgsConstructor |
| | |
| | | private final AiAutoTuneJobService aiAutoTuneJobService; |
| | | private final AiAutoTuneChangeService aiAutoTuneChangeService; |
| | | private final ConcurrentMap<String, DryRunPreview> dryRunPreviews = new ConcurrentHashMap<>(); |
| | | private LongSupplier currentTimeMillisSupplier = System::currentTimeMillis; |
| | | |
| | | @Tool(name = "dispatch_get_auto_tune_snapshot", description = "获取WCS自动调参所需的调度快照、站点运行态、拓扑容量和当前可写参数") |
| | | public AutoTuneSnapshot getAutoTuneSnapshot() { |
| | |
| | | if (preview == null) { |
| | | throw new IllegalArgumentException("dryRunToken is missing, expired, or already used."); |
| | | } |
| | | if (preview.isExpired()) { |
| | | if (preview.isExpired(currentTimeMillis())) { |
| | | throw new IllegalArgumentException("dryRunToken is expired. Run dryRun=true again."); |
| | | } |
| | | if (!preview.getFingerprint().equals(fingerprint)) { |
| | |
| | | private String createDryRunToken(String fingerprint) { |
| | | cleanExpiredDryRunPreviews(); |
| | | String token = UUID.randomUUID().toString(); |
| | | dryRunPreviews.put(token, new DryRunPreview(fingerprint, System.currentTimeMillis() + DRY_RUN_TOKEN_TTL_MILLIS)); |
| | | dryRunPreviews.put(token, new DryRunPreview(fingerprint, currentTimeMillis() + DRY_RUN_TOKEN_TTL_MILLIS)); |
| | | return token; |
| | | } |
| | | |
| | | private void cleanExpiredDryRunPreviews() { |
| | | long currentTimeMillis = currentTimeMillis(); |
| | | for (Map.Entry<String, DryRunPreview> entry : dryRunPreviews.entrySet()) { |
| | | if (entry.getValue() == null || entry.getValue().isExpired()) { |
| | | if (entry.getValue() == null || entry.getValue().isExpired(currentTimeMillis)) { |
| | | dryRunPreviews.remove(entry.getKey()); |
| | | } |
| | | } |
| | |
| | | return value == null || value.trim().isEmpty(); |
| | | } |
| | | |
| | | private long currentTimeMillis() { |
| | | return currentTimeMillisSupplier.getAsLong(); |
| | | } |
| | | |
| | | void setCurrentTimeMillisSupplier(LongSupplier currentTimeMillisSupplier) { |
| | | this.currentTimeMillisSupplier = currentTimeMillisSupplier == null |
| | | ? System::currentTimeMillis |
| | | : currentTimeMillisSupplier; |
| | | } |
| | | |
| | | private static class DryRunPreview { |
| | | private final String fingerprint; |
| | | private final long expireAtMillis; |
| | |
| | | return fingerprint; |
| | | } |
| | | |
| | | boolean isExpired() { |
| | | return System.currentTimeMillis() > expireAtMillis; |
| | | boolean isExpired(long currentTimeMillis) { |
| | | return currentTimeMillis > expireAtMillis; |
| | | } |
| | | } |
| | | } |