1
- use std:: env;
2
1
use std:: fmt:: Write ;
3
2
use std:: net:: SocketAddr ;
4
3
use std:: path:: PathBuf ;
5
4
use std:: str:: FromStr ;
6
5
use std:: sync:: Arc ;
6
+ use std:: { env, fs} ;
7
7
8
8
use anyhow:: { anyhow, Context as _, Error , Result } ;
9
9
use axum:: async_trait;
10
10
use clap:: { Parser , Subcommand , ValueEnum } ;
11
11
use docs_rs:: cdn:: CdnBackend ;
12
12
use docs_rs:: db:: { self , add_path_into_database, Overrides , Pool , PoolClient } ;
13
13
use docs_rs:: repositories:: RepositoryStatsUpdater ;
14
+ use docs_rs:: storage:: { rustdoc_archive_path, source_archive_path, PathNotFoundError } ;
14
15
use docs_rs:: utils:: {
15
16
get_config, get_crate_pattern_and_priority, list_crate_priorities, queue_builder,
16
- remove_crate_priority, set_config, set_crate_priority, ConfigName ,
17
+ remove_crate_priority, set_config, set_crate_priority, spawn_blocking , ConfigName ,
17
18
} ;
18
19
use docs_rs:: {
19
20
start_background_metrics_webserver, start_web_server, AsyncStorage , BuildQueue , Config ,
@@ -23,6 +24,7 @@ use docs_rs::{
23
24
use futures_util:: StreamExt ;
24
25
use humantime:: Duration ;
25
26
use once_cell:: sync:: OnceCell ;
27
+ use rusqlite:: { Connection , OpenFlags } ;
26
28
use sentry:: TransactionContext ;
27
29
use tokio:: runtime:: { Builder , Runtime } ;
28
30
use tracing_log:: LogTracer ;
@@ -509,6 +511,9 @@ enum DatabaseSubcommand {
509
511
/// temporary commant to update the `crates.latest_version_id` field
510
512
UpdateLatestVersionId ,
511
513
514
+ /// temporary command to rebuild a subset of the archive indexes
515
+ FixBrokenArchiveIndexes ,
516
+
512
517
/// Updates Github/Gitlab stats for crates.
513
518
UpdateRepositoryFields ,
514
519
@@ -567,6 +572,80 @@ impl DatabaseSubcommand {
567
572
. context ( "Failed to run database migrations" ) ?
568
573
}
569
574
575
+ Self :: FixBrokenArchiveIndexes => {
576
+ let pool = ctx. pool ( ) ?;
577
+ let build_queue = ctx. build_queue ( ) ?;
578
+ ctx. runtime ( ) ?
579
+ . block_on ( async {
580
+ let storage = ctx. async_storage ( ) . await ?;
581
+ let mut conn = pool. get_async ( ) . await ?;
582
+ let mut result_stream = sqlx:: query!(
583
+ "
584
+ SELECT c.name, r.version, r.release_time
585
+ FROM crates c, releases r
586
+ WHERE c.id = r.crate_id
587
+ ORDER BY r.id
588
+ "
589
+ )
590
+ . fetch ( & mut * conn) ;
591
+
592
+ while let Some ( row) = result_stream. next ( ) . await {
593
+ let row = row?;
594
+
595
+ println ! (
596
+ "checking index for {} {} ({:?})" ,
597
+ row. name, row. version, row. release_time
598
+ ) ;
599
+
600
+ for path in & [
601
+ rustdoc_archive_path ( & row. name , & row. version ) ,
602
+ source_archive_path ( & row. name , & row. version ) ,
603
+ ] {
604
+ let local_archive_index_filename = match storage
605
+ . download_archive_index ( path, 42 )
606
+ . await
607
+ {
608
+ Ok ( path) => path,
609
+ Err ( err)
610
+ if err. downcast_ref :: < PathNotFoundError > ( ) . is_some ( ) =>
611
+ {
612
+ continue
613
+ }
614
+ Err ( err) => return Err ( err) ,
615
+ } ;
616
+
617
+ let count = {
618
+ let connection = Connection :: open_with_flags (
619
+ & local_archive_index_filename,
620
+ OpenFlags :: SQLITE_OPEN_READ_ONLY
621
+ | OpenFlags :: SQLITE_OPEN_NO_MUTEX ,
622
+ ) ?;
623
+ let mut stmt =
624
+ connection. prepare ( "SELECT count(*) FROM files" ) ?;
625
+
626
+ stmt. query_row ( [ ] , |row| Ok ( row. get :: < _ , usize > ( 0 ) ) ) ??
627
+ } ;
628
+
629
+ fs:: remove_file ( & local_archive_index_filename) ?;
630
+
631
+ if count >= 65000 {
632
+ println ! ( "...big index, queueing rebuild" ) ;
633
+ spawn_blocking ( {
634
+ let build_queue = build_queue. clone ( ) ;
635
+ let name = row. name . clone ( ) ;
636
+ let version = row. version . clone ( ) ;
637
+ move || build_queue. add_crate ( & name, & version, 5 , None )
638
+ } )
639
+ . await ?;
640
+ }
641
+ }
642
+ }
643
+
644
+ Ok :: < ( ) , anyhow:: Error > ( ( ) )
645
+ } )
646
+ . context ( "Failed to queue rebuilds for big documentation sizes" ) ?
647
+ }
648
+
570
649
Self :: UpdateLatestVersionId => {
571
650
let pool = ctx. pool ( ) ?;
572
651
ctx. runtime ( ) ?
@@ -581,7 +660,7 @@ impl DatabaseSubcommand {
581
660
while let Some ( row) = result_stream. next ( ) . await {
582
661
let row = row?;
583
662
584
- println ! ( "handling crate {}" , row. name) ;
663
+ println ! ( "handling crate {} " , row. name) ;
585
664
586
665
db:: update_latest_version_id ( & mut update_conn, row. id ) . await ?;
587
666
}
0 commit comments