refactor dataloader

This commit is contained in:
2026-06-02 20:36:05 +02:00
parent eb576c4878
commit 16f8a929d2
8 changed files with 172 additions and 126 deletions

View File

@@ -1,72 +0,0 @@
// use async_graphql::dataloader::*;
// use async_graphql::*;
// use itertools::Itertools;
// use std::collections::HashMap;
// use std::sync::Arc;
//
// use crate::models::gruppe_ansicht::{GruppeAnsicht, Herkunft};
// use crate::scalar::Id;
//
// pub struct BenutzerGruppenKumulativLoader {
// pub pool: sqlx::PgPool,
// }
//
// impl Loader<Id> for BenutzerGruppenKumulativLoader {
// type Value = Vec<GruppeAnsicht>;
// type Error = Arc<sqlx::Error>;
//
// async fn load(&self, keys: &[Id]) -> Result<HashMap<Id, Self::Value>, Self::Error> {
// let rows = sqlx::query!(
// r#"
// SELECT DISTINCT
// COALESCE(bg.benutzer_id, br.benutzer_id) AS benutzer_id,
// g.id AS gruppe_id,
// g.gruppenname,
// g.erstellt_am,
// g.geaendert_am,
// CASE WHEN br.benutzer_id IS NOT null THEN r.rollenname END AS rollenname,
// CASE
// WHEN bg.benutzer_id IS NOT NULL AND br.benutzer_id IS NOT NULL THEN 'beides'::gruppen_herkunft
// WHEN bg.benutzer_id IS NOT NULL THEN 'direkt'::gruppen_herkunft
// WHEN br.benutzer_id IS NOT NULL THEN 'indirekt'::gruppen_herkunft
// END AS "herkunft: Herkunft"
// FROM gruppen AS g
// LEFT JOIN
// benutzer_gruppen AS bg
// ON
// g.id = bg.gruppe_id
// AND bg.benutzer_id = ANY($1)
// LEFT JOIN rollen_gruppen AS rg ON g.id = rg.gruppe_id
// LEFT JOIN
// benutzer_rollen AS br
// ON
// rg.rolle_id = br.rolle_id
// AND br.benutzer_id = ANY($1)
// LEFT JOIN rollen AS r ON rg.rolle_id = r.id
// WHERE
// bg.benutzer_id = ANY($1)
// OR br.benutzer_id = ANY($1);
// "#,
// keys
// )
// .fetch_all(&self.pool)
// .await?
// .into_iter()
// .map(|row| {
// (
// row.benutzer_id.unwrap(),
// GruppeAnsicht {
// id: row.gruppe_id,
// gruppenname: row.gruppenname,
// rollenname: row.rollenname,
// herkunft: row.herkunft.unwrap(),
// erstellt_am: row.erstellt_am,
// geaendert_am: row.geaendert_am,
// },
// )
// })
// .into_group_map();
//
// Ok(rows)
// }
// }

View File

@@ -1,51 +0,0 @@
// use async_graphql::dataloader::*;
// use async_graphql::*;
// use itertools::Itertools;
// use std::collections::HashMap;
// use std::sync::Arc;
//
// use crate::domain::rolle::model::Rolle;
// use crate::scalar::Id;
//
// pub struct BenutzerRollenLoader {
// pub pool: sqlx::PgPool,
// }
//
// impl Loader<Id> for BenutzerRollenLoader {
// type Value = Vec<Rolle>;
// type Error = Arc<sqlx::Error>;
//
// async fn load(&self, keys: &[Id]) -> Result<HashMap<Id, Self::Value>, Self::Error> {
// let rows = sqlx::query!(
// r#"
// SELECT
// br.benutzer_id,
// r.id,
// r.rollenname,
// r.erstellt_am,
// r.geaendert_am
// FROM rollen AS r
// LEFT JOIN benutzer_rollen AS br ON r.id = br.rolle_id
// WHERE br.benutzer_id = ANY($1);
// "#,
// keys
// )
// .fetch_all(&self.pool)
// .await?
// .into_iter()
// .map(|row| {
// (
// row.benutzer_id,
// Rolle {
// id: row.id,
// rollenname: row.rollenname,
// erstellt_am: row.erstellt_am,
// geaendert_am: row.geaendert_am,
// },
// )
// })
// .into_group_map();
//
// Ok(rows)
// }
// }

View File

@@ -1,6 +1,3 @@
mod benutzer_gruppen_kumulativ;
mod benutzer_rollen;
use crate::domain::{
gruppe::dataloader::gruppen::GruppenLoader, rolle::dataloader::rollen::RollenLoader,
};

View File

@@ -0,0 +1,2 @@
pub mod benutzer_gruppen_kumulativ;
pub mod benutzer_rollen;

View File

