mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
Add multi-database data layer
Introduce aether-data-schema and driver-specific schema generation for Postgres, MySQL, and SQLite. Split data backends, lifecycle, repositories, and gateway runtime integration across database drivers. Verified with cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace.
This commit is contained in:
@@ -4,6 +4,6 @@ pub(crate) use aether_data::repository::wallet::{
|
||||
AdminWalletTransactionRecord,
|
||||
};
|
||||
pub(crate) use aether_data_contracts::repository::billing::{
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingPresetApplyResult,
|
||||
AdminBillingRuleRecord, AdminBillingRuleWriteInput,
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingMutationOutcome,
|
||||
AdminBillingPresetApplyResult, AdminBillingRuleRecord, AdminBillingRuleWriteInput,
|
||||
};
|
||||
|
||||
@@ -253,52 +253,39 @@ impl AppState {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub async fn run_postgres_migrations(&self) -> Result<bool, sqlx::migrate::MigrateError> {
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(false);
|
||||
};
|
||||
aether_data::migrate::run_migrations(&pool).await?;
|
||||
Ok(true)
|
||||
pub async fn run_database_migrations(&self) -> Result<bool, sqlx::migrate::MigrateError> {
|
||||
self.data.run_database_migrations().await
|
||||
}
|
||||
|
||||
pub async fn run_postgres_backfills(&self) -> Result<bool, sqlx::migrate::MigrateError> {
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(false);
|
||||
};
|
||||
aether_data::backfill::run_backfills(&pool).await?;
|
||||
Ok(true)
|
||||
pub async fn run_database_backfills(&self) -> Result<bool, sqlx::migrate::MigrateError> {
|
||||
self.data.run_database_backfills().await
|
||||
}
|
||||
|
||||
pub async fn pending_postgres_migrations(
|
||||
pub async fn pending_database_migrations(
|
||||
&self,
|
||||
) -> Result<Option<Vec<aether_data::migrate::PendingMigrationInfo>>, sqlx::migrate::MigrateError>
|
||||
{
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(aether_data::migrate::pending_migrations(&pool).await?))
|
||||
) -> Result<
|
||||
Option<Vec<aether_data::lifecycle::migrate::PendingMigrationInfo>>,
|
||||
sqlx::migrate::MigrateError,
|
||||
> {
|
||||
self.data.pending_database_migrations().await
|
||||
}
|
||||
|
||||
pub async fn prepare_postgres_for_startup(
|
||||
pub async fn prepare_database_for_startup(
|
||||
&self,
|
||||
) -> Result<Option<Vec<aether_data::migrate::PendingMigrationInfo>>, sqlx::migrate::MigrateError>
|
||||
{
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(
|
||||
aether_data::migrate::prepare_database_for_startup(&pool).await?,
|
||||
))
|
||||
) -> Result<
|
||||
Option<Vec<aether_data::lifecycle::migrate::PendingMigrationInfo>>,
|
||||
sqlx::migrate::MigrateError,
|
||||
> {
|
||||
self.data.prepare_database_for_startup().await
|
||||
}
|
||||
|
||||
pub async fn pending_postgres_backfills(
|
||||
pub async fn pending_database_backfills(
|
||||
&self,
|
||||
) -> Result<Option<Vec<aether_data::backfill::PendingBackfillInfo>>, sqlx::migrate::MigrateError>
|
||||
{
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(aether_data::backfill::pending_backfills(&pool).await?))
|
||||
) -> Result<
|
||||
Option<Vec<aether_data::lifecycle::backfill::PendingBackfillInfo>>,
|
||||
sqlx::migrate::MigrateError,
|
||||
> {
|
||||
self.data.pending_database_backfills().await
|
||||
}
|
||||
|
||||
pub fn with_video_task_poller_config(mut self, interval: Duration, batch_size: usize) -> Self {
|
||||
@@ -753,14 +740,10 @@ impl AppState {
|
||||
self.data.has_redis_backend()
|
||||
}
|
||||
|
||||
pub(crate) fn redis_kv_runner(&self) -> Option<aether_data::redis::RedisKvRunner> {
|
||||
pub(crate) fn redis_kv_runner(&self) -> Option<aether_data::driver::redis::RedisKvRunner> {
|
||||
self.data.kv_runner()
|
||||
}
|
||||
|
||||
pub(crate) fn postgres_pool(&self) -> Option<aether_data::postgres::PostgresPool> {
|
||||
self.data.postgres_pool()
|
||||
}
|
||||
|
||||
pub(crate) fn remove_scheduler_affinity_cache_entry(&self, cache_key: &str) -> bool {
|
||||
self.scheduler_affinity_cache.remove(cache_key).is_some()
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ mod types;
|
||||
mod video;
|
||||
|
||||
pub(crate) use self::admin_types::{
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingPresetApplyResult,
|
||||
AdminBillingRuleRecord, AdminBillingRuleWriteInput, AdminPaymentCallbackRecord,
|
||||
AdminSecurityBlacklistEntry, AdminWalletPaymentOrderRecord, AdminWalletRefundRecord,
|
||||
AdminWalletTransactionRecord,
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingMutationOutcome,
|
||||
AdminBillingPresetApplyResult, AdminBillingRuleRecord, AdminBillingRuleWriteInput,
|
||||
AdminPaymentCallbackRecord, AdminSecurityBlacklistEntry, AdminWalletPaymentOrderRecord,
|
||||
AdminWalletRefundRecord, AdminWalletTransactionRecord,
|
||||
};
|
||||
pub use self::app::AppState;
|
||||
pub(crate) use self::cache::{
|
||||
|
||||
@@ -155,6 +155,7 @@ impl AppState {
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn rotate_user_session_refresh_token(
|
||||
&self,
|
||||
user_id: &str,
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
use super::{
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingPresetApplyResult,
|
||||
AdminBillingRuleRecord, AdminBillingRuleWriteInput, AppState, GatewayError,
|
||||
LocalMutationOutcome,
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingMutationOutcome,
|
||||
AdminBillingPresetApplyResult, AdminBillingRuleRecord, AdminBillingRuleWriteInput, AppState,
|
||||
GatewayError, LocalMutationOutcome,
|
||||
};
|
||||
use crate::query::billing as billing_query;
|
||||
|
||||
fn data_error(err: impl ToString) -> GatewayError {
|
||||
GatewayError::Internal(err.to_string())
|
||||
}
|
||||
|
||||
fn local_mutation_outcome<T>(outcome: AdminBillingMutationOutcome<T>) -> LocalMutationOutcome<T> {
|
||||
match outcome {
|
||||
AdminBillingMutationOutcome::Applied(value) => LocalMutationOutcome::Applied(value),
|
||||
AdminBillingMutationOutcome::NotFound => LocalMutationOutcome::NotFound,
|
||||
AdminBillingMutationOutcome::Invalid(detail) => LocalMutationOutcome::Invalid(detail),
|
||||
AdminBillingMutationOutcome::Unavailable => LocalMutationOutcome::Unavailable,
|
||||
}
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn admin_billing_enabled_default_value_exists(
|
||||
@@ -30,17 +42,17 @@ impl AppState {
|
||||
return Ok(exists);
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(false);
|
||||
};
|
||||
billing_query::admin_billing_enabled_default_value_exists(
|
||||
&pool,
|
||||
api_format,
|
||||
task_type,
|
||||
dimension_name,
|
||||
existing_id,
|
||||
)
|
||||
.await
|
||||
Ok(self
|
||||
.data
|
||||
.admin_billing_enabled_default_value_exists(
|
||||
api_format,
|
||||
task_type,
|
||||
dimension_name,
|
||||
existing_id,
|
||||
)
|
||||
.await
|
||||
.map_err(data_error)?
|
||||
.unwrap_or(false))
|
||||
}
|
||||
|
||||
pub(crate) async fn create_admin_billing_rule(
|
||||
@@ -70,10 +82,11 @@ impl AppState {
|
||||
return Ok(LocalMutationOutcome::Applied(record));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(LocalMutationOutcome::Unavailable);
|
||||
};
|
||||
billing_query::create_admin_billing_rule(&pool, input).await
|
||||
self.data
|
||||
.create_admin_billing_rule(input)
|
||||
.await
|
||||
.map(local_mutation_outcome)
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn list_admin_billing_rules(
|
||||
@@ -111,13 +124,10 @@ impl AppState {
|
||||
return Ok(Some((items, total)));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
let (items, total) =
|
||||
billing_query::list_admin_billing_rules(&pool, task_type, is_enabled, page, page_size)
|
||||
.await?;
|
||||
Ok(Some((items, total)))
|
||||
self.data
|
||||
.list_admin_billing_rules(task_type, is_enabled, page, page_size)
|
||||
.await
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn read_admin_billing_rule(
|
||||
@@ -133,10 +143,10 @@ impl AppState {
|
||||
.cloned());
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
billing_query::find_admin_billing_rule(&pool, rule_id).await
|
||||
self.data
|
||||
.find_admin_billing_rule(rule_id)
|
||||
.await
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn update_admin_billing_rule(
|
||||
@@ -162,10 +172,11 @@ impl AppState {
|
||||
return Ok(LocalMutationOutcome::Applied(record.clone()));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(LocalMutationOutcome::Unavailable);
|
||||
};
|
||||
billing_query::update_admin_billing_rule(&pool, rule_id, input).await
|
||||
self.data
|
||||
.update_admin_billing_rule(rule_id, input)
|
||||
.await
|
||||
.map(local_mutation_outcome)
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn create_admin_billing_collector(
|
||||
@@ -197,10 +208,11 @@ impl AppState {
|
||||
return Ok(LocalMutationOutcome::Applied(record));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(LocalMutationOutcome::Unavailable);
|
||||
};
|
||||
billing_query::create_admin_billing_collector(&pool, input).await
|
||||
self.data
|
||||
.create_admin_billing_collector(input)
|
||||
.await
|
||||
.map(local_mutation_outcome)
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn list_admin_billing_collectors(
|
||||
@@ -243,20 +255,17 @@ impl AppState {
|
||||
return Ok(Some((items, total)));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
let (items, total) = billing_query::list_admin_billing_collectors(
|
||||
&pool,
|
||||
api_format,
|
||||
task_type,
|
||||
dimension_name,
|
||||
is_enabled,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Some((items, total)))
|
||||
self.data
|
||||
.list_admin_billing_collectors(
|
||||
api_format,
|
||||
task_type,
|
||||
dimension_name,
|
||||
is_enabled,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn read_admin_billing_collector(
|
||||
@@ -272,10 +281,10 @@ impl AppState {
|
||||
.cloned());
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(None);
|
||||
};
|
||||
billing_query::find_admin_billing_collector(&pool, collector_id).await
|
||||
self.data
|
||||
.find_admin_billing_collector(collector_id)
|
||||
.await
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn update_admin_billing_collector(
|
||||
@@ -305,10 +314,11 @@ impl AppState {
|
||||
return Ok(LocalMutationOutcome::Applied(record.clone()));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(LocalMutationOutcome::Unavailable);
|
||||
};
|
||||
billing_query::update_admin_billing_collector(&pool, collector_id, input).await
|
||||
self.data
|
||||
.update_admin_billing_collector(collector_id, input)
|
||||
.await
|
||||
.map(local_mutation_outcome)
|
||||
.map_err(data_error)
|
||||
}
|
||||
|
||||
pub(crate) async fn apply_admin_billing_preset(
|
||||
@@ -389,9 +399,10 @@ impl AppState {
|
||||
));
|
||||
}
|
||||
|
||||
let Some(pool) = self.postgres_pool() else {
|
||||
return Ok(LocalMutationOutcome::Unavailable);
|
||||
};
|
||||
billing_query::apply_admin_billing_preset(&pool, preset, mode, collectors).await
|
||||
self.data
|
||||
.apply_admin_billing_preset(preset, mode, collectors)
|
||||
.await
|
||||
.map(local_mutation_outcome)
|
||||
.map_err(data_error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::super::{
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingPresetApplyResult,
|
||||
AdminBillingRuleRecord, AdminBillingRuleWriteInput, AppState, GatewayError,
|
||||
LocalMutationOutcome,
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingMutationOutcome,
|
||||
AdminBillingPresetApplyResult, AdminBillingRuleRecord, AdminBillingRuleWriteInput, AppState,
|
||||
GatewayError, LocalMutationOutcome,
|
||||
};
|
||||
|
||||
mod admin;
|
||||
|
||||
@@ -13,6 +13,7 @@ mod auth;
|
||||
mod billing;
|
||||
mod candidate_queries;
|
||||
mod gemini_files;
|
||||
mod monitoring;
|
||||
mod payments;
|
||||
mod security;
|
||||
mod usage_queries;
|
||||
@@ -77,13 +78,21 @@ impl AppState {
|
||||
self.data.has_wallet_writer()
|
||||
}
|
||||
|
||||
pub fn has_database_wallet_data_writer(&self) -> bool {
|
||||
self.data.has_wallet_writer() && self.data.database_driver().is_some()
|
||||
}
|
||||
|
||||
pub fn has_auth_user_write_capability(&self) -> bool {
|
||||
#[cfg(test)]
|
||||
if self.auth_user_store.is_some() {
|
||||
return true;
|
||||
}
|
||||
#[cfg(test)]
|
||||
if !self.data.has_backends() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.postgres_pool().is_some()
|
||||
self.data.has_user_reader()
|
||||
}
|
||||
|
||||
pub fn has_auth_wallet_write_capability(&self) -> bool {
|
||||
@@ -92,7 +101,7 @@ impl AppState {
|
||||
return true;
|
||||
}
|
||||
|
||||
self.postgres_pool().is_some()
|
||||
self.data.has_wallet_writer()
|
||||
}
|
||||
|
||||
pub fn has_provider_quota_data_writer(&self) -> bool {
|
||||
|
||||
136
apps/aether-gateway/src/state/runtime/monitoring.rs
Normal file
136
apps/aether-gateway/src/state/runtime/monitoring.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use aether_data::repository::audit::AuditLogListQuery;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use super::{AppState, GatewayError};
|
||||
|
||||
impl AppState {
|
||||
pub(crate) async fn list_admin_audit_logs(
|
||||
&self,
|
||||
cutoff_time: DateTime<Utc>,
|
||||
username_pattern: Option<&str>,
|
||||
event_type: Option<&str>,
|
||||
limit: usize,
|
||||
offset: usize,
|
||||
) -> Result<(Vec<Value>, usize), GatewayError> {
|
||||
let query = AuditLogListQuery {
|
||||
cutoff_unix_secs: cutoff_unix_secs(cutoff_time),
|
||||
username_pattern: username_pattern.map(str::to_string),
|
||||
event_type: event_type.map(str::to_string),
|
||||
limit,
|
||||
offset,
|
||||
};
|
||||
let page = self
|
||||
.data
|
||||
.list_admin_audit_logs(&query)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
GatewayError::Internal(format!("admin audit logs read failed: {err}"))
|
||||
})?;
|
||||
let total = usize::try_from(page.total).unwrap_or(usize::MAX);
|
||||
let items = page
|
||||
.items
|
||||
.iter()
|
||||
.map(|record| {
|
||||
json!({
|
||||
"id": record.id,
|
||||
"event_type": record.event_type,
|
||||
"user_id": record.user_id,
|
||||
"user_email": record.user_email,
|
||||
"user_username": record.user_username,
|
||||
"description": record.description,
|
||||
"ip_address": record.ip_address,
|
||||
"status_code": record.status_code,
|
||||
"error_message": record.error_message,
|
||||
"metadata": record.metadata,
|
||||
"created_at": record.created_at_rfc3339(),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok((items, total))
|
||||
}
|
||||
|
||||
pub(crate) async fn list_admin_suspicious_activities(
|
||||
&self,
|
||||
cutoff_time: DateTime<Utc>,
|
||||
) -> Result<Vec<Value>, GatewayError> {
|
||||
let activities = self
|
||||
.data
|
||||
.list_admin_suspicious_activities(cutoff_unix_secs(cutoff_time))
|
||||
.await
|
||||
.map_err(|err| {
|
||||
GatewayError::Internal(format!("admin suspicious activities read failed: {err}"))
|
||||
})?;
|
||||
Ok(activities
|
||||
.iter()
|
||||
.map(|record| {
|
||||
json!({
|
||||
"id": record.id,
|
||||
"event_type": record.event_type,
|
||||
"user_id": record.user_id,
|
||||
"description": record.description,
|
||||
"ip_address": record.ip_address,
|
||||
"metadata": record.metadata,
|
||||
"created_at": record.created_at_rfc3339(),
|
||||
})
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub(crate) async fn read_admin_user_behavior_event_counts(
|
||||
&self,
|
||||
user_id: &str,
|
||||
cutoff_time: DateTime<Utc>,
|
||||
) -> Result<BTreeMap<String, u64>, GatewayError> {
|
||||
self.data
|
||||
.read_admin_user_behavior_event_counts(user_id, cutoff_unix_secs(cutoff_time))
|
||||
.await
|
||||
.map_err(|err| {
|
||||
GatewayError::Internal(format!("admin user behavior read failed: {err}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn list_user_audit_logs(
|
||||
&self,
|
||||
user_id: &str,
|
||||
cutoff_time: DateTime<Utc>,
|
||||
event_type: Option<&str>,
|
||||
limit: usize,
|
||||
offset: usize,
|
||||
) -> Result<(Vec<Value>, usize), GatewayError> {
|
||||
let query = AuditLogListQuery {
|
||||
cutoff_unix_secs: cutoff_unix_secs(cutoff_time),
|
||||
username_pattern: None,
|
||||
event_type: event_type.map(str::to_string),
|
||||
limit,
|
||||
offset,
|
||||
};
|
||||
let page = self
|
||||
.data
|
||||
.list_user_audit_logs(user_id, &query)
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(format!("user audit logs read failed: {err}")))?;
|
||||
let total = usize::try_from(page.total).unwrap_or(usize::MAX);
|
||||
let items = page
|
||||
.items
|
||||
.iter()
|
||||
.map(|record| {
|
||||
json!({
|
||||
"id": record.id,
|
||||
"event_type": record.event_type,
|
||||
"description": record.description,
|
||||
"ip_address": record.ip_address,
|
||||
"status_code": record.status_code,
|
||||
"created_at": record.created_at_rfc3339(),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok((items, total))
|
||||
}
|
||||
}
|
||||
|
||||
fn cutoff_unix_secs(cutoff_time: DateTime<Utc>) -> u64 {
|
||||
cutoff_time.timestamp().max(0) as u64
|
||||
}
|
||||
@@ -1,10 +1,3 @@
|
||||
use sqlx::Row;
|
||||
|
||||
use super::{
|
||||
AdminBillingCollectorRecord, AdminBillingRuleRecord, AdminWalletPaymentOrderRecord,
|
||||
AdminWalletRefundRecord, GatewayError,
|
||||
};
|
||||
|
||||
pub(crate) fn admin_wallet_build_order_no(now: chrono::DateTime<chrono::Utc>) -> String {
|
||||
format!(
|
||||
"po_{}_{}",
|
||||
@@ -21,274 +14,3 @@ pub(crate) fn admin_payment_gateway_response_map(
|
||||
_ => serde_json::Map::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn admin_wallet_snapshot_from_row(
|
||||
row: &sqlx::postgres::PgRow,
|
||||
) -> Result<aether_data::repository::wallet::StoredWalletSnapshot, GatewayError> {
|
||||
aether_data::repository::wallet::StoredWalletSnapshot::new(
|
||||
row.try_get("id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("user_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("api_key_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("balance")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("gift_balance")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("limit_mode")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("currency")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("status")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("total_recharged")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("total_consumed")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("total_refunded")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("total_adjusted")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
row.try_get("updated_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
)
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))
|
||||
}
|
||||
|
||||
pub(super) fn admin_wallet_payment_order_from_row(
|
||||
row: &sqlx::postgres::PgRow,
|
||||
) -> Result<AdminWalletPaymentOrderRecord, GatewayError> {
|
||||
Ok(AdminWalletPaymentOrderRecord {
|
||||
id: row
|
||||
.try_get("id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
order_no: row
|
||||
.try_get("order_no")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
wallet_id: row
|
||||
.try_get("wallet_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
user_id: row
|
||||
.try_get("user_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
amount_usd: row
|
||||
.try_get("amount_usd")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
pay_amount: row
|
||||
.try_get("pay_amount")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
pay_currency: row
|
||||
.try_get("pay_currency")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
exchange_rate: row
|
||||
.try_get("exchange_rate")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
refunded_amount_usd: row
|
||||
.try_get("refunded_amount_usd")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
refundable_amount_usd: row
|
||||
.try_get("refundable_amount_usd")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
payment_method: row
|
||||
.try_get("payment_method")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
gateway_order_id: row
|
||||
.try_get("gateway_order_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
status: row
|
||||
.try_get("status")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
gateway_response: row
|
||||
.try_get("gateway_response")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
created_at_unix_ms: row
|
||||
.try_get::<i64, _>("created_at_unix_ms")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
paid_at_unix_secs: row
|
||||
.try_get::<Option<i64>, _>("paid_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.map(|value| value.max(0) as u64),
|
||||
credited_at_unix_secs: row
|
||||
.try_get::<Option<i64>, _>("credited_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.map(|value| value.max(0) as u64),
|
||||
expires_at_unix_secs: row
|
||||
.try_get::<Option<i64>, _>("expires_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.map(|value| value.max(0) as u64),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn admin_wallet_refund_from_row(
|
||||
row: &sqlx::postgres::PgRow,
|
||||
) -> Result<AdminWalletRefundRecord, GatewayError> {
|
||||
Ok(AdminWalletRefundRecord {
|
||||
id: row
|
||||
.try_get("id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
refund_no: row
|
||||
.try_get("refund_no")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
wallet_id: row
|
||||
.try_get("wallet_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
user_id: row
|
||||
.try_get("user_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
payment_order_id: row
|
||||
.try_get("payment_order_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
source_type: row
|
||||
.try_get("source_type")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
source_id: row
|
||||
.try_get("source_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
refund_mode: row
|
||||
.try_get("refund_mode")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
amount_usd: row
|
||||
.try_get("amount_usd")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
status: row
|
||||
.try_get("status")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
reason: row
|
||||
.try_get("reason")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
failure_reason: row
|
||||
.try_get("failure_reason")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
gateway_refund_id: row
|
||||
.try_get("gateway_refund_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
payout_method: row
|
||||
.try_get("payout_method")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
payout_reference: row
|
||||
.try_get("payout_reference")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
payout_proof: row
|
||||
.try_get("payout_proof")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
requested_by: row
|
||||
.try_get("requested_by")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
approved_by: row
|
||||
.try_get("approved_by")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
processed_by: row
|
||||
.try_get("processed_by")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
created_at_unix_ms: row
|
||||
.try_get::<i64, _>("created_at_unix_ms")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
updated_at_unix_secs: row
|
||||
.try_get::<i64, _>("updated_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
processed_at_unix_secs: row
|
||||
.try_get::<Option<i64>, _>("processed_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.map(|value| value.max(0) as u64),
|
||||
completed_at_unix_secs: row
|
||||
.try_get::<Option<i64>, _>("completed_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.map(|value| value.max(0) as u64),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn admin_billing_rule_from_row(
|
||||
row: &sqlx::postgres::PgRow,
|
||||
) -> Result<AdminBillingRuleRecord, GatewayError> {
|
||||
Ok(AdminBillingRuleRecord {
|
||||
id: row
|
||||
.try_get("id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
name: row
|
||||
.try_get("name")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
task_type: row
|
||||
.try_get("task_type")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
global_model_id: row
|
||||
.try_get("global_model_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
model_id: row
|
||||
.try_get("model_id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
expression: row
|
||||
.try_get("expression")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
variables: row
|
||||
.try_get::<Option<serde_json::Value>, _>("variables")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.unwrap_or_else(|| serde_json::json!({})),
|
||||
dimension_mappings: row
|
||||
.try_get::<Option<serde_json::Value>, _>("dimension_mappings")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.unwrap_or_else(|| serde_json::json!({})),
|
||||
is_enabled: row
|
||||
.try_get("is_enabled")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
created_at_unix_ms: row
|
||||
.try_get::<i64, _>("created_at_unix_ms")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
updated_at_unix_secs: row
|
||||
.try_get::<i64, _>("updated_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn admin_billing_collector_from_row(
|
||||
row: &sqlx::postgres::PgRow,
|
||||
) -> Result<AdminBillingCollectorRecord, GatewayError> {
|
||||
Ok(AdminBillingCollectorRecord {
|
||||
id: row
|
||||
.try_get("id")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
api_format: row
|
||||
.try_get("api_format")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
task_type: row
|
||||
.try_get("task_type")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
dimension_name: row
|
||||
.try_get("dimension_name")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
source_type: row
|
||||
.try_get("source_type")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
source_path: row
|
||||
.try_get("source_path")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
value_type: row
|
||||
.try_get("value_type")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
transform_expression: row
|
||||
.try_get("transform_expression")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
default_value: row
|
||||
.try_get("default_value")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
priority: row
|
||||
.try_get("priority")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
is_enabled: row
|
||||
.try_get("is_enabled")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?,
|
||||
created_at_unix_ms: row
|
||||
.try_get::<i64, _>("created_at_unix_ms")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
updated_at_unix_secs: row
|
||||
.try_get::<i64, _>("updated_at_unix_secs")
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.max(0) as u64,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user