@@ -5,7 +5,7 @@ use crate::{
5
5
db:: { Pool , PoolClient } ,
6
6
impl_webpage,
7
7
web:: { error:: Nope , match_version, page:: WebPage , redirect_base} ,
8
- BuildQueue ,
8
+ BuildQueue , Config ,
9
9
} ;
10
10
use chrono:: { DateTime , Utc } ;
11
11
use iron:: {
@@ -498,13 +498,18 @@ impl Default for Search {
498
498
}
499
499
500
500
fn redirect_to_random_crate ( req : & Request , conn : & mut PoolClient ) -> IronResult < Response > {
501
- // since there is a chance of this query returning an empty result,
502
- // we retry a certain amount of times, and log a warning.
503
- for i in 0 ..20 {
504
- let rows = ctry ! (
505
- req,
506
- conn. query(
507
- "WITH params AS (
501
+ // We try to find a random crate and redirect to it.
502
+ //
503
+ // The query is efficient, but relies on a static factor which depends
504
+ // on the amount of crates with > 100 GH stars over the amount of all crates.
505
+ //
506
+ // If random-crate-searches end up being empty, increase that value.
507
+
508
+ let config = extension ! ( req, Config ) ;
509
+ let rows = ctry ! (
510
+ req,
511
+ conn. query(
512
+ "WITH params AS (
508
513
-- get maximum possible id-value in crates-table
509
514
SELECT last_value AS max_id FROM crates_id_seq
510
515
)
@@ -513,55 +518,44 @@ fn redirect_to_random_crate(req: &Request, conn: &mut PoolClient) -> IronResult<
513
518
releases.version,
514
519
releases.target_name
515
520
FROM (
516
- -- generate 500 random numbers in the ID-range.
517
- -- this might have to be increased when we have to repeat
518
- -- this query too often.
519
- -- it depends on the percentage of crates with > 100 stars
521
+ -- generate random numbers in the ID-range.
520
522
SELECT DISTINCT 1 + trunc(random() * params.max_id)::INTEGER AS id
521
- FROM params, generate_series(1, 500 )
523
+ FROM params, generate_series(1, $1 )
522
524
) AS r
523
525
INNER JOIN crates ON r.id = crates.id
524
526
INNER JOIN releases ON crates.latest_version_id = releases.id
525
527
INNER JOIN github_repos ON releases.github_repo = github_repos.id
526
528
WHERE
527
529
releases.rustdoc_status = TRUE AND
528
530
github_repos.stars >= 100
529
- LIMIT 1
530
- " ,
531
- & [ ]
532
- ) ,
533
- ) ;
534
-
535
- if let Some ( row) = rows. into_iter ( ) . next ( ) {
536
- let name: String = row. get ( "name" ) ;
537
- let version: String = row. get ( "version" ) ;
538
- let target_name: String = row. get ( "target_name" ) ;
539
- let url = ctry ! (
540
- req,
541
- Url :: parse( & format!(
542
- "{}/{}/{}/{}/" ,
543
- redirect_base( req) ,
544
- name,
545
- version,
546
- target_name
547
- ) ) ,
548
- ) ;
531
+ LIMIT 1" ,
532
+ & [ & ( config. random_crate_search_view_size as i32 ) , ]
533
+ )
534
+ ) ;
549
535
550
- let mut resp = Response :: with ( ( status:: Found , Redirect ( url) ) ) ;
551
- resp. headers . set ( Expires ( HttpDate ( time:: now ( ) ) ) ) ;
536
+ if let Some ( row) = rows. into_iter ( ) . next ( ) {
537
+ let name: String = row. get ( "name" ) ;
538
+ let version: String = row. get ( "version" ) ;
539
+ let target_name: String = row. get ( "target_name" ) ;
540
+ let url = ctry ! (
541
+ req,
542
+ Url :: parse( & format!(
543
+ "{}/{}/{}/{}/" ,
544
+ redirect_base( req) ,
545
+ name,
546
+ version,
547
+ target_name
548
+ ) ) ,
549
+ ) ;
552
550
553
- let metrics = extension ! ( req, crate :: Metrics ) . clone ( ) ;
554
- metrics. im_feeling_lucky_searches . inc ( ) ;
551
+ let metrics = extension ! ( req, crate :: Metrics ) . clone ( ) ;
552
+ metrics. im_feeling_lucky_searches . inc ( ) ;
555
553
556
- log:: debug!( "finished random crate search on iteration {}" , i) ;
557
- return Ok ( resp) ;
558
- } else {
559
- log:: warn!( "retrying random crate search" ) ;
560
- }
554
+ Ok ( super :: redirect ( url) )
555
+ } else {
556
+ log:: error!( "found no result in random crate search" ) ;
557
+ Err ( Nope :: NoResults . into ( ) )
561
558
}
562
- log:: error!( "found no result in random crate search" ) ;
563
-
564
- Err ( Nope :: NoResults . into ( ) )
565
559
}
566
560
567
561
impl_webpage ! {
0 commit comments