@@ -0,0 +1,73 @@
use async_graphql::dataloader::*;
use async_graphql::*;
use itertools::Itertools;
use std::collections::HashMap;
use std::sync::Arc;
use crate::domain::benutzer::model::GruppeAnsicht;
use crate::domain::benutzer::model::Herkunft;
use crate::scalar::Id;
pub struct BenutzerGruppenKumulativLoader {
pub pool: sqlx::PgPool,
}
impl Loader<Id> for BenutzerGruppenKumulativLoader {
type Value = Vec<GruppeAnsicht>;
type Error = Arc<sqlx::Error>;
async fn load(&self, keys: &[Id]) -> Result<HashMap<Id, Self::Value>, Self::Error> {
let rows = sqlx::query!(
r#"
SELECT DISTINCT
COALESCE(bg.benutzer_id, br.benutzer_id) AS benutzer_id,
g.id AS gruppe_id,
g.gruppenname,
g.erstellt_am,
g.geaendert_am,
CASE WHEN br.benutzer_id IS NOT null THEN r.rollenname END AS rollenname,
CASE
WHEN bg.benutzer_id IS NOT NULL AND br.benutzer_id IS NOT NULL THEN 'beides'::gruppen_herkunft
WHEN bg.benutzer_id IS NOT NULL THEN 'direkt'::gruppen_herkunft
WHEN br.benutzer_id IS NOT NULL THEN 'indirekt'::gruppen_herkunft
END AS "herkunft: Herkunft"
FROM gruppen AS g
LEFT JOIN
benutzer_gruppen AS bg
ON
g.id = bg.gruppe_id
AND bg.benutzer_id = ANY($1)
LEFT JOIN rollen_gruppen AS rg ON g.id = rg.gruppe_id
LEFT JOIN
benutzer_rollen AS br
ON
rg.rolle_id = br.rolle_id
AND br.benutzer_id = ANY($1)
LEFT JOIN rollen AS r ON rg.rolle_id = r.id
WHERE
bg.benutzer_id = ANY($1)
OR br.benutzer_id = ANY($1);
"#,
keys
)
.fetch_all(&self.pool)
.await?
.into_iter()
.map(|row| {
(
row.benutzer_id.unwrap(),
GruppeAnsicht {
id: row.gruppe_id,
gruppenname: row.gruppenname,
rollenname: row.rollenname,
herkunft: row.herkunft.unwrap(),
erstellt_am: row.erstellt_am,
geaendert_am: row.geaendert_am,
},
)
})
.into_group_map();
Ok(rows)
}
}

View File

@@ -0,0 +1,51 @@
use async_graphql::dataloader::*;
use async_graphql::*;
use itertools::Itertools;
use std::collections::HashMap;
use std::sync::Arc;
use crate::domain::rolle::model::Rolle;
use crate::scalar::Id;
pub struct BenutzerRollenLoader {
pub pool: sqlx::PgPool,
}
impl Loader<Id> for BenutzerRollenLoader {
type Value = Vec<Rolle>;
type Error = Arc<sqlx::Error>;
async fn load(&self, keys: &[Id]) -> Result<HashMap<Id, Self::Value>, Self::Error> {
let rows = sqlx::query!(
r#"
SELECT
br.benutzer_id,
r.id,
r.rollenname,
r.erstellt_am,
r.geaendert_am
FROM rollen AS r
LEFT JOIN benutzer_rollen AS br ON r.id = br.rolle_id
WHERE br.benutzer_id = ANY($1);
"#,
keys
)
.fetch_all(&self.pool)
.await?
.into_iter()
.map(|row| {
(
row.benutzer_id,
Rolle {
id: row.id,
rollenname: row.rollenname,
erstellt_am: row.erstellt_am,
geaendert_am: row.geaendert_am,
},
)
})
.into_group_map();
Ok(rows)
}
}

View File

@@ -1,5 +1,8 @@
pub mod benutzer;
pub mod benutzer_create_input;
pub mod benutzer_gruppen_ansicht;
pub use benutzer::Benutzer;
pub use benutzer_create_input::BenutzerCreateInput;
pub use benutzer_gruppen_ansicht::GruppeAnsicht;
pub use benutzer_gruppen_ansicht::Herkunft;

View File

@@ -0,0 +1,43 @@
use async_graphql::{ComplexObject, Enum, SimpleObject};
use sqlx::Type;
use crate::scalar::{Id, Time};
/// Aus welcher Quelle die Gruppe stammt.
#[derive(Enum, Clone, Debug, Eq, Copy, PartialEq, Type)]
#[sqlx(type_name = "gruppen_herkunft", rename_all = "lowercase")]
pub enum Herkunft {
/// Die Gruppe wurde direkt dem Benutzer zugefügt
Direkt,
/// Die Gruppe wurde durch eine Rolle vergeben
Indirekt,
/// Die Gruppe ist sowohl direkt als auch indirekt zugefügt
Beides,
}
#[derive(sqlx::FromRow, SimpleObject, Clone, Debug)]
#[graphql(complex)]
pub struct GruppeAnsicht {
/// Die UUID einer Gruppe
pub id: Id,
/// Der Gruppenname
pub gruppenname: String,
/// Die Herkunft der Gruppe
pub herkunft: Herkunft,
/// Bei einer indirekten Zuweisung, wird der Rollenname angegeben
pub rollenname: Option<String>,
/// Wann die Gruppe erstellt wurde
pub erstellt_am: Time,
/// Wann die Gruppe geaendert wurde
pub geaendert_am: Time,
}
#[ComplexObject]
impl GruppeAnsicht {}