Skip to content

Commit 9d33c5c

Browse files
committed
Auto merge of #3423 - pietroalbini:downloads-counter-tests, r=jtgeibel
Adds tests for DownloadsCounter This fixes #3416 by adding tests for `DownloadsCounter`. There are a few notable things in this PR I'd like to highlight. First off, the tests are not implemented in `src/tests`, but are implemented in a `#[cfg(test)] mod tests {}` in the same source file. While this resulted in some code duplication I had to do this because testing `persist_next_shard` requires access to the internals of `DownloadsCounter` and I'd prefer not to expose them. This PR also fixes a bug I discovered while writing the test for incrementing a missing version. Inserting a missing version ID in the `version_downloads` table doesn't work thanks to the foreign key, and aborts the whole `INSERT` statement (losing all the downloads in that shard). This could happen in production if a version is deleted between calling `increment()` and persisting that shard. To fix that bug I changed the code to do a `SELECT FOR SHARE` from the `versions` table of the version IDs we're about to persist, discarding the versions that are not returned by the query. The `FOR SHARE` clause does the equivalent of `RwLock::read`, preventing other transactions from updating or deleting the selected rows while allowing other `SELECT`s and `SELECT FOR SHARE`s. There were also some refactorings to make the tests better to write. This PR is best reviewed commit-by-commit. r? `@jtgeibel`
2 parents efe9d2e + c22ba7c commit 9d33c5c

File tree

5 files changed

+341
-70
lines changed

5 files changed

+341
-70
lines changed

src/bin/server.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
138138
rt.block_on(async { server.await.unwrap() });
139139

140140
println!("Persisting remaining downloads counters");
141-
if let Err(err) = app.downloads_counter.persist_all_shards(&app) {
142-
println!("downloads_counter error: {}", err);
141+
match app.downloads_counter.persist_all_shards(&app) {
142+
Ok(stats) => stats.log(),
143+
Err(err) => println!("downloads_counter error: {}", err),
143144
}
144145

145146
println!("Server has gracefully shutdown!");
@@ -154,8 +155,9 @@ fn downloads_counter_thread(app: Arc<App>) {
154155
std::thread::spawn(move || loop {
155156
std::thread::sleep(interval);
156157

157-
if let Err(err) = app.downloads_counter.persist_next_shard(&app) {
158-
println!("downloads_counter error: {}", err);
158+
match app.downloads_counter.persist_next_shard(&app) {
159+
Ok(stats) => stats.log(),
160+
Err(err) => println!("downloads_counter error: {}", err),
159161
}
160162
});
161163
}

src/db.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,10 @@ impl CustomizeConnection<PgConnection, r2d2::Error> for ConnectionConfig {
130130
Ok(())
131131
}
132132
}
133+
134+
#[cfg(test)]
135+
pub(crate) fn test_conn() -> PgConnection {
136+
let conn = PgConnection::establish(&crate::env("TEST_DATABASE_URL")).unwrap();
137+
conn.begin_test_transaction().unwrap();
138+
conn
139+
}

0 commit comments

Comments
 (0)