Skip to content

Commit 6f1ecd9

Browse files
committed
queue: move docbuilder::queue::BuildQueue to queue::BuildQueue
1 parent f876bb7 commit 6f1ecd9

File tree

10 files changed

+330
-327
lines changed

10 files changed

+330
-327
lines changed

src/docbuilder/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ mod rustwide_builder;
77

88
pub(crate) use self::limits::Limits;
99
pub(self) use self::metadata::Metadata;
10-
pub use self::queue::BuildQueue;
1110
pub(crate) use self::rustwide_builder::BuildResult;
1211
pub use self::rustwide_builder::RustwideBuilder;
1312

1413
use crate::db::Pool;
1514
use crate::error::Result;
1615
use crate::index::Index;
16+
use crate::queue::BuildQueue;
1717
use crate::DocBuilderOptions;
1818
use log::debug;
1919
use std::collections::BTreeSet;

src/docbuilder/queue.rs

Lines changed: 0 additions & 318 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//! Updates registry index and builds new packages
22
33
use super::{DocBuilder, RustwideBuilder};
4-
use crate::config::Config;
5-
use crate::db::Pool;
64
use crate::error::Result;
75
use crate::utils::get_crate_priority;
86
use crates_index_diff::ChangeKind;
@@ -87,319 +85,3 @@ impl DocBuilder {
8785
Ok(processed)
8886
}
8987
}
90-
91-
#[derive(Debug, Eq, PartialEq, serde::Serialize)]
92-
pub(crate) struct QueuedCrate {
93-
#[serde(skip)]
94-
id: i32,
95-
pub(crate) name: String,
96-
pub(crate) version: String,
97-
pub(crate) priority: i32,
98-
}
99-
100-
#[derive(Debug)]
101-
pub struct BuildQueue {
102-
db: Pool,
103-
max_attempts: i32,
104-
}
105-
106-
impl BuildQueue {
107-
pub fn new(db: Pool, config: &Config) -> Self {
108-
BuildQueue {
109-
db,
110-
max_attempts: config.build_attempts.into(),
111-
}
112-
}
113-
114-
pub fn add_crate(&self, name: &str, version: &str, priority: i32) -> Result<()> {
115-
self.db.get()?.execute(
116-
"INSERT INTO queue (name, version, priority) VALUES ($1, $2, $3);",
117-
&[&name, &version, &priority],
118-
)?;
119-
Ok(())
120-
}
121-
122-
pub(crate) fn pending_count(&self) -> Result<usize> {
123-
let res = self.db.get()?.query(
124-
"SELECT COUNT(*) FROM queue WHERE attempt < $1;",
125-
&[&self.max_attempts],
126-
)?;
127-
Ok(res.get(0).get::<_, i64>(0) as usize)
128-
}
129-
130-
pub(crate) fn prioritized_count(&self) -> Result<usize> {
131-
let res = self.db.get()?.query(
132-
"SELECT COUNT(*) FROM queue WHERE attempt < $1 AND priority <= 0;",
133-
&[&self.max_attempts],
134-
)?;
135-
Ok(res.get(0).get::<_, i64>(0) as usize)
136-
}
137-
138-
pub(crate) fn failed_count(&self) -> Result<usize> {
139-
let res = self.db.get()?.query(
140-
"SELECT COUNT(*) FROM queue WHERE attempt >= $1;",
141-
&[&self.max_attempts],
142-
)?;
143-
Ok(res.get(0).get::<_, i64>(0) as usize)
144-
}
145-
146-
pub(crate) fn queued_crates(&self) -> Result<Vec<QueuedCrate>> {
147-
let query = self.db.get()?.query(
148-
"SELECT id, name, version, priority
149-
FROM queue
150-
WHERE attempt < $1
151-
ORDER BY priority ASC, attempt ASC, id ASC",
152-
&[&self.max_attempts],
153-
)?;
154-
155-
Ok(query
156-
.into_iter()
157-
.map(|row| QueuedCrate {
158-
id: row.get("id"),
159-
name: row.get("name"),
160-
version: row.get("version"),
161-
priority: row.get("priority"),
162-
})
163-
.collect())
164-
}
165-
166-
pub(crate) fn process_next_crate(
167-
&self,
168-
f: impl FnOnce(&QueuedCrate) -> Result<()>,
169-
) -> Result<()> {
170-
let conn = self.db.get()?;
171-
172-
let queued = self.queued_crates()?;
173-
let to_process = match queued.get(0) {
174-
Some(krate) => krate,
175-
None => return Ok(()),
176-
};
177-
178-
match f(&to_process) {
179-
Ok(()) => {
180-
conn.execute("DELETE FROM queue WHERE id = $1;", &[&to_process.id])?;
181-
crate::web::metrics::TOTAL_BUILDS.inc();
182-
}
183-
Err(e) => {
184-
// Increase attempt count
185-
let rows = conn.query(
186-
"UPDATE queue SET attempt = attempt + 1 WHERE id = $1 RETURNING attempt;",
187-
&[&to_process.id],
188-
)?;
189-
let attempt: i32 = rows.get(0).get(0);
190-
191-
if attempt >= self.max_attempts {
192-
crate::web::metrics::FAILED_BUILDS.inc();
193-
}
194-
195-
error!(
196-
"Failed to build package {}-{} from queue: {}\nBacktrace: {}",
197-
to_process.name,
198-
to_process.version,
199-
e,
200-
e.backtrace()
201-
);
202-
}
203-
}
204-
205-
Ok(())
206-
}
207-
}
208-
209-
#[cfg(test)]
210-
mod tests {
211-
use super::*;
212-
213-
#[test]
214-
fn test_add_and_process_crates() {
215-
const MAX_ATTEMPTS: u16 = 3;
216-
217-
crate::test::wrapper(|env| {
218-
env.override_config(|config| {
219-
config.build_attempts = MAX_ATTEMPTS;
220-
});
221-
222-
let queue = env.build_queue();
223-
224-
let test_crates = [
225-
("low-priority", "1.0.0", 1000),
226-
("high-priority-foo", "1.0.0", -1000),
227-
("medium-priority", "1.0.0", -10),
228-
("high-priority-bar", "1.0.0", -1000),
229-
("standard-priority", "1.0.0", 0),
230-
("high-priority-baz", "1.0.0", -1000),
231-
];
232-
for krate in &test_crates {
233-
queue.add_crate(krate.0, krate.1, krate.2)?;
234-
}
235-
236-
let assert_next = |name| -> Result<()> {
237-
queue.process_next_crate(|krate| {
238-
assert_eq!(name, krate.name);
239-
Ok(())
240-
})?;
241-
Ok(())
242-
};
243-
let assert_next_and_fail = |name| -> Result<()> {
244-
queue.process_next_crate(|krate| {
245-
assert_eq!(name, krate.name);
246-
failure::bail!("simulate a failure");
247-
})?;
248-
Ok(())
249-
};
250-
251-
// The first processed item is the one with the highest priority added first.
252-
assert_next("high-priority-foo")?;
253-
254-
// Simulate a failure in high-priority-bar.
255-
assert_next_and_fail("high-priority-bar")?;
256-
257-
// Continue with the next high priority crate.
258-
assert_next("high-priority-baz")?;
259-
260-
// After all the crates with the max priority are processed, before starting to process
261-
// crates with a lower priority the failed crates with the max priority will be tried
262-
// again.
263-
assert_next("high-priority-bar")?;
264-
265-
// Continue processing according to the priority.
266-
assert_next("medium-priority")?;
267-
assert_next("standard-priority")?;
268-
269-
// Simulate the crate failing many times.
270-
for _ in 0..MAX_ATTEMPTS {
271-
assert_next_and_fail("low-priority")?;
272-
}
273-
274-
// Since low-priority failed many times it will be removed from the queue. Because of
275-
// that the queue should now be empty.
276-
let mut called = false;
277-
queue.process_next_crate(|_| {
278-
called = true;
279-
Ok(())
280-
})?;
281-
assert!(!called, "there were still items in the queue");
282-
283-
Ok(())
284-
})
285-
}
286-
287-
#[test]
288-
fn test_pending_count() {
289-
crate::test::wrapper(|env| {
290-
let queue = env.build_queue();
291-
292-
assert_eq!(queue.pending_count()?, 0);
293-
queue.add_crate("foo", "1.0.0", 0)?;
294-
assert_eq!(queue.pending_count()?, 1);
295-
queue.add_crate("bar", "1.0.0", 0)?;
296-
assert_eq!(queue.pending_count()?, 2);
297-
298-
queue.process_next_crate(|krate| {
299-
assert_eq!("foo", krate.name);
300-
Ok(())
301-
})?;
302-
assert_eq!(queue.pending_count()?, 1);
303-
304-
Ok(())
305-
});
306-
}
307-
308-
#[test]
309-
fn test_prioritized_count() {
310-
crate::test::wrapper(|env| {
311-
let queue = env.build_queue();
312-
313-
assert_eq!(queue.prioritized_count()?, 0);
314-
queue.add_crate("foo", "1.0.0", 0)?;
315-
assert_eq!(queue.prioritized_count()?, 1);
316-
queue.add_crate("bar", "1.0.0", -100)?;
317-
assert_eq!(queue.prioritized_count()?, 2);
318-
queue.add_crate("baz", "1.0.0", 100)?;
319-
assert_eq!(queue.prioritized_count()?, 2);
320-
321-
queue.process_next_crate(|krate| {
322-
assert_eq!("bar", krate.name);
323-
Ok(())
324-
})?;
325-
assert_eq!(queue.prioritized_count()?, 1);
326-
327-
Ok(())
328-
});
329-
}
330-
331-
#[test]
332-
fn test_failed_count() {
333-
const MAX_ATTEMPTS: u16 = 3;
334-
crate::test::wrapper(|env| {
335-
env.override_config(|config| {
336-
config.build_attempts = 3;
337-
});
338-
let queue = env.build_queue();
339-
340-
assert_eq!(queue.failed_count()?, 0);
341-
queue.add_crate("foo", "1.0.0", -100)?;
342-
assert_eq!(queue.failed_count()?, 0);
343-
queue.add_crate("bar", "1.0.0", 0)?;
344-
345-
for _ in 0..MAX_ATTEMPTS {
346-
assert_eq!(queue.failed_count()?, 0);
347-
queue.process_next_crate(|krate| {
348-
assert_eq!("foo", krate.name);
349-
failure::bail!("this failed");
350-
})?;
351-
}
352-
assert_eq!(queue.failed_count()?, 1);
353-
354-
queue.process_next_crate(|krate| {
355-
assert_eq!("bar", krate.name);
356-
Ok(())
357-
})?;
358-
assert_eq!(queue.failed_count()?, 1);
359-
360-
Ok(())
361-
});
362-
}
363-
364-
#[test]
365-
fn test_queued_crates() {
366-
crate::test::wrapper(|env| {
367-
let queue = env.build_queue();
368-
369-
let test_crates = [
370-
("foo", "1.0.0", -10),
371-
("bar", "1.0.0", 0),
372-
("baz", "1.0.0", 10),
373-
];
374-
for krate in &test_crates {
375-
queue.add_crate(krate.0, krate.1, krate.2)?;
376-
}
377-
378-
assert_eq!(
379-
vec![
380-
QueuedCrate {
381-
id: 1,
382-
name: "foo".into(),
383-
version: "1.0.0".into(),
384-
priority: -10,
385-
},
386-
QueuedCrate {
387-
id: 2,
388-
name: "bar".into(),
389-
version: "1.0.0".into(),
390-
priority: 0,
391-
},
392-
QueuedCrate {
393-
id: 3,
394-
name: "baz".into(),
395-
version: "1.0.0".into(),
396-
priority: 10,
397-
},
398-
],
399-
queue.queued_crates()?
400-
);
401-
402-
Ok(())
403-
});
404-
}
405-
}

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44

55
pub use self::config::Config;
66
pub use self::docbuilder::options::DocBuilderOptions;
7-
pub use self::docbuilder::BuildQueue;
87
pub use self::docbuilder::DocBuilder;
98
pub use self::docbuilder::RustwideBuilder;
9+
pub use self::queue::BuildQueue;
1010
pub use self::web::Server;
1111

1212
mod config;
1313
pub mod db;
1414
mod docbuilder;
1515
mod error;
1616
mod index;
17+
mod queue;
1718
pub mod storage;
1819
#[cfg(test)]
1920
mod test;

0 commit comments

Comments
 (0)