agentics_persistence/repositories/
solution_submissions.rs1use sqlx::PgPool;
2
3use crate::db;
4use crate::repositories::{
5 AdminSolutionSubmissionListItemRecord, CreateSolutionSubmissionInput,
6 PublicObserverStatsRecord, PublicSolutionSubmissionListItemRecord,
7};
8use agentics_domain::models::evaluation::ScoringMode;
9use agentics_domain::models::ids::{AgentId, SolutionSubmissionId};
10use agentics_domain::models::names::{ChallengeName, TargetName};
11use agentics_error::Result;
12
13#[derive(Debug, Clone, Copy)]
14pub struct SolutionSubmissionsRepository<'a> {
15 pub(super) pool: &'a PgPool,
16}
17
18impl SolutionSubmissionsRepository<'_> {
19 pub async fn create_with_job(
20 &self,
21 input: &CreateSolutionSubmissionInput,
22 ) -> Result<crate::repositories::SolutionSubmissionRecord> {
23 db::solution_submissions::create_solution_submission_with_job(self.pool, input).await
24 }
25
26 pub async fn ensure_parent_matches_scope(
27 &self,
28 parent_solution_submission_id: Option<&SolutionSubmissionId>,
29 agent_id: &AgentId,
30 challenge_name: &ChallengeName,
31 target: &TargetName,
32 ) -> Result<()> {
33 db::solution_submissions::ensure_parent_solution_submission_matches_scope(
34 self.pool,
35 parent_solution_submission_id,
36 agent_id,
37 challenge_name,
38 target,
39 )
40 .await
41 }
42
43 pub async fn delete(&self, solution_submission_id: &SolutionSubmissionId) -> Result<()> {
44 db::solution_submissions::delete_solution_submission(self.pool, solution_submission_id)
45 .await
46 }
47
48 pub async fn get_by_id(
49 &self,
50 id: &SolutionSubmissionId,
51 ) -> Result<Option<crate::repositories::SolutionSubmissionRecord>> {
52 db::solution_submissions::get_solution_submission_by_id(self.pool, id).await
53 }
54
55 pub async fn get_public_by_id(
56 &self,
57 id: &SolutionSubmissionId,
58 ) -> Result<Option<crate::repositories::SolutionSubmissionRecord>> {
59 db::solution_submissions::get_public_solution_submission_by_id(self.pool, id).await
60 }
61
62 pub async fn list_admin(
63 &self,
64 limit: i64,
65 ) -> Result<Vec<AdminSolutionSubmissionListItemRecord>> {
66 db::solution_submissions::list_admin_solution_submissions(self.pool, limit).await
67 }
68
69 pub async fn list_public_for_challenge(
70 &self,
71 challenge_name: &ChallengeName,
72 target: &TargetName,
73 limit: i64,
74 ) -> Result<Vec<PublicSolutionSubmissionListItemRecord>> {
75 db::solution_submissions::list_public_solution_submissions_for_challenge(
76 self.pool,
77 challenge_name,
78 target,
79 limit,
80 )
81 .await
82 }
83
84 pub async fn count_public_for_challenge(
85 &self,
86 challenge_name: &ChallengeName,
87 target: &TargetName,
88 ) -> Result<i64> {
89 db::solution_submissions::count_public_solution_submissions_for_challenge(
90 self.pool,
91 challenge_name,
92 target,
93 )
94 .await
95 }
96
97 pub async fn observer_stats(&self) -> Result<PublicObserverStatsRecord> {
98 db::solution_submissions::public_observer_stats(self.pool).await
99 }
100
101 pub async fn count_recent_runs_for_agent_challenge(
102 &self,
103 agent_id: &AgentId,
104 challenge_name: &ChallengeName,
105 target: &TargetName,
106 eval_type: ScoringMode,
107 window_seconds: i64,
108 ) -> Result<i64> {
109 db::validation_quotas::count_recent_runs_for_agent_challenge(
110 self.pool,
111 agent_id,
112 challenge_name,
113 target,
114 eval_type,
115 window_seconds,
116 )
117 .await
118 }
119
120 pub async fn count_lifetime_runs_for_agent_challenge(
121 &self,
122 agent_id: &AgentId,
123 challenge_name: &ChallengeName,
124 target: &TargetName,
125 eval_type: ScoringMode,
126 ) -> Result<i64> {
127 db::validation_quotas::count_lifetime_runs_for_agent_challenge(
128 self.pool,
129 agent_id,
130 challenge_name,
131 target,
132 eval_type,
133 )
134 .await
135 }
136}