Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,17 @@ jobs:
--test s3_cluster \
-- --nocapture --test-threads=1 2>&1 | tee -a "$test_log"

# Keep the same package feature graph for this admitted-startup unit
# fixture; selecting only server would rebuild Lance and object_store.
cargo test --locked \
-p omnigraph-engine \
-p omnigraph-server \
-p omnigraph-cluster \
-p omnigraph-cli \
--lib \
settings::tests::s3_bootstrap_handoff_serves_empty_then_deploys_first_graph \
-- --exact --nocapture --test-threads=1 2>&1 | tee -a "$test_log"

if grep -Eiq \
"SKIP public_physical_ref_token_rejects_s3_same_version_aba|skipping s3 " \
"$test_log"
Expand All @@ -1300,6 +1311,7 @@ jobs:
public_physical_ref_token_rejects_s3_same_version_aba \
s3::server_opens_s3_graph_directly_and_serves_snapshot_and_read \
s3::server_boots_cluster_from_bare_storage_uri_and_serves_query \
settings::tests::s3_bootstrap_handoff_serves_empty_then_deploys_first_graph \
s3_cluster_full_lifecycle_import_apply_serve_evolve_delete \
cli_cluster_e2e::cluster_e2e_s3_live_apply_without_restart \
system_local::local_cli_s3_end_to_end_init_load_read_flow
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions changelog.d/bootstrap-serving-handoff.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- A fresh, empty S3 cluster initialized through `omnigraph-cluster::bootstrap_serving` can transfer its retained ownership to the first server with `--bootstrap-handoff FILE`. The bounded, exact receipt is checked before listening; failed or replayed claims never fall back to ordinary startup. See [first boot from a bootstrap receipt][bootstrap-serving-handoff].

[bootstrap-serving-handoff]: ../docs/user/clusters/index.md#first-boot-from-a-bootstrap-receipt
1 change: 1 addition & 0 deletions crates/omnigraph-cluster/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tokio = { workspace = true }
ulid = { workspace = true }

[dev-dependencies]
async-trait = { workspace = true }
serial_test = "3"
tempfile = { workspace = true }
tokio = { workspace = true }
Expand Down
30 changes: 30 additions & 0 deletions crates/omnigraph-cluster/src/admission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,30 @@ struct AdmissionOwner {
}

impl ClusterAdmission {
/// Only the private policy-only bootstrap protocol can transfer an
/// already-held lock into an admission. Neither owner is ever unlocked.
pub(crate) fn from_bootstrap_lock(
store: ClusterStore,
guard: StateLockGuard,
serving_deployment: Option<crate::DeploymentResult>,
) -> Self {
let purpose = if serving_deployment.is_some() {
ClusterAdmissionPurpose::Serve
} else {
ClusterAdmissionPurpose::Deployment
};
Self(Arc::new(AdmissionOwner {
canonical_root: store
.canonical_root()
.expect("bootstrap has a validated S3 root"),
store,
guard,
schema_contracts: BTreeMap::new(),
serving_deployment,
purpose,
}))
}

pub fn canonical_root(&self) -> &str {
&self.0.canonical_root
}
Expand Down Expand Up @@ -149,6 +173,12 @@ impl ClusterAdmission {
/// outstanding clone, or abandonment retains the persisted lock. Operators
/// must exclude concurrent force-unlock/release; the backend has no
/// conditional-delete guarantee.
///
/// After bootstrap transfer, this obligation includes earlier accepted
/// bootstrap control I/O, not only the current serving process. Otherwise
/// deleting this lock could let a delayed bootstrap create-if-absent
/// recreate its old lock. The transfer proves those attempts harmless
/// only while the lock remains continuously present.
pub async fn release_after_settlement(self) -> Result<(), Diagnostic> {
let owner = Arc::try_unwrap(self.0).map_err(|owner| {
Diagnostic::error(
Expand Down
5 changes: 5 additions & 0 deletions crates/omnigraph-cluster/src/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ use omnigraph::db::{

mod execution;
pub use execution::*;
mod bootstrap;
pub use bootstrap::{
BootstrapServingReceipt, MAX_BOOTSTRAP_SERVING_RECEIPT_BYTES, bootstrap_serving,
claim_bootstrap_serving,
};

pub(crate) const MAX_LEDGER_BYTES: usize = 16 * 1024 * 1024;
pub const MAX_BUNDLE_BYTES: usize = 16 * 1024 * 1024;
Expand Down
Loading
Loading