Skip to content

Commit 09283ef

Browse files
Merge pull request #344 from QuietMisdreavus/build-queue-priority
add "priority" to the build queue, and decouple builds from reading new crates
2 parents e3b022e + 94cf10f commit 09283ef

File tree

8 files changed

+223
-91
lines changed

8 files changed

+223
-91
lines changed

src/bin/cratesfyi.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use std::path::PathBuf;
1212

1313
use clap::{Arg, App, SubCommand};
1414
use cratesfyi::{DocBuilder, DocBuilderOptions, db};
15-
use cratesfyi::utils::build_doc;
15+
use cratesfyi::utils::{build_doc, add_crate_to_queue};
1616
use cratesfyi::start_web_server;
17-
use cratesfyi::db::add_path_into_database;
17+
use cratesfyi::db::{add_path_into_database, connect_db};
1818

1919

2020
pub fn main() {
@@ -130,6 +130,23 @@ pub fn main() {
130130
chart")
131131
.subcommand(SubCommand::with_name("update-search-index"))
132132
.about("Updates search index"))
133+
.subcommand(SubCommand::with_name("queue")
134+
.about("Interactions with the build queue")
135+
.subcommand(SubCommand::with_name("add")
136+
.about("Add a crate to the build queue")
137+
.arg(Arg::with_name("CRATE_NAME")
138+
.index(1)
139+
.required(true)
140+
.help("Name of crate to build"))
141+
.arg(Arg::with_name("CRATE_VERSION")
142+
.index(2)
143+
.required(true)
144+
.help("Version of crate to build"))
145+
.arg(Arg::with_name("BUILD_PRIORITY")
146+
.short("p")
147+
.long("priority")
148+
.help("Priority of build (default: 5) (new crate builds get priority 0)")
149+
.takes_value(true))))
133150
.get_matches();
134151

135152

@@ -227,6 +244,17 @@ pub fn main() {
227244
start_web_server(Some(matches.value_of("SOCKET_ADDR").unwrap_or("0.0.0.0:3000")));
228245
} else if let Some(_) = matches.subcommand_matches("daemon") {
229246
cratesfyi::utils::start_daemon();
247+
} else if let Some(matches) = matches.subcommand_matches("queue") {
248+
if let Some(matches) = matches.subcommand_matches("add") {
249+
let priority = matches.value_of("BUILD_PRIORITY").unwrap_or("5");
250+
let priority: i32 = priority.parse().expect("--priority was not a number");
251+
let conn = connect_db().expect("Could not connect to database");
252+
253+
add_crate_to_queue(&conn,
254+
matches.value_of("CRATE_NAME").unwrap(),
255+
matches.value_of("CRATE_VERSION").unwrap(),
256+
priority).expect("Could not add crate to queue");
257+
}
230258
} else {
231259
println!("{}", matches.usage());
232260
}

src/db/migrate.rs

+10
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ pub fn migrate(version: Option<Version>) -> CratesfyiResult<()> {
169169
"DROP TABLE authors, author_rels, keyword_rels, keywords, owner_rels,
170170
owners, releases, crates, builds, queue, files, config;"
171171
),
172+
migration!(
173+
// version
174+
2,
175+
// description
176+
"Added priority column to build queue",
177+
// upgrade query
178+
"ALTER TABLE queue ADD COLUMN priority INT DEFAULT 0;",
179+
// downgrade query
180+
"ALTER TABLE queue DROP COLUMN priority;"
181+
),
172182
];
173183

