1
1
use anyhow:: { Context , Result } ;
2
- use redis:: { aio:: MultiplexedConnection , parse_redis_url, AsyncCommands , Client , RedisError } ;
2
+ use redis:: { aio:: ConnectionManager , parse_redis_url, AsyncCommands , Client , RedisError } ;
3
3
use spin_core:: async_trait;
4
4
use spin_factor_key_value:: { log_error, Cas , Error , Store , StoreManager , SwapError } ;
5
- use std:: ops:: DerefMut ;
6
5
use std:: sync:: Arc ;
7
- use tokio:: sync:: { Mutex , OnceCell } ;
6
+ use tokio:: sync:: OnceCell ;
8
7
use url:: Url ;
9
8
10
9
pub struct KeyValueRedis {
11
10
database_url : Url ,
12
- connection : OnceCell < Arc < Mutex < MultiplexedConnection > > > ,
11
+ connection : OnceCell < ConnectionManager > ,
13
12
}
14
13
15
14
impl KeyValueRedis {
@@ -30,10 +29,8 @@ impl StoreManager for KeyValueRedis {
30
29
. connection
31
30
. get_or_try_init ( || async {
32
31
Client :: open ( self . database_url . clone ( ) ) ?
33
- . get_multiplexed_async_connection ( )
32
+ . get_connection_manager ( )
34
33
. await
35
- . map ( Mutex :: new)
36
- . map ( Arc :: new)
37
34
} )
38
35
. await
39
36
. map_err ( log_error) ?;
@@ -55,90 +52,69 @@ impl StoreManager for KeyValueRedis {
55
52
}
56
53
57
54
struct RedisStore {
58
- connection : Arc < Mutex < MultiplexedConnection > > ,
55
+ connection : ConnectionManager ,
59
56
database_url : Url ,
60
57
}
61
58
62
59
struct CompareAndSwap {
63
60
key : String ,
64
- connection : Arc < Mutex < MultiplexedConnection > > ,
61
+ connection : ConnectionManager ,
65
62
bucket_rep : u32 ,
66
63
}
67
64
68
65
#[ async_trait]
69
66
impl Store for RedisStore {
67
+ async fn after_open ( & self ) -> Result < ( ) , Error > {
68
+ if let Err ( _error) = self . connection . clone ( ) . ping :: < ( ) > ( ) . await {
69
+ // If an IO error happens, ConnectionManager will start reconnection in the background
70
+ // so we do not take any action and just pray re-connection will be successful.
71
+ }
72
+ Ok ( ( ) )
73
+ }
74
+
70
75
async fn get ( & self , key : & str ) -> Result < Option < Vec < u8 > > , Error > {
71
- let mut conn = self . connection . lock ( ) . await ;
72
- conn. get ( key) . await . map_err ( log_error)
76
+ self . connection . clone ( ) . get ( key) . await . map_err ( log_error)
73
77
}
74
78
75
79
async fn set ( & self , key : & str , value : & [ u8 ] ) -> Result < ( ) , Error > {
76
80
self . connection
77
- . lock ( )
78
- . await
81
+ . clone ( )
79
82
. set ( key, value)
80
83
. await
81
84
. map_err ( log_error)
82
85
}
83
86
84
87
async fn delete ( & self , key : & str ) -> Result < ( ) , Error > {
85
- self . connection
86
- . lock ( )
87
- . await
88
- . del ( key)
89
- . await
90
- . map_err ( log_error)
88
+ self . connection . clone ( ) . del ( key) . await . map_err ( log_error)
91
89
}
92
90
93
91
async fn exists ( & self , key : & str ) -> Result < bool , Error > {
94
- self . connection
95
- . lock ( )
96
- . await
97
- . exists ( key)
98
- . await
99
- . map_err ( log_error)
92
+ self . connection . clone ( ) . exists ( key) . await . map_err ( log_error)
100
93
}
101
94
102
95
async fn get_keys ( & self ) -> Result < Vec < String > , Error > {
103
- self . connection
104
- . lock ( )
105
- . await
106
- . keys ( "*" )
107
- . await
108
- . map_err ( log_error)
96
+ self . connection . clone ( ) . keys ( "*" ) . await . map_err ( log_error)
109
97
}
110
98
111
99
async fn get_many ( & self , keys : Vec < String > ) -> Result < Vec < ( String , Option < Vec < u8 > > ) > , Error > {
112
- self . connection
113
- . lock ( )
114
- . await
115
- . keys ( keys)
116
- . await
117
- . map_err ( log_error)
100
+ self . connection . clone ( ) . keys ( keys) . await . map_err ( log_error)
118
101
}
119
102
120
103
async fn set_many ( & self , key_values : Vec < ( String , Vec < u8 > ) > ) -> Result < ( ) , Error > {
121
104
self . connection
122
- . lock ( )
123
- . await
105
+ . clone ( )
124
106
. mset ( & key_values)
125
107
. await
126
108
. map_err ( log_error)
127
109
}
128
110
129
111
async fn delete_many ( & self , keys : Vec < String > ) -> Result < ( ) , Error > {
130
- self . connection
131
- . lock ( )
132
- . await
133
- . del ( keys)
134
- . await
135
- . map_err ( log_error)
112
+ self . connection . clone ( ) . del ( keys) . await . map_err ( log_error)
136
113
}
137
114
138
115
async fn increment ( & self , key : String , delta : i64 ) -> Result < i64 , Error > {
139
116
self . connection
140
- . lock ( )
141
- . await
117
+ . clone ( )
142
118
. incr ( key, delta)
143
119
. await
144
120
. map_err ( log_error)
@@ -154,10 +130,8 @@ impl Store for RedisStore {
154
130
) -> Result < Arc < dyn Cas > , Error > {
155
131
let cx = Client :: open ( self . database_url . clone ( ) )
156
132
. map_err ( log_error) ?
157
- . get_multiplexed_async_connection ( )
133
+ . get_connection_manager ( )
158
134
. await
159
- . map ( Mutex :: new)
160
- . map ( Arc :: new)
161
135
. map_err ( log_error) ?;
162
136
163
137
Ok ( Arc :: new ( CompareAndSwap {
@@ -175,12 +149,11 @@ impl Cas for CompareAndSwap {
175
149
async fn current ( & self ) -> Result < Option < Vec < u8 > > , Error > {
176
150
redis:: cmd ( "WATCH" )
177
151
. arg ( & self . key )
178
- . exec_async ( self . connection . lock ( ) . await . deref_mut ( ) )
152
+ . exec_async ( & mut self . connection . clone ( ) )
179
153
. await
180
154
. map_err ( log_error) ?;
181
155
self . connection
182
- . lock ( )
183
- . await
156
+ . clone ( )
184
157
. get ( & self . key )
185
158
. await
186
159
. map_err ( log_error)
@@ -194,12 +167,12 @@ impl Cas for CompareAndSwap {
194
167
let res: Result < ( ) , RedisError > = transaction
195
168
. atomic ( )
196
169
. set ( & self . key , value)
197
- . query_async ( self . connection . lock ( ) . await . deref_mut ( ) )
170
+ . query_async ( & mut self . connection . clone ( ) )
198
171
. await ;
199
172
200
173
redis:: cmd ( "UNWATCH" )
201
174
. arg ( & self . key )
202
- . exec_async ( self . connection . lock ( ) . await . deref_mut ( ) )
175
+ . exec_async ( & mut self . connection . clone ( ) )
203
176
. await
204
177
. map_err ( |err| SwapError :: CasFailed ( format ! ( "{err:?}" ) ) ) ?;
205
178
0 commit comments