Skip to content

Commit b155837

Browse files
committed
Try to build crates if there is any in queue
In addition to #90 this change will also run `build_queue` in it's own thread to catch panics (only panicked twice in last 6 months). This commit also introduces an attempt count to avoid endless tries to build yanked crates. This only happens if a crate gets yanked before docs.rs tries. docs.rs will only try to build a crate 5 times and ignore them after it but it will still leave it in queue for inspection.
1 parent c74827d commit b155837

File tree

4 files changed

+64
-28
lines changed

4 files changed

+64
-28
lines changed

src/db/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ pub fn create_tables(conn: &Connection) -> Result<(), Error> {
159159
id SERIAL, \
160160
name VARCHAR(255), \
161161
version VARCHAR(100), \
162+
attempt INT DEFAULT 0, \
163+
date_added TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
162164
UNIQUE(name, version) \
163165
)",
164166
"CREATE TABLE files ( \

src/docbuilder/queue.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,37 @@ use crates_index_diff::{ChangeKind, Index};
88

99

1010
impl DocBuilder {
11-
/// Updates crates.io-index repository and adds new crates into build queue
12-
pub fn get_new_crates(&mut self) -> Result<()> {
11+
/// Updates crates.io-index repository and adds new crates into build queue.
12+
/// Returns size of queue
13+
pub fn get_new_crates(&mut self) -> Result<i64> {
1314
let conn = try!(connect_db());
1415
let index = try!(Index::from_path_or_cloned(&self.options.crates_io_index_path));
15-
let changes = try!(index.fetch_changes());
16+
let mut changes = try!(index.fetch_changes());
17+
18+
// I belive this will fix ordering of queue if we get more than one crate from changes
19+
changes.reverse();
20+
1621
for krate in changes.iter().filter(|k| k.kind != ChangeKind::Yanked) {
1722
conn.execute("INSERT INTO queue (name, version) VALUES ($1, $2)",
1823
&[&krate.name, &krate.version]).ok();
24+
debug!("{}-{} added into build queue", krate.name, krate.version);
1925
}
2026

21-
Ok(())
27+
let queue_count = conn.query("SELECT COUNT(*) FROM queue WHERE attempt < 5",
28+
&[]).unwrap().get(0).get(0);
29+
30+
Ok(queue_count)
2231
}
2332

2433

2534
/// Builds packages from queue
2635
pub fn build_packages_queue(&mut self) -> Result<()> {
2736
let conn = try!(connect_db());
2837

29-
for row in &try!(conn.query("SELECT id, name, version FROM queue ORDER BY id ASC", &[])) {
38+
for row in &try!(conn.query("SELECT id, name, version \
39+
FROM queue \
40+
WHERE attempt < 5 \
41+
ORDER BY id ASC", &[])) {
3042
let id: i32 = row.get(0);
3143
let name: String = row.get(1);
3244
let version: String = row.get(2);
@@ -36,6 +48,9 @@ impl DocBuilder {
3648
let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]);
3749
}
3850
Err(e) => {
51+
// Increase attempt count
52+
let _ = conn.execute("UPDATE queue SET attempt = attempt + 1 WHERE id = $1",
53+
&[&id]);
3954
error!("Failed to build package {}-{} from queue: {}",
4055
name,
4156
version,

src/utils/daemon.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,10 @@ pub fn start_daemon() {
4545
}
4646

4747

48-
// check new crates every 5 minutes
49-
// FIXME: why not just check new crates and build them if there is any?
48+
// check new crates every minute
5049
thread::spawn(move || {
5150
loop {
52-
thread::sleep(Duration::from_secs(300));
53-
debug!("Checking new crates");
54-
if let Err(e) = DocBuilder::new(opts()).get_new_crates() {
55-
error!("Failed to get new crates: {}", e);
56-
}
57-
}
58-
});
59-
60-
61-
// build crates in que every 5 minutes
62-
thread::spawn(move || {
63-
loop {
64-
thread::sleep(Duration::from_secs(300));
51+
thread::sleep(Duration::from_secs(60));
6552

6653
let mut opts = opts();
6754
opts.skip_if_exists = true;
@@ -72,25 +59,54 @@ pub fn start_daemon() {
7259
continue;
7360
}
7461

62+
let mut doc_builder = DocBuilder::new(opts);
63+
64+
debug!("Checking new crates");
65+
let queue_count = match doc_builder.get_new_crates() {
66+
Ok(size) => size,
67+
Err(e) => {
68+
error!("Failed to get new crates: {}", e);
69+
continue;
70+
}
71+
};
72+
73+
// Only build crates if there is any
74+
if queue_count == 0 {
75+
debug!("Queue is empty, going back to sleep");
76+
continue;
77+
}
78+
79+
info!("Building {} crates from queue", queue_count);
80+
7581
// update index
7682
if let Err(e) = update_sources() {
7783
error!("Failed to update sources: {}", e);
7884
continue;
7985
}
8086

81-
let mut doc_builder = DocBuilder::new(opts);
8287
if let Err(e) = doc_builder.load_cache() {
8388
error!("Failed to load cache: {}", e);
8489
continue;
8590
}
8691

87-
debug!("Building new crates");
88-
if let Err(e) = doc_builder.build_packages_queue() {
89-
error!("Failed build new crates: {}", e);
90-
}
9192

92-
if let Err(e) = doc_builder.save_cache() {
93-
error!("Failed to save cache: {}", e);
93+
// Run build_packages_queue in it's own thread to catch panics
94+
// This only panicked twice in the last 6 months but its just a better
95+
// idea to do this.
96+
let res = thread::spawn(move || {
97+
if let Err(e) = doc_builder.build_packages_queue() {
98+
error!("Failed build new crates: {}", e);
99+
}
100+
101+
if let Err(e) = doc_builder.save_cache() {
102+
error!("Failed to save cache: {}", e);
103+
}
104+
105+
debug!("Finished building new crates, going back to sleep");
106+
}).join();
107+
108+
if let Err(e) = res {
109+
error!("GRAVE ERROR Building new crates panicked: {:?}", e);
94110
}
95111
}
96112
});

src/web/releases.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,10 @@ pub fn activity_handler(req: &mut Request) -> IronResult<Response> {
505505
pub fn build_queue_handler(req: &mut Request) -> IronResult<Response> {
506506
let conn = extension!(req, Pool);
507507
let mut crates: Vec<(String, String)> = Vec::new();
508-
for krate in &conn.query("SELECT name, version FROM queue ORDER BY id ASC", &[]).unwrap() {
508+
for krate in &conn.query("SELECT name, version
509+
FROM queue
510+
WHERE attempt < 5
511+
ORDER BY id ASC", &[]).unwrap() {
509512
crates.push((krate.get(0), krate.get(1)));
510513
}
511514
let is_empty = crates.is_empty();

0 commit comments

Comments
 (0)