11use crate :: dialoguer;
22use anyhow:: Context ;
3+ use chrono:: { NaiveDateTime , Utc } ;
34use colored:: Colorize ;
4- use crates_io:: schema:: crate_downloads;
5+ use crates_io:: models:: NewDeletedCrate ;
6+ use crates_io:: schema:: { crate_downloads, deleted_crates} ;
57use crates_io:: worker:: jobs;
68use crates_io:: { db, schema:: crates} ;
79use crates_io_worker:: BackgroundJob ;
810use diesel:: dsl:: sql;
911use diesel:: expression:: SqlLiteral ;
1012use diesel:: prelude:: * ;
1113use diesel:: sql_types:: { Array , BigInt , Text } ;
12- use diesel_async:: RunQueryDsl ;
14+ use diesel_async:: scoped_futures:: ScopedFutureExt ;
15+ use diesel_async:: { AsyncConnection , AsyncPgConnection , RunQueryDsl } ;
1316use std:: fmt:: Display ;
1417
1518#[ derive( clap:: Parser , Debug ) ]
@@ -58,17 +61,27 @@ pub async fn run(opts: Opts) -> anyhow::Result<()> {
5861 return Ok ( ( ) ) ;
5962 }
6063
64+ let now = Utc :: now ( ) ;
65+
6166 for name in & crate_names {
6267 if let Some ( crate_info) = existing_crates. iter ( ) . find ( |info| info. name == * name) {
6368 let id = crate_info. id ;
6469
70+ let created_at = crate_info. created_at . and_utc ( ) ;
71+ let deleted_crate = NewDeletedCrate :: builder ( name)
72+ . created_at ( & created_at)
73+ . deleted_at ( & now)
74+ . available_at ( & now)
75+ . build ( ) ;
76+
6577 info ! ( "{name}: Deleting crate from the database…" ) ;
66- if let Err ( error) = diesel:: delete ( crates:: table. find ( id) )
67- . execute ( & mut conn)
68- . await
69- {
78+ let result = conn
79+ . transaction ( |conn| delete_from_database ( conn, id, deleted_crate) . scope_boxed ( ) )
80+ . await ;
81+
82+ if let Err ( error) = result {
7083 warn ! ( %id, "{name}: Failed to delete crate from the database: {error}" ) ;
71- }
84+ } ;
7285 } else {
7386 info ! ( "{name}: Skipped missing crate" ) ;
7487 } ;
@@ -94,12 +107,31 @@ pub async fn run(opts: Opts) -> anyhow::Result<()> {
94107 Ok ( ( ) )
95108}
96109
110+ async fn delete_from_database (
111+ conn : & mut AsyncPgConnection ,
112+ crate_id : i32 ,
113+ deleted_crate : NewDeletedCrate < ' _ > ,
114+ ) -> anyhow:: Result < ( ) > {
115+ diesel:: delete ( crates:: table. find ( crate_id) )
116+ . execute ( conn)
117+ . await ?;
118+
119+ diesel:: insert_into ( deleted_crates:: table)
120+ . values ( deleted_crate)
121+ . execute ( conn)
122+ . await ?;
123+
124+ Ok ( ( ) )
125+ }
126+
97127#[ derive( Debug , Clone , Queryable , Selectable ) ]
98128struct CrateInfo {
99129 #[ diesel( select_expression = crates:: columns:: name) ]
100130 name : String ,
101131 #[ diesel( select_expression = crates:: columns:: id) ]
102132 id : i32 ,
133+ #[ diesel( select_expression = crates:: columns:: created_at) ]
134+ created_at : NaiveDateTime ,
103135 #[ diesel( select_expression = crate_downloads:: columns:: downloads) ]
104136 downloads : i64 ,
105137 #[ diesel( select_expression = owners_subquery( ) ) ]
0 commit comments