]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/instance.rs
Make functions work with both connection and pool (#3420)
[lemmy.git] / crates / db_schema / src / impls / instance.rs
1 use crate::{
2   newtypes::InstanceId,
3   schema::{federation_allowlist, federation_blocklist, instance},
4   source::instance::{Instance, InstanceForm},
5   utils::{get_conn, naive_now, DbPool},
6 };
7 use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
8 use diesel_async::RunQueryDsl;
9
10 impl Instance {
11   /// Attempt to read Instance column for the given domain. If it doesnt exist, insert a new one.
12   /// There is no need for update as the domain of an existing instance cant change.
13   pub async fn read_or_create(pool: &mut DbPool<'_>, domain_: String) -> Result<Self, Error> {
14     use crate::schema::instance::domain;
15     let conn = &mut get_conn(pool).await?;
16
17     // First try to read the instance row and return directly if found
18     let instance = instance::table
19       .filter(domain.eq(&domain_))
20       .first::<Self>(conn)
21       .await;
22     match instance {
23       Ok(i) => Ok(i),
24       Err(diesel::NotFound) => {
25         // Instance not in database yet, insert it
26         let form = InstanceForm::builder()
27           .domain(domain_)
28           .updated(Some(naive_now()))
29           .build();
30         insert_into(instance::table)
31           .values(&form)
32           // Necessary because this method may be called concurrently for the same domain. This
33           // could be handled with a transaction, but nested transactions arent allowed
34           .on_conflict(instance::domain)
35           .do_update()
36           .set(&form)
37           .get_result::<Self>(conn)
38           .await
39       }
40       e => e,
41     }
42   }
43   pub async fn delete(pool: &mut DbPool<'_>, instance_id: InstanceId) -> Result<usize, Error> {
44     let conn = &mut get_conn(pool).await?;
45     diesel::delete(instance::table.find(instance_id))
46       .execute(conn)
47       .await
48   }
49   #[cfg(test)]
50   pub async fn delete_all(pool: &mut DbPool<'_>) -> Result<usize, Error> {
51     let conn = &mut get_conn(pool).await?;
52     diesel::delete(instance::table).execute(conn).await
53   }
54   pub async fn allowlist(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
55     let conn = &mut get_conn(pool).await?;
56     instance::table
57       .inner_join(federation_allowlist::table)
58       .select(instance::all_columns)
59       .get_results(conn)
60       .await
61   }
62
63   pub async fn blocklist(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
64     let conn = &mut get_conn(pool).await?;
65     instance::table
66       .inner_join(federation_blocklist::table)
67       .select(instance::all_columns)
68       .get_results(conn)
69       .await
70   }
71
72   pub async fn linked(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
73     let conn = &mut get_conn(pool).await?;
74     instance::table
75       .left_join(federation_blocklist::table)
76       .filter(federation_blocklist::id.is_null())
77       .select(instance::all_columns)
78       .get_results(conn)
79       .await
80   }
81 }