package com.vincent.rsf.server.ai.store; import com.vincent.rsf.server.ai.config.AiDefaults; import com.vincent.rsf.server.ai.store.support.AiRedisExecutor; import com.vincent.rsf.server.ai.store.support.AiRedisKeys; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.time.Instant; @Component @RequiredArgsConstructor public class AiStreamStateStore { private final AiRedisExecutor aiRedisExecutor; private final AiRedisKeys aiRedisKeys; public void markStreamState(String requestId, Long tenantId, Long userId, Long sessionId, String promptCode, String status, String errorMessage) { if (!StringUtils.hasText(requestId)) { return; } aiRedisExecutor.writeJson(aiRedisKeys.buildStreamStateKey(tenantId, requestId), AiStreamState.builder() .requestId(requestId) .tenantId(tenantId) .userId(userId) .sessionId(sessionId) .promptCode(promptCode) .status(status) .errorMessage(errorMessage) .timestamp(Instant.now().toEpochMilli()) .build(), AiDefaults.STREAM_STATE_TTL_SECONDS); } @Data @Builder @NoArgsConstructor @AllArgsConstructor private static class AiStreamState { private String requestId; private Long tenantId; private Long userId; private Long sessionId; private String promptCode; private String status; private String errorMessage; private Long timestamp; } }