refactor(data): remove MySQL and SQLite support

Use PostgreSQL as the only database backend across runtime, schema tooling, installation, Compose, and CI. Update regression tests and reject removed drivers explicitly.
This commit is contained in:
elky
2026-09-07 00:09:42 +08:00
parent b5ed802277
commit 2281f2b754
298 changed files with 793 additions and 134804 deletions
@@ -4,10 +4,6 @@ pub use aether_data_contracts::repository::announcements::{
AnnouncementListQuery, AnnouncementReadRepository, AnnouncementWriteRepository,
CreateAnnouncementRecord, StoredAnnouncement, StoredAnnouncementPage, UpdateAnnouncementRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlAnnouncementRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxAnnouncementReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteAnnouncementRepository;
pub use memory::InMemoryAnnouncementReadRepository;
@@ -8,10 +8,6 @@ pub use aether_data_contracts::repository::audit::{
StoredAdminAuditLogPage, StoredSuspiciousActivity, StoredUserAuditLog, StoredUserAuditLogPage,
SUSPICIOUS_EVENT_TYPES,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlAuditLogReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::PostgresAuditLogReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteAuditLogReadRepository;
pub use types::{read_request_audit_bundle, RequestAuditBundle, RequestAuditReader};
@@ -9,10 +9,6 @@ pub use aether_data_contracts::repository::auth::{
StoredAuthApiKeyExportRecord, StoredAuthApiKeySnapshot, UpdateStandaloneApiKeyBasicRecord,
UpdateUserApiKeyBasicRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlAuthApiKeyReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxAuthApiKeySnapshotReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteAuthApiKeyReadRepository;
pub use memory::InMemoryAuthApiKeySnapshotRepository;
@@ -4,10 +4,6 @@ pub use aether_data_contracts::repository::auth_modules::{
AuthModuleReadRepository, AuthModuleWriteRepository, CompareAndSwapLdapConfigResult,
LdapBindPasswordUpdate, StoredLdapModuleConfig, StoredOAuthProviderModuleConfig,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::{MysqlAuthModuleReadRepository, MysqlAuthModuleRepository};
#[cfg(feature = "postgres")]
pub use aether_data_postgres::{SqlxAuthModuleReadRepository, SqlxAuthModuleRepository};
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::{SqliteAuthModuleReadRepository, SqliteAuthModuleRepository};
pub use memory::InMemoryAuthModuleReadRepository;
@@ -8,10 +8,6 @@ pub(crate) use aether_data_contracts::repository::background_tasks::{
StoredBackgroundTaskRunPage, UpsertBackgroundTaskEvent, UpsertBackgroundTaskRun,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlBackgroundTaskRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxBackgroundTaskRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteBackgroundTaskRepository;
pub use memory::InMemoryBackgroundTaskRepository;
@@ -1,9 +1,5 @@
mod memory;
pub use aether_data_contracts::repository::billing::*;
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlBillingReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxBillingReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteBillingReadRepository;
pub use memory::InMemoryBillingReadRepository;
@@ -8,10 +8,6 @@ pub(crate) use aether_data_contracts::repository::candidate_selection::{
StoredPoolKeyCandidateRowsQuery, StoredProviderModelMapping,
StoredRequestedModelCandidateRowsQuery,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlMinimalCandidateSelectionReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxMinimalCandidateSelectionReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteMinimalCandidateSelectionReadRepository;
pub use memory::InMemoryMinimalCandidateSelectionReadRepository;
@@ -9,10 +9,6 @@ pub(crate) use aether_data_contracts::repository::candidates::{
RequestCandidateTrace, RequestCandidateWriteRepository, StoredRequestCandidate,
UpsertRequestCandidateRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlRequestCandidateRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxRequestCandidateReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteRequestCandidateRepository;
pub use memory::InMemoryRequestCandidateRepository;
@@ -1,16 +1,8 @@
pub mod memory;
#[cfg(feature = "mysql")]
pub mod mysql {
pub use aether_data_mysql::MysqlGeminiFileMappingRepository;
}
#[cfg(feature = "postgres")]
pub mod postgres {
pub use aether_data_postgres::SqlxGeminiFileMappingRepository;
}
#[cfg(feature = "sqlite")]
pub mod sqlite {
pub use aether_data_sqlite::SqliteGeminiFileMappingRepository;
}
pub mod types {
pub use aether_data_contracts::repository::gemini_file_mappings::*;
}
@@ -20,10 +12,6 @@ pub use aether_data_contracts::repository::gemini_file_mappings::{
GeminiFileMappingRepository, GeminiFileMappingStats, GeminiFileMappingWriteRepository,
StoredGeminiFileMapping, StoredGeminiFileMappingListPage, UpsertGeminiFileMappingRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlGeminiFileMappingRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxGeminiFileMappingRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteGeminiFileMappingRepository;
pub use memory::InMemoryGeminiFileMappingRepository;
@@ -10,10 +10,6 @@ pub(crate) use aether_data_contracts::repository::global_models::{
StoredPublicCatalogModel, StoredPublicGlobalModel, StoredPublicGlobalModelPage,
UpdateAdminGlobalModelRecord, UpsertAdminProviderModelRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlGlobalModelReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxGlobalModelReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteGlobalModelReadRepository;
pub use memory::InMemoryGlobalModelReadRepository;
@@ -6,10 +6,6 @@ pub use aether_data_contracts::repository::management_tokens::{
StoredManagementToken, StoredManagementTokenListPage, StoredManagementTokenUserSummary,
StoredManagementTokenWithUser, UpdateManagementTokenRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlManagementTokenRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxManagementTokenRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteManagementTokenRepository;
pub use memory::InMemoryManagementTokenRepository;
@@ -6,10 +6,6 @@ pub use aether_data_contracts::repository::oauth_providers::{
OAuthProviderRepository, OAuthProviderWriteRepository, StoredOAuthProviderConfig,
UpsertOAuthProviderConfigOutcome, UpsertOAuthProviderConfigRecord,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlOAuthProviderRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxOAuthProviderRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteOAuthProviderRepository;
pub use memory::InMemoryOAuthProviderRepository;
@@ -2,10 +2,6 @@ pub use aether_data_contracts::repository::pool_scores::*;
mod memory;
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlPoolMemberScoreRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::PostgresPoolMemberScoreRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqlitePoolMemberScoreRepository;
pub use memory::InMemoryPoolMemberScoreRepository;
@@ -15,10 +15,6 @@ pub(crate) use aether_data_contracts::repository::provider_catalog::{
StoredProviderCatalogKeyMaintenanceSummary, StoredProviderCatalogKeyPage,
StoredProviderCatalogKeyStats, StoredProviderCatalogProvider,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlProviderCatalogReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxProviderCatalogReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteProviderCatalogReadRepository;
pub use memory::InMemoryProviderCatalogReadRepository;
@@ -1,12 +1,8 @@
mod memory;
pub use aether_data_contracts::repository::proxy_nodes::*;
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlProxyNodeReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxProxyNodeRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteProxyNodeReadRepository;
pub use memory::InMemoryProxyNodeRepository;
pub fn log_reported_tunnel_error_event(
@@ -5,10 +5,6 @@ pub(crate) use aether_data_contracts::repository::quota::{
ProviderQuotaReadRepository, ProviderQuotaRepository, ProviderQuotaWriteRepository,
StoredProviderQuotaSnapshot,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlProviderQuotaRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxProviderQuotaRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteProviderQuotaRepository;
pub use memory::InMemoryProviderQuotaRepository;
@@ -8,9 +8,5 @@ pub(crate) use aether_data_contracts::repository::routing_profiles::{
};
pub use memory::InMemoryRoutingGroupRepository;
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlRoutingGroupRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::PostgresRoutingGroupRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteRoutingGroupRepository;
@@ -1,11 +1,7 @@
mod memory;
pub use aether_data_contracts::repository::settlement::*;
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlSettlementRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxSettlementRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteSettlementRepository;
pub use memory::InMemorySettlementRepository;
#[cfg(test)]
@@ -1,6 +1,4 @@
mod memory;
#[cfg(feature = "mysql")]
mod mysql;
#[allow(unused_imports)]
pub(crate) use aether_data_contracts::repository::usage::{
@@ -43,11 +41,7 @@ pub mod cleanup {
}
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxUsageReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::{SqliteUsageReadRepository, SqliteUsageWriteRepository};
pub use memory::InMemoryUsageReadRepository;
#[cfg(feature = "mysql")]
pub use mysql::{MysqlUsageReadRepository, MysqlUsageWriteRepository};
#[cfg(test)]
mod tests {
@@ -1,457 +0,0 @@
use std::collections::BTreeMap;
use aether_data_contracts::repository::usage::{
ProviderApiKeyWindowUsageRequest, StoredProviderApiKeyUsageSummary,
StoredProviderApiKeyWindowUsageSummary, StoredProviderUsageSummary, StoredRequestUsageAudit,
StoredUsageAuditAggregation, StoredUsageAuditSummary, StoredUsageBreakdownSummaryRow,
StoredUsageCacheAffinityHitSummary, StoredUsageCacheAffinityIntervalRow,
StoredUsageCacheHitSummary, StoredUsageCostSavingsSummary, StoredUsageDailySummary,
StoredUsageDashboardDailyBreakdownRow, StoredUsageDashboardProviderCount,
StoredUsageDashboardSummary, StoredUsageErrorDistributionRow, StoredUsageLeaderboardSummary,
StoredUsagePerformancePercentilesRow, StoredUsageProviderPerformance,
StoredUsageSettledCostSummary, StoredUsageTimeSeriesBucket, StoredUsageUserTotals,
UsageAuditAggregationQuery, UsageAuditKeywordSearchQuery, UsageAuditListQuery,
UsageAuditSummaryQuery, UsageBreakdownSummaryQuery, UsageCacheAffinityHitSummaryQuery,
UsageCacheAffinityIntervalQuery, UsageCacheHitSummaryQuery, UsageCostSavingsSummaryQuery,
UsageDailyHeatmapQuery, UsageDashboardDailyBreakdownQuery, UsageDashboardProviderCountsQuery,
UsageDashboardSummaryQuery, UsageErrorDistributionQuery, UsageLeaderboardQuery,
UsageMonitoringErrorCountQuery, UsageMonitoringErrorListQuery,
UsagePerformancePercentilesQuery, UsageProviderPerformanceQuery, UsageReadRepository,
UsageSettledCostSummaryQuery, UsageTimeSeriesQuery,
};
use super::InMemoryUsageReadRepository;
use crate::driver::mysql::MysqlPool;
use crate::DataLayerError;
pub use aether_data_mysql::MysqlUsageWriteRepository;
use aether_data_mysql::{MysqlUsageReadFilter, MysqlUsageStorage};
#[derive(Debug, Clone)]
pub struct MysqlUsageReadRepository {
storage: MysqlUsageStorage,
}
impl MysqlUsageReadRepository {
pub fn new(pool: MysqlPool) -> Self {
Self {
storage: MysqlUsageStorage::new(pool),
}
}
async fn materialize_read_model(
&self,
filter: MysqlUsageReadFilter,
) -> Result<InMemoryUsageReadRepository, DataLayerError> {
Ok(InMemoryUsageReadRepository::seed(
self.storage.load_usage_records_in_range(&filter).await?,
))
}
fn range(created_from_unix_secs: u64, created_until_unix_secs: u64) -> MysqlUsageReadFilter {
MysqlUsageReadFilter::new(created_from_unix_secs, created_until_unix_secs)
}
}
#[async_trait::async_trait]
impl UsageReadRepository for MysqlUsageReadRepository {
async fn find_by_id(
&self,
id: &str,
) -> Result<Option<StoredRequestUsageAudit>, DataLayerError> {
self.storage.find_by_id(id).await
}
async fn list_by_ids(
&self,
ids: &[String],
) -> Result<Vec<StoredRequestUsageAudit>, DataLayerError> {
self.storage.list_by_ids(ids).await
}
async fn find_by_request_id(
&self,
request_id: &str,
) -> Result<Option<StoredRequestUsageAudit>, DataLayerError> {
self.storage.find_by_request_id(request_id).await
}
async fn resolve_body_ref(
&self,
body_ref: &str,
) -> Result<Option<serde_json::Value>, DataLayerError> {
self.storage.resolve_body_ref(body_ref).await
}
async fn list_usage_audits(
&self,
query: &UsageAuditListQuery,
) -> Result<Vec<StoredRequestUsageAudit>, DataLayerError> {
self.storage.list_usage_audits(query).await
}
async fn count_usage_audits(&self, query: &UsageAuditListQuery) -> Result<u64, DataLayerError> {
self.storage.count_usage_audits(query).await
}
async fn list_usage_audits_by_keyword_search(
&self,
query: &UsageAuditKeywordSearchQuery,
) -> Result<Vec<StoredRequestUsageAudit>, DataLayerError> {
self.storage
.list_usage_audits_by_keyword_search(query)
.await
}
async fn count_usage_audits_by_keyword_search(
&self,
query: &UsageAuditKeywordSearchQuery,
) -> Result<u64, DataLayerError> {
self.storage
.count_usage_audits_by_keyword_search(query)
.await
}
async fn aggregate_usage_audits(
&self,
query: &UsageAuditAggregationQuery,
) -> Result<Vec<StoredUsageAuditAggregation>, DataLayerError> {
let repository = self
.materialize_read_model(Self::range(
query.created_from_unix_secs,
query.created_until_unix_secs,
))
.await?;
repository.aggregate_usage_audits(query).await
}
async fn summarize_usage_audits(
&self,
query: &UsageAuditSummaryQuery,
) -> Result<StoredUsageAuditSummary, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_provider_name(query.provider_name.as_deref())
.with_model(query.model.as_deref());
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_audits(query).await
}
async fn summarize_usage_totals_by_user_ids(
&self,
user_ids: &[String],
) -> Result<Vec<StoredUsageUserTotals>, DataLayerError> {
self.storage
.summarize_usage_totals_by_user_ids(user_ids)
.await
}
async fn summarize_usage_cache_hit_summary(
&self,
query: &UsageCacheHitSummaryQuery,
) -> Result<StoredUsageCacheHitSummary, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref());
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_cache_hit_summary(query).await
}
async fn summarize_usage_settled_cost(
&self,
query: &UsageSettledCostSummaryQuery,
) -> Result<StoredUsageSettledCostSummary, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_api_key_id(query.api_key_id.as_deref());
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_settled_cost(query).await
}
async fn summarize_usage_cache_affinity_hit_summary(
&self,
query: &UsageCacheAffinityHitSummaryQuery,
) -> Result<StoredUsageCacheAffinityHitSummary, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_api_key_id(query.api_key_id.as_deref())
.completed_only();
let repository = self.materialize_read_model(filter).await?;
repository
.summarize_usage_cache_affinity_hit_summary(query)
.await
}
async fn list_usage_cache_affinity_intervals(
&self,
query: &UsageCacheAffinityIntervalQuery,
) -> Result<Vec<StoredUsageCacheAffinityIntervalRow>, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_api_key_id(query.api_key_id.as_deref())
.completed_only();
let repository = self.materialize_read_model(filter).await?;
repository.list_usage_cache_affinity_intervals(query).await
}
async fn summarize_dashboard_usage(
&self,
query: &UsageDashboardSummaryQuery,
) -> Result<StoredUsageDashboardSummary, DataLayerError> {
if query.created_from_unix_secs >= query.created_until_unix_secs {
return Ok(StoredUsageDashboardSummary::default());
}
if let Some(summary) = self
.storage
.summarize_dashboard_usage_from_daily_aggregates(query)
.await?
{
return Ok(summary);
}
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.finalized_only();
let repository = self.materialize_read_model(filter).await?;
repository.summarize_dashboard_usage(query).await
}
async fn list_dashboard_daily_breakdown(
&self,
query: &UsageDashboardDailyBreakdownQuery,
) -> Result<Vec<StoredUsageDashboardDailyBreakdownRow>, DataLayerError> {
if query.created_from_unix_secs >= query.created_until_unix_secs {
return Ok(Vec::new());
}
let rows = self
.storage
.list_dashboard_daily_breakdown_from_daily_aggregates(query)
.await?;
if !rows.is_empty() {
return Ok(rows);
}
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.finalized_only();
let repository = self.materialize_read_model(filter).await?;
repository.list_dashboard_daily_breakdown(query).await
}
async fn summarize_dashboard_provider_counts(
&self,
query: &UsageDashboardProviderCountsQuery,
) -> Result<Vec<StoredUsageDashboardProviderCount>, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.finalized_only();
let repository = self.materialize_read_model(filter).await?;
repository.summarize_dashboard_provider_counts(query).await
}
async fn summarize_usage_breakdown(
&self,
query: &UsageBreakdownSummaryQuery,
) -> Result<Vec<StoredUsageBreakdownSummaryRow>, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_provider_name(query.provider_name.as_deref())
.with_model(query.model.as_deref())
.with_api_format(query.api_format.as_deref())
.finalized_only();
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_breakdown(query).await
}
async fn count_monitoring_usage_errors(
&self,
query: &UsageMonitoringErrorCountQuery,
) -> Result<u64, DataLayerError> {
self.storage.count_monitoring_usage_errors(query).await
}
async fn list_monitoring_usage_errors(
&self,
query: &UsageMonitoringErrorListQuery,
) -> Result<Vec<StoredRequestUsageAudit>, DataLayerError> {
self.storage.list_monitoring_usage_errors(query).await
}
async fn summarize_usage_error_distribution(
&self,
query: &UsageErrorDistributionQuery,
) -> Result<Vec<StoredUsageErrorDistributionRow>, DataLayerError> {
let repository = self
.materialize_read_model(Self::range(
query.created_from_unix_secs,
query.created_until_unix_secs,
))
.await?;
repository.summarize_usage_error_distribution(query).await
}
async fn summarize_usage_performance_percentiles(
&self,
query: &UsagePerformancePercentilesQuery,
) -> Result<Vec<StoredUsagePerformancePercentilesRow>, DataLayerError> {
let repository = self
.materialize_read_model(
Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.completed_only(),
)
.await?;
repository
.summarize_usage_performance_percentiles(query)
.await
}
async fn summarize_usage_provider_performance(
&self,
query: &UsageProviderPerformanceQuery,
) -> Result<StoredUsageProviderPerformance, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_provider_id(query.provider_id.as_deref())
.with_model(query.model.as_deref())
.with_api_format(query.api_format.as_deref())
.with_endpoint_kind(query.endpoint_kind.as_deref())
.with_is_stream(query.is_stream)
.with_has_format_conversion(query.has_format_conversion)
.finalized_only();
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_provider_performance(query).await
}
async fn summarize_usage_cost_savings(
&self,
query: &UsageCostSavingsSummaryQuery,
) -> Result<StoredUsageCostSavingsSummary, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_provider_name(query.provider_name.as_deref())
.with_model(query.model.as_deref());
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_cost_savings(query).await
}
async fn summarize_usage_time_series(
&self,
query: &UsageTimeSeriesQuery,
) -> Result<Vec<StoredUsageTimeSeriesBucket>, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_provider_name(query.provider_name.as_deref())
.with_model(query.model.as_deref());
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_time_series(query).await
}
async fn summarize_usage_leaderboard(
&self,
query: &UsageLeaderboardQuery,
) -> Result<Vec<StoredUsageLeaderboardSummary>, DataLayerError> {
let filter = Self::range(query.created_from_unix_secs, query.created_until_unix_secs)
.with_user_id(query.user_id.as_deref())
.with_provider_name(query.provider_name.as_deref())
.with_model(query.model.as_deref())
.finalized_only();
let repository = self.materialize_read_model(filter).await?;
repository.summarize_usage_leaderboard(query).await
}
async fn list_recent_usage_audits(
&self,
user_id: Option<&str>,
limit: usize,
) -> Result<Vec<StoredRequestUsageAudit>, DataLayerError> {
self.storage.list_recent_usage_audits(user_id, limit).await
}
async fn summarize_total_tokens_by_api_key_ids(
&self,
api_key_ids: &[String],
) -> Result<BTreeMap<String, u64>, DataLayerError> {
let repository = InMemoryUsageReadRepository::seed(
self.storage
.load_usage_records_by_api_key_ids(api_key_ids)
.await?,
);
repository
.summarize_total_tokens_by_api_key_ids(api_key_ids)
.await
}
async fn summarize_usage_by_provider_api_key_ids(
&self,
provider_api_key_ids: &[String],
) -> Result<BTreeMap<String, StoredProviderApiKeyUsageSummary>, DataLayerError> {
let repository = InMemoryUsageReadRepository::seed(
self.storage
.load_usage_records_by_provider_api_key_ids(provider_api_key_ids)
.await?,
);
repository
.summarize_usage_by_provider_api_key_ids(provider_api_key_ids)
.await
}
async fn summarize_usage_by_provider_api_key_windows(
&self,
requests: &[ProviderApiKeyWindowUsageRequest],
) -> Result<Vec<StoredProviderApiKeyWindowUsageSummary>, DataLayerError> {
let repository = InMemoryUsageReadRepository::seed(
self.storage
.load_usage_records_by_provider_api_key_windows(requests)
.await?,
);
repository
.summarize_usage_by_provider_api_key_windows(requests)
.await
}
async fn summarize_provider_usage_since(
&self,
provider_id: &str,
since_unix_secs: u64,
) -> Result<StoredProviderUsageSummary, DataLayerError> {
let repository = InMemoryUsageReadRepository::seed(
self.storage
.load_usage_records_for_provider_since(provider_id, since_unix_secs)
.await?,
);
repository
.summarize_provider_usage_since(provider_id, since_unix_secs)
.await
}
async fn summarize_usage_daily_heatmap(
&self,
query: &UsageDailyHeatmapQuery,
) -> Result<Vec<StoredUsageDailySummary>, DataLayerError> {
self.storage.summarize_usage_daily_heatmap(query).await
}
async fn read_usage_counter_health(
&self,
) -> Result<aether_data_contracts::repository::usage::UsageCounterHealthSnapshot, DataLayerError>
{
self.storage.read_usage_counter_health().await
}
async fn read_usage_counter_pending_health(
&self,
) -> Result<
aether_data_contracts::repository::usage::UsageCounterPendingHealthSnapshot,
DataLayerError,
> {
self.storage.read_usage_counter_pending_health().await
}
}
#[cfg(test)]
mod tests {
#[test]
fn mysql_usage_reads_do_not_restore_the_unconditional_full_table_loader() {
let source = include_str!("mysql.rs");
let forbidden = ["load_usage_", "records()"].concat();
assert!(!source.contains(&forbidden));
assert!(source.contains("load_usage_records_in_range"));
assert!(source.contains("MysqlUsageReadFilter::new"));
}
}
@@ -11,10 +11,6 @@ pub use aether_data_contracts::repository::users::{
UserExportSortOrder, UserExportSummary, UserReadRepository, LAST_ACTIVE_ADMIN_DELETE_DENIED,
LAST_ACTIVE_ADMIN_UPDATE_DENIED,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlUserReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxUserReadRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteUserReadRepository;
pub use memory::InMemoryUserReadRepository;
@@ -6,10 +6,6 @@ pub(crate) use aether_data_contracts::repository::video_tasks::{
VideoTaskQueryFilter, VideoTaskReadRepository, VideoTaskRepository, VideoTaskStatus,
VideoTaskStatusCount, VideoTaskWriteRepository,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlVideoTaskRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::{SqlxVideoTaskReadRepository, SqlxVideoTaskRepository};
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteVideoTaskRepository;
pub use memory::InMemoryVideoTaskRepository;
@@ -42,10 +42,6 @@ pub use aether_data_contracts::repository::wallet::{
WalletReadRepository, WalletReadSeed, WalletReadSnapshot, WalletRepository,
WalletWriteRepository, WALLET_RECHARGE_CHECKOUT_CLAIM_LEASE_SECS,
};
#[cfg(feature = "mysql")]
pub use aether_data_mysql::MysqlWalletReadRepository;
#[cfg(feature = "postgres")]
pub use aether_data_postgres::SqlxWalletRepository;
#[cfg(feature = "sqlite")]
pub use aether_data_sqlite::SqliteWalletReadRepository;
pub use memory::InMemoryWalletRepository;