1
1
use crate :: dialoguer;
2
2
use anyhow:: Context ;
3
+ use chrono:: { NaiveDateTime , Utc } ;
3
4
use colored:: Colorize ;
4
- use crates_io:: schema:: crate_downloads;
5
+ use crates_io:: models:: NewDeletedCrate ;
6
+ use crates_io:: schema:: { crate_downloads, deleted_crates} ;
5
7
use crates_io:: worker:: jobs;
6
8
use crates_io:: { db, schema:: crates} ;
7
9
use crates_io_worker:: BackgroundJob ;
8
10
use diesel:: dsl:: sql;
9
11
use diesel:: expression:: SqlLiteral ;
10
12
use diesel:: prelude:: * ;
11
13
use 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 } ;
13
16
use std:: fmt:: Display ;
14
17
15
18
#[ derive( clap:: Parser , Debug ) ]
@@ -60,17 +63,27 @@ pub async fn run(opts: Opts) -> anyhow::Result<()> {
60
63
return Ok ( ( ) ) ;
61
64
}
62
65
66
+ let now = Utc :: now ( ) ;
67
+
63
68
for name in & crate_names {
64
69
if let Some ( crate_info) = existing_crates. iter ( ) . find ( |info| info. name == * name) {
65
70
let id = crate_info. id ;
66
71
72
+ let created_at = crate_info. created_at . and_utc ( ) ;
73
+ let deleted_crate = NewDeletedCrate :: builder ( name)
74
+ . created_at ( & created_at)
75
+ . deleted_at ( & now)
76
+ . available_at ( & now)
77
+ . build ( ) ;
78
+
67
79
info ! ( "{name}: Deleting crate from the database…" ) ;
68
- if let Err ( error) = diesel:: delete ( crates:: table. find ( id) )
69
- . execute ( & mut conn)
70
- . await
71
- {
80
+ let result = conn
81
+ . transaction ( |conn| delete_from_database ( conn, id, deleted_crate) . scope_boxed ( ) )
82
+ . await ;
83
+
84
+ if let Err ( error) = result {
72
85
warn ! ( %id, "{name}: Failed to delete crate from the database: {error}" ) ;
73
- }
86
+ } ;
74
87
} else {
75
88
info ! ( "{name}: Skipped missing crate" ) ;
76
89
} ;
@@ -96,12 +109,31 @@ pub async fn run(opts: Opts) -> anyhow::Result<()> {
96
109
Ok ( ( ) )
97
110
}
98
111
112
+ async fn delete_from_database (
113
+ conn : & mut AsyncPgConnection ,
114
+ crate_id : i32 ,
115
+ deleted_crate : NewDeletedCrate < ' _ > ,
116
+ ) -> anyhow:: Result < ( ) > {
117
+ diesel:: delete ( crates:: table. find ( crate_id) )
118
+ . execute ( conn)
119
+ . await ?;
120
+
121
+ diesel:: insert_into ( deleted_crates:: table)
122
+ . values ( deleted_crate)
123
+ . execute ( conn)
124
+ . await ?;
125
+
126
+ Ok ( ( ) )
127
+ }
128
+
99
129
#[ derive( Debug , Clone , Queryable , Selectable ) ]
100
130
struct CrateInfo {
101
131
#[ diesel( select_expression = crates:: columns:: name) ]
102
132
name : String ,
103
133
#[ diesel( select_expression = crates:: columns:: id) ]
104
134
id : i32 ,
135
+ #[ diesel( select_expression = crates:: columns:: created_at) ]
136
+ created_at : NaiveDateTime ,
105
137
#[ diesel( select_expression = crate_downloads:: columns:: downloads) ]
106
138
downloads : i64 ,
107
139
#[ diesel( select_expression = owners_subquery( ) ) ]
0 commit comments