Skip to content

Commit a54d0ec

Browse files
authored
Merge branch 'main' into fix/listing-denial-text
2 parents 62ec823 + b858c24 commit a54d0ec

7 files changed

Lines changed: 98 additions & 49 deletions

File tree

‎crates/sqlbuild-orchestration/tests/platform/helpers.rs‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,28 @@ pub(crate) async fn receive_webhook(
141141
)
142142
}
143143

144+
/// Wait for `count` deliveries: fail after a minute without progress or ten minutes in total.
144145
pub(crate) async fn wait_for_webhook(
145146
receiver: &WebhookReceiver,
146147
dispatcher: &JoinHandle<Result<(), ControlError>>,
147148
count: usize,
148149
) {
149150
let mut delivered = receiver.delivered.subscribe();
150-
tokio::time::timeout(
151-
Duration::from_secs(10),
152-
delivered.wait_for(|received| *received >= count),
153-
)
151+
tokio::time::timeout(Duration::from_secs(600), async {
152+
for _ in 0..count {
153+
let seen = *delivered.borrow_and_update();
154+
tokio::time::timeout(
155+
Duration::from_secs(60),
156+
delivered.wait_for(|received| *received > seen || *received >= count),
157+
)
158+
.await
159+
.expect("dispatcher keeps delivering across bounded pages")
160+
.expect("webhook receiver remains available");
161+
}
162+
})
154163
.await
155-
.expect("dispatcher drains more than one bounded page")
156-
.expect("webhook receiver remains available");
164+
.expect("dispatcher delivers every event within ten minutes");
165+
assert!(*delivered.borrow() >= count, "every event delivered");
157166
assert!(
158167
!dispatcher.is_finished(),
159168
"delivery loop stopped before draining"

‎crates/sqlbuild-orchestration/tests/runs/test_claims.rs‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::runs::tests::terminal_helpers::finish;
1818
use crate::runs::tests::test_types::{
1919
BacklogClaimTestCase, GroupLimitTestCase, PriorityClaimsTestCase, ScopedClaimTestCase,
2020
};
21+
use crate::store::tests::lease_helpers::extend_lease_through_test;
2122
use crate::store::tests::replica_helpers::second_store;
2223
use crate::store::tests::store_helpers::{close_store, close_test_store, open_test_store, run};
2324
use crate::store::tests::store_test_types::Backend;
@@ -399,23 +400,19 @@ fn given_more_than_one_page_of_blocked_runs_when_claiming_then_lower_priority_in
399400
.await
400401
.expect("snapshot");
401402
let scope = (location, published.snapshot_id);
402-
let mut lease = acquire_lease(store, Uuid::now_v7())
403+
let elected = acquire_lease(store, Uuid::now_v7())
403404
.await
404405
.expect("elect")
405406
.expect("leader");
407+
let lease = extend_lease_through_test(store, elected).await;
406408
let limits = BTreeMap::new();
407409
queue(store, &request(scope, 1, 0, &["orders"])).await;
408410
claim_next_run(store, &lease, &limits, None)
409411
.await
410412
.expect("claim blocker")
411413
.expect("available");
412-
for batch in (2..=104).collect::<Vec<_>>().chunks(20) {
413-
for id in batch {
414-
queue(store, &request(scope, *id, 0, &["orders"])).await;
415-
}
416-
lease = crate::scheduler::main::renew_lease::renew_lease(store, &lease)
417-
.await
418-
.expect("keep leader live while preparing backlog");
414+
for id in 2..=104 {
415+
queue(store, &request(scope, id, 0, &["orders"])).await;
419416
}
420417
queue(store, &request(scope, 105, -1, &["customers"])).await;
421418
let started = std::time::Instant::now();

‎crates/sqlbuild-orchestration/tests/runs/test_group_admission.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::runs::tests::test_types::{
2222
AdmissionParent, GroupAdmissionTestCase, GroupChildLimitTestCase, GroupQueueTestCase,
2323
MixedAdmissionTestCase, RunLifecycleTestCase,
2424
};
25+
use crate::store::tests::lease_helpers::extend_lease_through_test;
2526
use crate::store::tests::replica_helpers::second_store;
2627
use crate::store::tests::store_helpers::{close_store, close_test_store, open_test_store, run};
2728
use crate::store::tests::store_test_types::Backend;
@@ -802,10 +803,11 @@ fn given_a_large_healthy_project_with_blocked_groups_when_claiming_then_unrelate
802803
let published = publish_snapshot(store, &input)
803804
.await
804805
.expect("publish large project");
805-
let lease = acquire_lease(store, Uuid::now_v7())
806+
let elected = acquire_lease(store, Uuid::now_v7())
806807
.await
807808
.expect("elect")
808809
.expect("leader");
810+
let lease = extend_lease_through_test(store, elected).await;
809811
let limits = BTreeMap::from([("warehouse".into(), NonZeroU32::new(1).expect("one"))]);
810812
let scope = (location, "development");
811813
let mut physical = request((location, published.snapshot_id), 1, 10, &["products"]);

‎crates/sqlbuild-orchestration/tests/runs/test_monitor.rs‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::runs::main::heartbeat_run::heartbeat_run;
99
use crate::runs::main::list_runs::list_runs;
1010
use crate::runs::main::monitor_runs::monitor_runs;
1111
use crate::runs::models::{RunAuthority, RunChange, RunChangeRequest, RunOutcome, RunStatus};
12-
use crate::scheduler::main::renew_lease::renew_lease;
1312
use crate::scheduler::models::SchedulerState;
1413
use crate::scheduler::tests::contracts::helpers::{acquire_lease, scheduler_cycle};
1514
use crate::snapshots::main::publish_snapshot::publish_snapshot;
@@ -25,7 +24,7 @@ use crate::runs::tests::test_types::{
2524
MonitorBacklogTestCase, RunMonitorTestCase, TransactionFault,
2625
};
2726
use crate::store::tests::fault_helpers::{install_fault, remove_fault};
28-
use crate::store::tests::lease_helpers::expire_lease;
27+
use crate::store::tests::lease_helpers::{expire_lease, extend_lease_through_test};
2928
use crate::store::tests::store_helpers::{close_test_store, open_test_store, run};
3029
use crate::store::tests::store_test_types::Backend;
3130

@@ -287,10 +286,11 @@ fn given_a_silent_worker_backlog_when_monitoring_then_bounded_transactions_conti
287286
.await
288287
.expect("snapshot");
289288
let holder = Uuid::now_v7();
290-
let mut lease = acquire_lease(store, holder)
289+
let elected = acquire_lease(store, holder)
291290
.await
292291
.expect("elect")
293292
.expect("leader");
293+
let lease = extend_lease_through_test(store, elected).await;
294294
for index in 0..test_case.run_count {
295295
let mut input = request(
296296
(location, published.snapshot_id),
@@ -301,9 +301,6 @@ fn given_a_silent_worker_backlog_when_monitoring_then_bounded_transactions_conti
301301
input.write_set.clear();
302302
start_run(store, &lease, &input).await;
303303
age_heartbeat(store, input.run_id, 50).await;
304-
lease = renew_lease(store, &lease)
305-
.await
306-
.expect("renew during setup");
307304
}
308305
expire_lease(store).await;
309306
let mut state = SchedulerState::new(holder);

‎crates/sqlbuild-orchestration/tests/scheduler/ticks/helpers.rs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,9 +619,12 @@ pub(crate) async fn fault_run(
619619
.0;
620620
}
621621
let settled = Utc::now();
622-
scheduler_cycle(&second, survivor)
623-
.await
624-
.expect("final recovery");
622+
for _ in 0..FAULT_TRIGGERS.div_ceil(100) {
623+
survivor = scheduler_cycle(&second, survivor)
624+
.await
625+
.expect("final recovery")
626+
.0;
627+
}
625628
let first = started
626629
.duration_trunc(TimeDelta::minutes(1))
627630
.expect("minute")

‎crates/sqlbuild-orchestration/tests/sensors/test_execution_bounds.rs‎

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use crate::runs::main::{
1515
use crate::runs::models::{
1616
JobRunRequest, NodeOutcome, RunAuthority, RunChange, RunChangeRequest, RunOutcome,
1717
};
18-
use crate::scheduler::main::renew_lease::renew_lease;
1918
use crate::scheduler::tests::contracts::helpers::acquire_lease;
2019
use crate::sensors::main::{
2120
begin_sensor_evaluation::begin_sensor_evaluation,
@@ -25,6 +24,7 @@ use crate::sensors::tests::helpers::snapshot;
2524
use crate::sensors::tests::test_types::SensorTestCase;
2625
use crate::snapshots::main::publish_snapshot::publish_snapshot;
2726
use crate::store::main::migrate_store::migrate_store;
27+
use crate::store::tests::lease_helpers::extend_lease_through_test;
2828
use crate::store::tests::store_helpers::{close_test_store, open_test_store, run};
2929
use crate::store::tests::store_test_types::Backend;
3030

@@ -79,10 +79,11 @@ fn given_a_wide_group_when_only_the_last_node_has_not_started_then_all_chunks_mu
7979
publish_snapshot(store, &input)
8080
.await
8181
.expect("publish wide predicate");
82-
let lease = acquire_lease(store, Uuid::now_v7())
82+
let elected = acquire_lease(store, Uuid::now_v7())
8383
.await
8484
.expect("elect")
8585
.expect("leader");
86+
let lease = extend_lease_through_test(store, elected).await;
8687
let limits = std::collections::BTreeMap::new();
8788
let scope = (location, "development");
8889
for include_last in [true, false] {
@@ -138,28 +139,22 @@ fn given_a_wide_group_when_only_the_last_node_has_not_started_then_all_chunks_mu
138139
exit_code: None,
139140
}))
140141
.collect::<Vec<_>>();
141-
for batch in changes.chunks(100) {
142-
// Evidence setup must keep its scheduler alive, just like the real loop.
143-
renew_lease(store, &lease)
144-
.await
145-
.expect("renew during setup");
146-
for change in batch {
147-
change_run(
148-
store,
149-
RunAuthority::Worker {
150-
run_id: claim.request.run_id,
151-
claim_id: claim.claim_id,
152-
},
153-
&RunChangeRequest {
154-
event_id: Uuid::now_v7(),
155-
run_id: claim.request.run_id,
156-
claim_id: Some(claim.claim_id),
157-
change: change.clone(),
158-
},
159-
)
160-
.await
161-
.expect("real node evidence");
162-
}
142+
for change in &changes {
143+
change_run(
144+
store,
145+
RunAuthority::Worker {
146+
run_id: claim.request.run_id,
147+
claim_id: claim.claim_id,
148+
},
149+
&RunChangeRequest {
150+
event_id: Uuid::now_v7(),
151+
run_id: claim.request.run_id,
152+
claim_id: Some(claim.claim_id),
153+
change: change.clone(),
154+
},
155+
)
156+
.await
157+
.expect("real node evidence");
163158
}
164159
advance_groups(store, &lease, (&limits, scope))
165160
.await

‎crates/sqlbuild-orchestration/tests/store/leases/helpers.rs‎

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
//! Expire the persisted lease without introducing a fake control-store clock.
1+
//! Expire or hold the persisted lease without introducing a fake control-store clock.
22
3+
use chrono::{SecondsFormat, TimeDelta, Utc};
4+
5+
use crate::scheduler::models::SchedulerLease;
36
use crate::store::models::ControlStore;
47

58
pub(crate) async fn expire_lease(store: &ControlStore) {
@@ -22,3 +25,46 @@ pub(crate) async fn expire_lease(store: &ControlStore) {
2225
.await
2326
.expect("expire PostgreSQL scheduler lease");
2427
}
28+
29+
/// Keep `lease` live for a day without a renewer task, so slow setup cannot fence the test.
30+
pub(crate) async fn extend_lease_through_test(
31+
store: &ControlStore,
32+
lease: SchedulerLease,
33+
) -> SchedulerLease {
34+
let expires_at = Utc::now() + TimeDelta::days(1);
35+
let ControlStore::Postgres(pool) = store else {
36+
let ControlStore::Sqlite(path) = store else {
37+
unreachable!()
38+
};
39+
let held = rusqlite::Connection::open(path)
40+
.expect("open lease hold connection")
41+
.execute(
42+
"UPDATE sqb_scheduler_lease SET expires_at=?1 WHERE name='scheduler' AND holder=?2 AND epoch=?3",
43+
rusqlite::params![
44+
expires_at.to_rfc3339_opts(SecondsFormat::Micros, true),
45+
lease.holder.to_string(),
46+
lease.epoch
47+
],
48+
)
49+
.expect("hold SQLite scheduler lease");
50+
assert_eq!(held, 1, "the held lease is the current one");
51+
return SchedulerLease {
52+
expires_at,
53+
..lease
54+
};
55+
};
56+
let held = sqlx_core::query::query(
57+
"UPDATE sqb_scheduler_lease SET expires_at=$1 WHERE name='scheduler' AND holder=$2 AND epoch=$3",
58+
)
59+
.bind(expires_at)
60+
.bind(lease.holder)
61+
.bind(lease.epoch)
62+
.execute(pool)
63+
.await
64+
.expect("hold PostgreSQL scheduler lease");
65+
assert_eq!(held.rows_affected(), 1, "the held lease is the current one");
66+
SchedulerLease {
67+
expires_at,
68+
..lease
69+
}
70+
}

0 commit comments

Comments
 (0)