@@ -30,6 +30,7 @@ use diesel::{
30
30
Connection as _,
31
31
} ;
32
32
use graph:: {
33
+ cheap_clone:: CheapClone ,
33
34
components:: store:: DeploymentLocator ,
34
35
data:: {
35
36
store:: scalar:: ToPrimitive ,
@@ -1886,8 +1887,9 @@ pub fn is_empty(conn: &mut PgConnection) -> Result<bool, StoreError> {
1886
1887
/// a query returns either success or anything but a
1887
1888
/// `Err(StoreError::DatabaseUnavailable)`. This only works for tables that
1888
1889
/// are mirrored through `refresh_tables`
1890
+ #[ derive( Clone , CheapClone ) ]
1889
1891
pub struct Mirror {
1890
- pools : Vec < ConnectionPool > ,
1892
+ pools : Arc < Vec < ConnectionPool > > ,
1891
1893
}
1892
1894
1893
1895
impl Mirror {
@@ -1917,6 +1919,7 @@ impl Mirror {
1917
1919
pools. push ( pool. clone ( ) ) ;
1918
1920
pools
1919
1921
} ) ;
1922
+ let pools = Arc :: new ( pools) ;
1920
1923
Mirror { pools }
1921
1924
}
1922
1925
@@ -1925,7 +1928,7 @@ impl Mirror {
1925
1928
/// used for non-critical uses like command line tools
1926
1929
pub fn primary_only ( primary : ConnectionPool ) -> Mirror {
1927
1930
Mirror {
1928
- pools : vec ! [ primary] ,
1931
+ pools : Arc :: new ( vec ! [ primary] ) ,
1929
1932
}
1930
1933
}
1931
1934
@@ -1940,7 +1943,7 @@ impl Mirror {
1940
1943
mut f : impl ' a
1941
1944
+ FnMut ( & mut PooledConnection < ConnectionManager < PgConnection > > ) -> Result < T , StoreError > ,
1942
1945
) -> Result < T , StoreError > {
1943
- for pool in & self . pools {
1946
+ for pool in self . pools . as_ref ( ) {
1944
1947
let mut conn = match pool. get ( ) {
1945
1948
Ok ( conn) => conn,
1946
1949
Err ( StoreError :: DatabaseUnavailable ) => continue ,
@@ -1955,6 +1958,27 @@ impl Mirror {
1955
1958
Err ( StoreError :: DatabaseUnavailable )
1956
1959
}
1957
1960
1961
+ /// An async version of `read` that spawns a blocking task to do the
1962
+ /// actual work. This is useful when you want to call `read` from an
1963
+ /// async context
1964
+ pub ( crate ) async fn read_async < T , F > ( & self , mut f : F ) -> Result < T , StoreError >
1965
+ where
1966
+ T : ' static + Send ,
1967
+ F : ' static
1968
+ + Send
1969
+ + FnMut ( & mut PooledConnection < ConnectionManager < PgConnection > > ) -> Result < T , StoreError > ,
1970
+ {
1971
+ let this = self . cheap_clone ( ) ;
1972
+ let res = graph:: spawn_blocking ( async move { this. read ( |conn| f ( conn) ) } ) . await ;
1973
+ match res {
1974
+ Ok ( v) => v,
1975
+ Err ( e) => Err ( internal_error ! (
1976
+ "spawn_blocking in read_async failed: {}" ,
1977
+ e
1978
+ ) ) ,
1979
+ }
1980
+ }
1981
+
1958
1982
/// Refresh the contents of mirrored tables from the primary (through
1959
1983
/// the fdw mapping that `ForeignServer` establishes)
1960
1984
pub ( crate ) fn refresh_tables (
@@ -2050,8 +2074,10 @@ impl Mirror {
2050
2074
self . read ( |conn| queries:: assignments ( conn, node) )
2051
2075
}
2052
2076
2053
- pub fn active_assignments ( & self , node : & NodeId ) -> Result < Vec < Site > , StoreError > {
2054
- self . read ( |conn| queries:: active_assignments ( conn, node) )
2077
+ pub async fn active_assignments ( & self , node : & NodeId ) -> Result < Vec < Site > , StoreError > {
2078
+ let node = node. clone ( ) ;
2079
+ self . read_async ( move |conn| queries:: active_assignments ( conn, & node) )
2080
+ . await
2055
2081
}
2056
2082
2057
2083
pub fn assigned_node ( & self , site : & Site ) -> Result < Option < NodeId > , StoreError > {
0 commit comments