174184
for migration in migrations {

src/docbuilder/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ impl DocBuilder {
110110
Ok(())
111111
}
112112

113+
/// Checks for the lock file and returns whether it currently exists.
114+
pub fn is_locked(&self) -> bool {
115+
self.lock_path().exists()
116+
}
117+
113118
/// Returns a reference of options
114119
pub fn options(&self) -> &DocBuilderOptions {
115120
&self.options

src/docbuilder/queue.rs

+41-44
Original file line numberDiff line numberDiff line change
@@ -5,67 +5,74 @@ use super::DocBuilder;
55
use db::connect_db;
66
use error::Result;
77
use crates_index_diff::{ChangeKind, Index};
8+
use utils::add_crate_to_queue;
89

910

1011
impl DocBuilder {
1112
/// Updates crates.io-index repository and adds new crates into build queue.
1213
/// Returns size of queue
13-
pub fn get_new_crates(&mut self) -> Result<i64> {
14+
pub fn get_new_crates(&mut self) -> Result<usize> {
1415
let conn = try!(connect_db());
1516
let index = try!(Index::from_path_or_cloned(&self.options.crates_io_index_path));
1617
let mut changes = try!(index.fetch_changes());
18+
let mut add_count: usize = 0;
1719

1820
// I belive this will fix ordering of queue if we get more than one crate from changes
1921
changes.reverse();
2022

2123
for krate in changes.iter().filter(|k| k.kind != ChangeKind::Yanked) {
22-
conn.execute("INSERT INTO queue (name, version) VALUES ($1, $2)",
23-
&[&krate.name, &krate.version])
24-
.ok();
24+
add_crate_to_queue(&conn, &krate.name, &krate.version, 0).ok();
2525
debug!("{}-{} added into build queue", krate.name, krate.version);
26+
add_count += 1;
2627
}
2728

28-
let queue_count = conn.query("SELECT COUNT(*) FROM queue WHERE attempt < 5", &[])
29+
Ok(add_count)
30+
}
31+
32+
pub fn get_queue_count(&self) -> Result<i64> {
33+
let conn = try!(connect_db());
34+
Ok(conn.query("SELECT COUNT(*) FROM queue WHERE attempt < 5", &[])
2935
.unwrap()
3036
.get(0)
31-
.get(0);
32-
33-
Ok(queue_count)
37+
.get(0))
3438
}
3539

36-
37-
/// Builds packages from queue
38-
pub fn build_packages_queue(&mut self) -> Result<usize> {
40+
/// Builds the top package from the queue. Returns whether the queue was empty.
41+
pub fn build_next_queue_package(&mut self) -> Result<bool> {
3942
let conn = try!(connect_db());
40-
let mut build_count = 0;
4143

42-
for row in &try!(conn.query("SELECT id, name, version
44+
let query = try!(conn.query("SELECT id, name, version
4345
FROM queue
4446
WHERE attempt < 5
45-
ORDER BY id ASC",
46-
&[])) {
47-
let id: i32 = row.get(0);
48-
let name: String = row.get(1);
49-
let version: String = row.get(2);
50-
51-
match self.build_package(&name[..], &version[..]) {
52-
Ok(_) => {
53-
build_count += 1;
54-
let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]);
55-
}
56-
Err(e) => {
57-
// Increase attempt count
58-
let _ = conn.execute("UPDATE queue SET attempt = attempt + 1 WHERE id = $1",
59-
&[&id]);
60-
error!("Failed to build package {}-{} from queue: {}",
61-
name,
62-
version,
63-
e)
64-
}
47+
ORDER BY priority ASC, attempt ASC, id ASC
48+
LIMIT 1",
49+
&[]));
50+
51+
if query.is_empty() {
52+
// nothing in the queue; bail
53+
return Ok(false);
54+
}
55+
56+
let id: i32 = query.get(0).get(0);
57+
let name: String = query.get(0).get(1);
58+
let version: String = query.get(0).get(2);
59+
60+
match self.build_package(&name[..], &version[..]) {
61+
Ok(_) => {
62+
let _ = conn.execute("DELETE FROM queue WHERE id = $1", &[&id]);
63+
}
64+
Err(e) => {
65+
// Increase attempt count
66+
let _ = conn.execute("UPDATE queue SET attempt = attempt + 1 WHERE id = $1",
67+
&[&id]);
68+
error!("Failed to build package {}-{} from queue: {}",
69+
name,
70+
version,
71+
e)
6572
}
6673
}
6774

68-
Ok(build_count)
75+
Ok(true)
6976
}
7077
}
7178

@@ -87,14 +94,4 @@ mod test {
8794
}
8895
assert!(res.is_ok());
8996
}
90-
91-
92-
#[test]
93-
#[ignore]
94-
fn test_build_packages_queue() {
95-
let _ = env_logger::try_init();
96-
let options = DocBuilderOptions::from_prefix(PathBuf::from("../cratesfyi-prefix"));
97-
let mut docbuilder = DocBuilder::new(options);
98-
assert!(docbuilder.build_packages_queue().is_ok());
99-
}
10097
}

0 commit comments

Comments
 (0)