feat(trace): add session run isolation schema

This commit is contained in:
zhuyongxin
2026-07-10 17:47:56 +08:00
parent 841437fa06
commit 52bf0302c6
21 changed files with 1718 additions and 1 deletions
@@ -15,6 +15,7 @@ import java.time.LocalDateTime;
@Entity
@Table(name = "agent_step", indexes = {
@Index(name = "idx_session_step", columnList = "session_id, step_index"),
@Index(name = "idx_agent_step_run_step", columnList = "run_id, step_index"),
@Index(name = "idx_agent_name", columnList = "agent_name")
})
@Data
@@ -30,6 +31,9 @@ public class AgentStep {
@Column(name = "session_id", nullable = false, length = 64)
private String sessionId;
@Column(name = "run_id", length = 64)
private String runId;
@Column(name = "step_index", nullable = false)
private Integer stepIndex;
@@ -0,0 +1,64 @@
package com.superbiz.agent.domain.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* Chat session metadata entity.
* Full message history remains in Redis SessionContext.
*/
@Entity
@Table(name = "chat_session", indexes = {
@Index(name = "idx_chat_session_last_active", columnList = "last_active_at"),
@Index(name = "idx_chat_session_status", columnList = "status"),
@Index(name = "idx_chat_session_expires_at", columnList = "expires_at")
})
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatSession {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "session_id", unique = true, nullable = false, length = 64)
private String sessionId;
@Column(name = "status", length = 16)
private String status = "ACTIVE";
@Column(name = "message_pair_count")
private Integer messagePairCount = 0;
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;
@Column(name = "last_active_at")
private LocalDateTime lastActiveAt;
@Column(name = "expires_at")
private LocalDateTime expiresAt;
@PrePersist
protected void onCreate() {
LocalDateTime now = LocalDateTime.now();
createdAt = now;
if (lastActiveAt == null) {
lastActiveAt = now;
}
if (status == null) {
status = "ACTIVE";
}
if (messagePairCount == null) {
messagePairCount = 0;
}
}
}
@@ -0,0 +1,91 @@
package com.superbiz.agent.domain.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import java.time.LocalDateTime;
/**
* One diagnosis execution run.
*/
@Entity
@Table(name = "diagnosis_run", indexes = {
@Index(name = "idx_diagnosis_run_session_created", columnList = "session_id, created_at, id"),
@Index(name = "idx_diagnosis_run_session_run", columnList = "session_id, run_id"),
@Index(name = "idx_diagnosis_run_status", columnList = "status"),
@Index(name = "idx_diagnosis_run_agent_flow", columnList = "agent_flow")
})
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DiagnosisRun {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "run_id", unique = true, nullable = false, length = 64)
private String runId;
@Column(name = "session_id", nullable = false, length = 64)
private String sessionId;
@Column(name = "query", nullable = false, columnDefinition = "TEXT")
private String query;
@Column(name = "status", length = 16)
private String status = "PENDING";
@Column(name = "agent_flow", length = 32)
private String agentFlow;
@Column(name = "answer", columnDefinition = "LONGTEXT")
private String answer;
@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "self_evaluation", columnDefinition = "JSON")
private String selfEvaluation;
@Column(name = "feedback", length = 16)
private String feedback;
@Column(name = "total_duration_ms")
private Integer totalDurationMs;
@Column(name = "total_token_count")
private Integer totalTokenCount;
@Column(name = "step_count")
private Integer stepCount;
@Column(name = "tool_call_count")
private Integer toolCallCount;
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
LocalDateTime now = LocalDateTime.now();
createdAt = now;
updatedAt = now;
if (status == null) {
status = "PENDING";
}
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
@@ -17,6 +17,7 @@ import java.time.LocalDateTime;
@Entity
@Table(name = "tool_invocation", indexes = {
@Index(name = "idx_session_id", columnList = "session_id"),
@Index(name = "idx_tool_invocation_run_id", columnList = "run_id, id"),
@Index(name = "idx_tool_name", columnList = "tool_name"),
@Index(name = "idx_retrieval_layer", columnList = "retrieval_layer")
})
@@ -33,6 +34,9 @@ public class ToolInvocation {
@Column(name = "session_id", nullable = false, length = 64)
private String sessionId;
@Column(name = "run_id", length = 64)
private String runId;
@Column(name = "step_id")
private Long stepId;
@@ -22,8 +22,18 @@ public interface AgentStepRepository extends JpaRepository<AgentStep, Long> {
*/
List<AgentStep> findBySessionId(String sessionId);
/**
* 根据运行ID查询所有步骤(按步骤号排序)。
*/
List<AgentStep> findByRunIdOrderByStepIndex(String runId);
/**
* 统计某个会话的步骤数
*/
int countBySessionId(String sessionId);
/**
* 统计某个运行的步骤数。
*/
int countByRunId(String runId);
}
@@ -0,0 +1,14 @@
package com.superbiz.agent.repository;
import com.superbiz.agent.domain.entity.ChatSession;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface ChatSessionRepository extends JpaRepository<ChatSession, Long> {
Optional<ChatSession> findBySessionId(String sessionId);
}
@@ -0,0 +1,21 @@
package com.superbiz.agent.repository;
import com.superbiz.agent.domain.entity.DiagnosisRun;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface DiagnosisRunRepository extends JpaRepository<DiagnosisRun, Long> {
Optional<DiagnosisRun> findByRunId(String runId);
Optional<DiagnosisRun> findBySessionIdAndRunId(String sessionId, String runId);
Optional<DiagnosisRun> findFirstBySessionIdOrderByCreatedAtDescIdDesc(String sessionId);
List<DiagnosisRun> findBySessionIdOrderByCreatedAtDescIdDesc(String sessionId);
}
@@ -22,11 +22,21 @@ public interface ToolInvocationRepository extends JpaRepository<ToolInvocation,
*/
List<ToolInvocation> findBySessionIdOrderByIdAsc(String sessionId);
/**
* 根据运行ID按创建顺序查询所有工具调用
*/
List<ToolInvocation> findByRunIdOrderByIdAsc(String runId);
/**
* 根据会话ID统计真实工具调用次数
*/
long countBySessionId(String sessionId);
/**
* 根据运行ID统计真实工具调用次数
*/
long countByRunId(String runId);
/**
* 根据工具名查询所有调用
*/