@@ -7,6 +7,7 @@ use crate::{
7
7
use chrono:: { DateTime , Utc } ;
8
8
use firestore:: FirestoreDb ;
9
9
use futures:: { stream:: FuturesUnordered , StreamExt } ;
10
+ use tokio:: io:: AsyncReadExt ;
10
11
11
12
const CACHES_COLLECTION : & str = "caches" ;
12
13
@@ -19,19 +20,23 @@ pub struct MenuCache<'a> {
19
20
#[ derive( serde:: Serialize , serde:: Deserialize , Default ) ]
20
21
struct InDbMenuCache {
21
22
cached_at : DateTime < Utc > ,
22
- data : String ,
23
+ data : Vec < u8 > ,
23
24
}
24
25
25
- impl < ' a > From < InDbMenuCache > for MenuCache < ' a > {
26
- fn from ( cache : InDbMenuCache ) -> Self {
26
+ impl < ' a > MenuCache < ' a > {
27
+ async fn from_async ( cache : InDbMenuCache ) -> Self {
27
28
if cache. data . is_empty ( ) {
28
29
return MenuCache {
29
30
cached_at : cache. cached_at ,
30
31
locations : Locations :: default ( ) ,
31
32
} ;
32
33
}
34
+ let mut uncompressed =
35
+ async_compression:: tokio:: bufread:: GzipDecoder :: new ( cache. data . as_slice ( ) ) ;
36
+ let mut dst = String :: with_capacity ( cache. data . len ( ) * 8 ) ;
37
+ uncompressed. read_to_string ( & mut dst) . await ;
33
38
let locations: Locations =
34
- serde_json:: from_str ( & cache . data ) . expect ( "Data parse should always be valid" ) ;
39
+ serde_json:: from_str ( & dst ) . expect ( "Data parse should always be valid" ) ;
35
40
MenuCache {
36
41
cached_at : cache. cached_at ,
37
42
locations,
@@ -42,9 +47,14 @@ impl<'a> From<InDbMenuCache> for MenuCache<'a> {
42
47
impl < ' a > TryFrom < MenuCache < ' a > > for InDbMenuCache {
43
48
type Error = crate :: error:: Error ;
44
49
fn try_from ( cache : MenuCache < ' a > ) -> Result < Self , Error > {
50
+ let mut json = serde_json:: to_string ( & cache. locations ) ?;
51
+ let mut compressed = Vec :: with_capacity ( json. len ( ) / 4 ) ;
52
+ let mut compress =
53
+ async_compression:: tokio:: bufread:: GzipEncoder :: new ( std:: io:: Cursor :: new ( json) ) ;
54
+ compress. read_buf ( & mut compressed) ;
45
55
Ok ( Self {
46
56
cached_at : cache. cached_at ,
47
- data : serde_json :: to_string ( & cache . locations ) ? ,
57
+ data : compressed ,
48
58
} )
49
59
}
50
60
}
@@ -82,18 +92,23 @@ impl<'a> MenuCache<'a> {
82
92
. one ( "menu" )
83
93
. await ?
84
94
. unwrap_or_default ( ) ; // default is an empty cache
85
- Ok ( cache . into ( ) )
95
+ Ok ( MenuCache :: from_async ( cache ) . await )
86
96
}
87
97
88
- fn to_db_representation ( & self ) -> InDbMenuCache {
98
+ async fn to_db_representation ( & self ) -> InDbMenuCache {
99
+ let json = serde_json:: to_string ( self . locations ( ) ) . unwrap ( ) ;
100
+ let mut compressed = Vec :: with_capacity ( json. len ( ) / 4 ) ;
101
+ let mut compress =
102
+ async_compression:: tokio:: bufread:: GzipEncoder :: new ( std:: io:: Cursor :: new ( json) ) ;
103
+ compress. read_buf ( & mut compressed) . await ;
89
104
InDbMenuCache {
90
- data : serde_json:: to_string ( & self . locations ) . unwrap ( ) ,
91
105
cached_at : self . cached_at ,
106
+ data : compressed,
92
107
}
93
108
}
94
109
95
110
async fn save_to_db ( & self ) -> Result < ( ) , firestore:: errors:: FirestoreError > {
96
- let cache: InDbMenuCache = self . to_db_representation ( ) ;
111
+ let cache: InDbMenuCache = self . to_db_representation ( ) . await ;
97
112
let db = FirestoreDb :: new ( "ucsc-menu" ) . await ?;
98
113
db. fluent ( )
99
114
. update ( )
0 commit comments