1
1
use crate :: server:: { AppData , CommonResponse } ;
2
+
2
3
use actix_web:: { error, web, HttpRequest , HttpResponse , Result } ;
3
4
use serde:: { Deserialize , Serialize } ;
4
5
use sql_client:: accepted_count:: AcceptedCountClient ;
5
6
use sql_client:: language_count:: LanguageCountClient ;
6
7
use sql_client:: rated_point_sum:: RatedPointSumClient ;
7
8
use sql_client:: streak:: StreakClient ;
8
9
use std:: ops:: Range ;
10
+ use async_trait:: async_trait;
9
11
10
12
#[ derive( Deserialize ) ]
11
13
struct UserRankRequest {
@@ -32,87 +34,108 @@ pub(crate) struct RankingResponseEntry {
32
34
33
35
const MAX_RANKING_RANGE_LENGTH : usize = 1_000 ;
34
36
35
- pub ( crate ) fn ranking < State , Fut , F , A > (
36
- f : F ,
37
- ) -> impl actix_web:: Handler < (
38
- HttpRequest ,
39
- web:: Data < AppData < A > > ,
40
- web:: Query < RankingRequest > ,
41
- ) >
42
- where
43
- State : Send + Sync + ' static + Clone ,
44
- F : Sync + Send + ' static + Copy + Fn ( web:: Data < AppData < A > > , Range < usize > ) -> Fut ,
45
- Fut : std:: future:: Future < Output = Result < Vec < RankingResponseEntry > > > + Send + ' static ,
46
- {
47
- move |request : HttpRequest , data : web:: Data < AppData < A > > , query : web:: Query < RankingRequest > | async move {
37
+ // HttpRequest が Sync + Send でないエラーはこれで解消する
38
+ // 実行時に問題があるようであれば (?Send) は外し、ranking の引数から request を除けば良さそう
39
+ #[ async_trait( ?Send ) ]
40
+ pub ( crate ) trait RankingSelector < A : Sync + Send + Clone + ' static > {
41
+ async fn fetch ( data : web:: Data < AppData < A > > , query : Range < usize > ) -> Result < Vec < RankingResponseEntry > > ;
42
+ async fn get_ranking ( request : HttpRequest , data : web:: Data < AppData < A > > , query : web:: Query < RankingRequest > ) -> Result < HttpResponse > {
48
43
let query = ( query. from ) ..( query. to ) ;
49
44
if query. len ( ) > MAX_RANKING_RANGE_LENGTH {
50
45
return Ok ( HttpResponse :: Ok ( ) . finish ( ) ) ;
51
46
}
52
- let ranking = f ( data, query) . await ?;
47
+ let ranking = Self :: fetch ( data, query) . await ?;
53
48
let response = HttpResponse :: json ( & ranking) ?;
54
49
<Result < HttpResponse > >:: Ok ( response)
55
50
}
56
51
}
57
52
58
- pub ( crate ) fn user_rank < State , Fut , F , A > (
59
- f : F ,
60
- ) -> impl actix_web:: Handler < (
61
- HttpRequest ,
62
- web:: Data < AppData < A > > ,
63
- web:: Query < UserRankRequest > ,
64
- ) >
65
- where
66
- State : Send + Sync + ' static + Clone ,
67
- F : Sync + Send + ' static + Copy + Fn ( web:: Data < AppData < A > > , & str ) -> Fut ,
68
- Fut : std:: future:: Future < Output = Result < Option < UserRankResponse > > > + Send + ' static ,
69
- {
70
- move |request : HttpRequest , data : web:: Data < AppData < A > > , query : web:: Query < UserRankRequest > | async move {
71
- {
72
- let user_rank = f ( data, & query. user ) . await ?;
73
- // map と ok_or に書き換えられる
74
- match user_rank {
75
- Some ( rank) => {
76
- let response = HttpResponse :: json ( & rank) ?;
77
- <Result < HttpResponse > >:: Ok ( response)
78
- }
79
- None => Ok ( HttpResponse :: NotFound ( ) . finish ( ) ) ,
53
+ #[ async_trait( ?Send ) ]
54
+ pub ( crate ) trait UserRankSelector < A : Sync + Send + Clone + ' static > {
55
+ async fn fetch ( data : web:: Data < AppData < A > > , query : & str ) -> Result < Option < UserRankResponse > > ;
56
+ async fn get_users_rank ( request : HttpRequest , data : web:: Data < AppData < A > > , query : web:: Query < UserRankRequest > ) -> Result < HttpResponse > {
57
+ let user_rank = Self :: fetch ( data, & query. user ) . await ?;
58
+ // map と ok_or に書き換えられる
59
+ match user_rank {
60
+ Some ( rank) => {
61
+ let response = HttpResponse :: json ( & rank) ?;
62
+ <Result < HttpResponse > >:: Ok ( response)
80
63
}
64
+ None => Ok ( HttpResponse :: NotFound ( ) . finish ( ) ) ,
81
65
}
82
66
}
83
67
}
84
68
85
- pub ( crate ) async fn get_streak_ranking < A > (
86
- data : web:: Data < AppData < A > > ,
87
- query : Range < usize > ,
88
- ) -> Result < Vec < RankingResponseEntry > > {
89
- let conn = data. pg_pool . clone ( ) ;
90
- let ranking = conn
91
- . load_streak_count_in_range ( query)
92
- . await
93
- . map_err ( error:: ErrorInternalServerError ) ?;
94
- Ok ( ranking
95
- . into_iter ( )
96
- . map ( |entry| RankingResponseEntry {
97
- user_id : entry. user_id ,
98
- count : entry. streak ,
99
- } )
100
- . collect ( ) )
69
+ pub ( crate ) struct StreakRanking ;
70
+
71
+ #[ async_trait( ?Send ) ]
72
+ impl < A : Sync + Send + Clone + ' static > RankingSelector < A > for StreakRanking {
73
+ async fn fetch ( data : web:: Data < AppData < A > > , query : Range < usize > ) -> Result < Vec < RankingResponseEntry > > {
74
+ let conn = data. pg_pool . clone ( ) ;
75
+ let ranking = conn
76
+ . load_streak_count_in_range ( query)
77
+ . await
78
+ . map_err ( error:: ErrorInternalServerError ) ?;
79
+ Ok ( ranking
80
+ . into_iter ( )
81
+ . map ( |entry| RankingResponseEntry {
82
+ user_id : entry. user_id ,
83
+ count : entry. streak ,
84
+ } )
85
+ . collect ( ) )
86
+ }
101
87
}
102
88
103
- pub ( crate ) async fn get_ac_ranking < A > (
104
- data : web:: Data < AppData < A > > ,
105
- query : Range < usize > ,
106
- ) -> Result < Vec < RankingResponseEntry > > {
107
- let conn = data. pg_pool . clone ( ) ;
108
- let ranking = conn. load_accepted_count_in_range ( query) . await . map_err ( error:: ErrorInternalServerError ) ?;
109
- Ok ( ranking
110
- . into_iter ( )
111
- . map ( |entry| RankingResponseEntry {
112
- user_id : entry. user_id ,
113
- count : entry. problem_count as i64 ,
114
- } )
115
- . collect ( ) )
89
+ #[ async_trait( ?Send ) ]
90
+ impl < A : Sync + Send + Clone + ' static > UserRankSelector < A > for StreakRanking {
91
+ async fn fetch ( data : web:: Data < AppData < A > > , user_id : & str ) -> Result < Option < UserRankResponse > > {
92
+ let conn = data. pg_pool . clone ( ) ;
93
+ let count = match conn. get_users_streak_count ( user_id) . await {
94
+ Some ( number) => number,
95
+ None => return Ok ( None ) ,
96
+ } ;
97
+ let rank = conn
98
+ . get_streak_count_rank ( count)
99
+ . await
100
+ . map_err ( error:: ErrorInternalServerError ) ?;
101
+ Ok ( Some ( UserRankResponse { count, rank } ) )
102
+ }
103
+ }
104
+
105
+ pub ( crate ) struct AcRanking ;
106
+
107
+ #[ async_trait( ?Send ) ]
108
+ impl < A : Sync + Send + Clone + ' static > RankingSelector < A > for AcRanking {
109
+ async fn fetch ( data : web:: Data < AppData < A > > , query : Range < usize > ) -> Result < Vec < RankingResponseEntry > > {
110
+ let conn = data. pg_pool . clone ( ) ;
111
+ let ranking = conn
112
+ . load_accepted_count_in_range ( query)
113
+ . await
114
+ . map_err ( error:: ErrorInternalServerError ) ?;
115
+ Ok ( ranking
116
+ . into_iter ( )
117
+ . map ( |entry| RankingResponseEntry {
118
+ user_id : entry. user_id ,
119
+ count : entry. problem_count as i64 ,
120
+ } )
121
+ . collect ( ) )
122
+ }
123
+ }
124
+
125
+ #[ async_trait( ?Send ) ]
126
+ impl < A : Sync + Send + Clone + ' static > UserRankSelector < A > for AcRanking {
127
+ async fn fetch ( data : web:: Data < AppData < A > > , user_id : & str ) -> Result < Option < UserRankResponse > > {
128
+ let conn = data. pg_pool . clone ( ) ;
129
+ let count = match conn. get_users_accepted_count ( user_id) . await {
130
+ Some ( number) => number,
131
+ None => return Ok ( None ) ,
132
+ } ;
133
+ let rank = conn
134
+ . get_accepted_count_rank ( count)
135
+ . await
136
+ . map_err ( error:: ErrorInternalServerError ) ?;
137
+ Ok ( Some ( UserRankResponse { count, rank } ) )
138
+ }
116
139
}
117
140
118
141
#[ derive( Deserialize ) ]
@@ -125,7 +148,7 @@ struct LanguageQuery {
125
148
pub ( crate ) async fn get_language_ranking < A > (
126
149
request : HttpRequest ,
127
150
data : web:: Data < AppData < A > > ,
128
- query : web:: Query < LanguageQuery >
151
+ query : web:: Query < LanguageQuery > ,
129
152
) -> Result < HttpResponse > {
130
153
let conn = data. pg_pool . clone ( ) ;
131
154
let range = ( query. from ) ..( query. to ) ;
@@ -135,7 +158,8 @@ pub(crate) async fn get_language_ranking<A>(
135
158
136
159
let ranking = conn
137
160
. load_language_count_in_range ( & query. language , range)
138
- . await . map_err ( error:: ErrorInternalServerError ) ?;
161
+ . await
162
+ . map_err ( error:: ErrorInternalServerError ) ?;
139
163
let ranking = ranking
140
164
. into_iter ( )
141
165
. map ( |entry| RankingResponseEntry {
@@ -147,32 +171,6 @@ pub(crate) async fn get_language_ranking<A>(
147
171
Ok ( response)
148
172
}
149
173
150
- pub ( crate ) async fn get_users_ac_rank < A > (
151
- data : web:: Data < AppData < A > > ,
152
- user_id : & str ,
153
- ) -> Result < Option < UserRankResponse > > {
154
- let conn = data. pg_pool . clone ( ) ;
155
- let count = match conn. get_users_accepted_count ( user_id) . await {
156
- Some ( number) => number,
157
- None => return Ok ( None ) ,
158
- } ;
159
- let rank = conn. get_accepted_count_rank ( count) . await . map_err ( error:: ErrorInternalServerError ) ?;
160
- Ok ( Some ( UserRankResponse { count, rank } ) )
161
- }
162
-
163
- pub ( crate ) async fn get_users_streak_rank < A > (
164
- data : web:: Data < AppData < A > > ,
165
- user_id : & str ,
166
- ) -> Result < Option < UserRankResponse > > {
167
- let conn = data. pg_pool . clone ( ) ;
168
- let count = match conn. get_users_streak_count ( user_id) . await {
169
- Some ( number) => number,
170
- None => return Ok ( None ) ,
171
- } ;
172
- let rank = conn. get_streak_count_rank ( count) . await . map_err ( error:: ErrorInternalServerError ) ?;
173
- Ok ( Some ( UserRankResponse { count, rank } ) )
174
- }
175
-
176
174
#[ derive( Debug , Deserialize ) ]
177
175
struct UsersLanguageQuery {
178
176
user : String ,
@@ -181,7 +179,7 @@ struct UsersLanguageQuery {
181
179
pub ( crate ) async fn get_users_language_rank < A > (
182
180
request : HttpRequest ,
183
181
data : web:: Data < AppData < A > > ,
184
- query : web:: Query < UsersLanguageQuery >
182
+ query : web:: Query < UsersLanguageQuery > ,
185
183
) -> Result < HttpResponse > {
186
184
#[ derive( Debug , Serialize ) ]
187
185
struct UsersLanguageResponse {
@@ -190,8 +188,14 @@ pub(crate) async fn get_users_language_rank<A>(
190
188
rank : i64 ,
191
189
}
192
190
let conn = data. pg_pool . clone ( ) ;
193
- let counts = conn. load_users_language_count ( & query. user ) . await . map_err ( error:: ErrorInternalServerError ) ?;
194
- let ranks = conn. load_users_language_count_rank ( & query. user ) . await . map_err ( error:: ErrorInternalServerError ) ?;
191
+ let counts = conn
192
+ . load_users_language_count ( & query. user )
193
+ . await
194
+ . map_err ( error:: ErrorInternalServerError ) ?;
195
+ let ranks = conn
196
+ . load_users_language_count_rank ( & query. user )
197
+ . await
198
+ . map_err ( error:: ErrorInternalServerError ) ?;
195
199
let info = counts
196
200
. into_iter ( )
197
201
. zip ( ranks)
@@ -205,21 +209,26 @@ pub(crate) async fn get_users_language_rank<A>(
205
209
Ok ( response)
206
210
}
207
211
208
- pub ( crate ) async fn get_users_rated_point_sum_rank < A > (
209
- data : web:: Data < AppData < A > > ,
210
- user_id : & str ,
211
- ) -> Result < Option < UserRankResponse > > {
212
- let conn = data. pg_pool . clone ( ) ;
213
- let point_sum = conn. get_users_rated_point_sum ( user_id) . await ;
214
- let point_sum = match point_sum {
215
- Some ( point_sum) => point_sum,
216
- None => return Ok ( None ) ,
217
- } ;
218
-
219
- let rank = conn. get_rated_point_sum_rank ( point_sum) . await . map_err ( error:: ErrorInternalServerError ) ?;
220
- let response = UserRankResponse {
221
- count : point_sum,
222
- rank,
223
- } ;
224
- Ok ( Some ( response) )
212
+ pub ( crate ) struct RatedPointSumRanking ;
213
+
214
+ #[ async_trait( ?Send ) ]
215
+ impl < A : Sync + Send + Clone + ' static > UserRankSelector < A > for RatedPointSumRanking {
216
+ async fn fetch ( data : web:: Data < AppData < A > > , user_id : & str ) -> Result < Option < UserRankResponse > > {
217
+ let conn = data. pg_pool . clone ( ) ;
218
+ let point_sum = conn. get_users_rated_point_sum ( user_id) . await ;
219
+ let point_sum = match point_sum {
220
+ Some ( point_sum) => point_sum,
221
+ None => return Ok ( None ) ,
222
+ } ;
223
+
224
+ let rank = conn
225
+ . get_rated_point_sum_rank ( point_sum)
226
+ . await
227
+ . map_err ( error:: ErrorInternalServerError ) ?;
228
+ let response = UserRankResponse {
229
+ count : point_sum,
230
+ rank,
231
+ } ;
232
+ Ok ( Some ( response) )
233
+ }
225
234
}
0 commit comments