1- use chrono:: { DateTime , Utc } ;
1+ use chrono:: { DateTime , Duration , Utc } ;
2+ use futures:: { future:: Shared , FutureExt } ;
23use poem_openapi:: Object ;
34use serde:: { Deserialize , Serialize } ;
45use sqlx:: { query, query_as, query_scalar} ;
56
67use crate :: {
7- database:: Database , middlewares:: auth:: AccessibleResource , models:: user:: User , routes:: error:: HttpError , state:: State , utils:: id:: { generate_id, IdType }
8+ cache :: CachedValue , database:: Database , middlewares:: auth:: AccessibleResource , models:: user:: User , routes:: error:: HttpError , state:: State , utils:: id:: { generate_id, IdType }
89} ;
910
1011pub mod invite;
@@ -61,16 +62,10 @@ impl Team {
6162 . await
6263 }
6364
64- pub async fn delete_by_id (
65- db : & Database ,
66- team_id : impl AsRef < str > ,
67- ) -> Result < ( ) , sqlx:: Error > {
68- query ! (
69- "DELETE FROM teams WHERE team_id = $1" ,
70- team_id. as_ref( )
71- )
72- . execute ( & db. pool )
73- . await ?;
65+ pub async fn delete_by_id ( db : & Database , team_id : impl AsRef < str > ) -> Result < ( ) , sqlx:: Error > {
66+ query ! ( "DELETE FROM teams WHERE team_id = $1" , team_id. as_ref( ) )
67+ . execute ( & db. pool )
68+ . await ?;
7469
7570 Ok ( ( ) )
7671 }
@@ -92,18 +87,33 @@ impl Team {
9287 }
9388
9489 pub async fn is_member (
95- db : & Database ,
90+ state : & State ,
9691 team_id : impl AsRef < str > ,
9792 user_id : impl AsRef < str > ,
9893 ) -> Result < bool , sqlx:: Error > {
99- Ok ( query_scalar ! (
94+ let cache_key = format ! ( "team:{}:member:{}" , team_id. as_ref( ) , user_id. as_ref( ) ) ;
95+
96+ if let Some ( x) = state. cache . has ( & cache_key) . await {
97+ return Ok ( x. as_bool ( ) . unwrap_or ( false ) ) ;
98+ }
99+
100+ let x = query_scalar ! (
100101 "SELECT EXISTS (SELECT 1 FROM user_teams WHERE team_id = $1 AND user_id = $2) OR EXISTS (SELECT 1 FROM teams WHERE team_id = $1 AND owner_id = $2)" ,
101102 team_id. as_ref( ) ,
102103 user_id. as_ref( )
103104 )
104- . fetch_one ( & db . pool )
105+ . fetch_one ( & state . database . pool )
105106 . await ?
106- . unwrap_or ( false ) )
107+ . unwrap_or ( false ) ;
108+
109+ state. cache . raw . insert (
110+ cache_key,
111+ async move {
112+ CachedValue :: new_with_ttl ( serde_json:: Value :: from ( x) , Duration :: seconds ( 30 ) )
113+ } . boxed ( ) . shared ( ) ,
114+ ) ;
115+
116+ Ok ( x)
107117 }
108118
109119 pub async fn get_members (
@@ -124,7 +134,9 @@ pub struct TeamId<'a>(pub &'a str);
124134
125135impl < ' a > AccessibleResource for TeamId < ' a > {
126136 async fn has_access_to ( & self , state : & State , user_id : & str ) -> Result < bool , HttpError > {
127- let x = Team :: is_member ( & state. database , self . 0 , user_id) . await . map_err ( HttpError :: from) ?;
137+ let x = Team :: is_member ( & state, self . 0 , user_id)
138+ . await
139+ . map_err ( HttpError :: from) ?;
128140
129141 Ok ( x)
130142 }
0 commit comments