106 lines
3.8 KiB
Rust
106 lines
3.8 KiB
Rust
use super::http::Server;
|
|
use super::*;
|
|
use std::time::{Duration, Instant};
|
|
|
|
#[cfg(feature = "postgres")]
|
|
#[path = "job/heartbeat.rs"]
|
|
mod heartbeat;
|
|
|
|
#[test]
|
|
fn dever_jobs_persist_execute_and_rollback_with_bounded_retries() {
|
|
let directory = Directory::new();
|
|
verify_queue(
|
|
&directory,
|
|
serde_json::json!({"type":"sqlite","path":"data/jobs.db","max_connections":4}),
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "postgres")]
|
|
#[test]
|
|
#[ignore = "requires explicit isolated config/setting.json database.postgres_test"]
|
|
fn postgres_dever_jobs_persist_execute_and_rollback_with_bounded_retries() {
|
|
let directory = Directory::new();
|
|
let schema = super::database::postgres::Schema::new(
|
|
&directory.0,
|
|
"dever_native_jobs",
|
|
"CREATE SCHEMA dever_native_jobs",
|
|
"DROP SCHEMA dever_native_jobs CASCADE",
|
|
);
|
|
let mut connection = schema.connection.clone();
|
|
connection["max_connections"] = 4.into();
|
|
verify_queue(&directory, connection);
|
|
}
|
|
|
|
// 两种驱动运行同一 Dever 源码,包含 worker 重启、失败回滚和活跃键幂等。
|
|
fn verify_queue(directory: &Directory, connection: serde_json::Value) {
|
|
let project = Project::load(&fixture().with_file_name("job")).unwrap();
|
|
let program = project.check().unwrap();
|
|
assert_eq!(program.jobs.len(), 1);
|
|
let binary = build::build(
|
|
&program,
|
|
&project.sources,
|
|
"main",
|
|
&directory.0.join("jobs"),
|
|
)
|
|
.unwrap();
|
|
std::fs::create_dir(directory.0.join("config")).unwrap();
|
|
std::fs::write(directory.0.join("config/setting.json"), serde_json::to_vec(&serde_json::json!({"database":{"default":connection},"job":{"workers":2,"poll_ms":10,"lease_ms":2000,"retry_base_ms":10,"retry_max_ms":100},"runtime":{"shutdown_ms":1000}})).unwrap()).unwrap();
|
|
let run = |name: &str, input: &str| {
|
|
let result = execute(&binary, &format!("demo.queue.{name}"), input);
|
|
assert!(
|
|
result.status.success(),
|
|
"{}",
|
|
String::from_utf8_lossy(&result.stderr)
|
|
);
|
|
serde_json::from_slice::<serde_json::Value>(&result.stdout).unwrap()["data"].clone()
|
|
};
|
|
let first = run("submit", r#"{"name":"first","key":"one"}"#);
|
|
assert_eq!(first, run("submit", r#"{"name":"ignored","key":"one"}"#));
|
|
run("submit", r#"{"name":"fail","key":"bad"}"#);
|
|
assert!(
|
|
!execute(
|
|
&binary,
|
|
"demo.queue.rollback",
|
|
r#"{"name":"rolled back","key":"rollback"}"#
|
|
)
|
|
.status
|
|
.success()
|
|
);
|
|
assert_eq!(run("count", "{}"), 0);
|
|
let mut worker = Server(Command::new(&binary).spawn().unwrap());
|
|
let deadline = Instant::now() + Duration::from_secs(10);
|
|
loop {
|
|
assert!(worker.0.try_wait().unwrap().is_none(), "worker exited");
|
|
if run("count", "{}") == 1 {
|
|
break;
|
|
}
|
|
assert!(
|
|
Instant::now() < deadline,
|
|
"worker did not execute queued Dever code"
|
|
);
|
|
std::thread::sleep(Duration::from_millis(20));
|
|
}
|
|
std::thread::sleep(Duration::from_millis(150));
|
|
assert_eq!(run("count", "{}"), 1);
|
|
assert!(
|
|
Command::new("sh")
|
|
.args(["-c", "kill -TERM \"$1\"", "--", &worker.0.id().to_string()])
|
|
.status()
|
|
.unwrap()
|
|
.success()
|
|
);
|
|
assert!(worker.0.wait().unwrap().success());
|
|
let next = run("submit", r#"{"name":"second","key":"one"}"#);
|
|
assert_ne!(first, next);
|
|
let mut worker = Server(Command::new(&binary).spawn().unwrap());
|
|
let deadline = Instant::now() + Duration::from_secs(10);
|
|
while run("count", "{}") != 2 {
|
|
assert!(
|
|
worker.0.try_wait().unwrap().is_none(),
|
|
"restarted worker exited"
|
|
);
|
|
assert!(Instant::now() < deadline);
|
|
std::thread::sleep(Duration::from_millis(20));
|
|
}
|
|
}
|