Skip to main content

gglib_core/ports/
benchmark.rs

1//! Benchmark repository port definition.
2//!
3//! Defines the interface for persisting benchmark runs and results.
4//! Implementations live in `gglib-db`; this trait contains only domain types.
5
6use async_trait::async_trait;
7
8use super::RepositoryError;
9use crate::domain::{
10    BenchmarkRun, BenchmarkRunType, ModelBenchmarkSummary, ModelCompareResult, ModelPerfResult,
11    TuneCandidateResult,
12};
13
14/// Repository interface for benchmark persistence.
15///
16/// Implementations are responsible for:
17/// - Creating and updating run records
18/// - Storing per-model compare and perf results
19/// - Upserting `model_benchmark_summaries` in the same transaction as each
20///   result save, so the model list query always has fresh summary data
21///   without extra round-trips
22#[async_trait]
23pub trait BenchmarkRepositoryPort: Send + Sync {
24    /// Create a new benchmark run record in `Running` status.
25    ///
26    /// Returns the auto-assigned run ID.
27    async fn create_run(
28        &self,
29        run_type: BenchmarkRunType,
30        model_ids: &[i64],
31        prompt_text: Option<&str>,
32        system_prompt: Option<&str>,
33        config_json: Option<&str>,
34    ) -> Result<i64, RepositoryError>;
35
36    /// Mark a run as `Complete` and record the completion timestamp.
37    async fn complete_run(&self, run_id: i64) -> Result<(), RepositoryError>;
38
39    /// Mark a run as `Failed` and record the error message.
40    async fn fail_run(&self, run_id: i64, error: &str) -> Result<(), RepositoryError>;
41
42    /// Persist a compare result and upsert the model's benchmark summary.
43    ///
44    /// Both the result INSERT and the summary upsert happen in the same
45    /// database transaction to keep the denormalised summary consistent.
46    ///
47    /// Returns the auto-assigned result ID.
48    async fn save_compare_result(
49        &self,
50        result: &ModelCompareResult,
51        run_id: i64,
52    ) -> Result<i64, RepositoryError>;
53
54    /// Persist a perf result and upsert the model's benchmark summary.
55    ///
56    /// Both the result INSERT and the summary upsert happen in the same
57    /// database transaction to keep the denormalised summary consistent.
58    ///
59    /// Returns the auto-assigned result ID.
60    async fn save_perf_result(
61        &self,
62        result: &ModelPerfResult,
63        run_id: i64,
64    ) -> Result<i64, RepositoryError>;
65
66    /// List benchmark runs, most recent first.
67    async fn list_runs(
68        &self,
69        limit: i64,
70        offset: i64,
71    ) -> Result<Vec<BenchmarkRun>, RepositoryError>;
72
73    /// Get a single benchmark run by ID.
74    async fn get_run(&self, run_id: i64) -> Result<Option<BenchmarkRun>, RepositoryError>;
75
76    /// Get compare results for one model, most recent first.
77    async fn get_model_compare_history(
78        &self,
79        model_id: i64,
80        limit: i64,
81    ) -> Result<Vec<ModelCompareResult>, RepositoryError>;
82
83    /// Get perf results for one model, most recent first.
84    async fn get_model_perf_history(
85        &self,
86        model_id: i64,
87        limit: i64,
88    ) -> Result<Vec<ModelPerfResult>, RepositoryError>;
89
90    /// Get the denormalised benchmark summary for one model.
91    ///
92    /// Returns `None` if no benchmark has been run for this model.
93    async fn get_model_summary(
94        &self,
95        model_id: i64,
96    ) -> Result<Option<ModelBenchmarkSummary>, RepositoryError>;
97
98    /// Persist one tune candidate's result.
99    ///
100    /// Unlike compare/perf, tune results do not upsert
101    /// `model_benchmark_summaries` — a candidate's `composite_score` is only
102    /// meaningful relative to the other candidates in the same run, so it is
103    /// not a useful cross-run "best" figure to denormalise.
104    ///
105    /// Returns the auto-assigned result ID.
106    async fn save_tune_result(
107        &self,
108        result: &TuneCandidateResult,
109        run_id: i64,
110        model_id: i64,
111    ) -> Result<i64, RepositoryError>;
112
113    /// Get tune candidate results for one model, most recent first.
114    async fn get_model_tune_history(
115        &self,
116        model_id: i64,
117        limit: i64,
118    ) -> Result<Vec<TuneCandidateResult>, RepositoryError>;
119}