Skip to content
Draft
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
6 changes: 3 additions & 3 deletions changelog.d/ensure-indices-refreshes-coverage.changed.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
- `ensure_indices` and `ensure_indices_on` also rebuild lagging BTREE/vector
indexes, report lagging full-text coverage as pending, and under a policy
need an actor with `Change`: use `ensure_indices_on_as`.
- The engine's index build (`ensure_indices_as`, `ensure_indices_on_as`) also
rebuilds lagging BTREE and vector indexes and reports lagging full-text
coverage as pending.
5 changes: 5 additions & 0 deletions changelog.d/full-text-rebuild-change-grant.deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- The full-text rebuild accepts `change` on its branch for one more release;
after that it needs `maintain`. Grant `maintain` to the accounts that rebuild
full-text indexes. See [rebuild full-text indexes][full-text-rebuild-change-grant].

[full-text-rebuild-change-grant]: ../docs/user/operations/maintenance.md#rebuild-full-text-indexes
10 changes: 10 additions & 0 deletions changelog.d/maintenance-entry-points-take-an-actor.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- An embedded host with a policy checker refuses maintenance until its policy
grants `maintain` or `reclaim`. Engine maintenance methods take an actor:
`optimize_as`, `cleanup_as`, `ensure_indices_as`, `ensure_indices_on_as` and
`rebuild_full_text_indices_on_as`. `repair` is the read-only
`repair_report_as`, without `RepairOptions`, `healed`, `forced` or
`graph_manifest_version`. See [policy actions][maintenance-actions-upgrade]
and [repair][maintenance-entry-points-repair].

[maintenance-actions-upgrade]: ../docs/user/operations/policy.md#actions
[maintenance-entry-points-repair]: ../docs/user/operations/maintenance.md#repair
5 changes: 5 additions & 0 deletions changelog.d/maintenance-policy-actions.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- Cedar policy has two maintenance actions: `maintain` for optimize, index
builds, the full-text rebuild and repair, and `reclaim` for cleanup. `change`
implies neither. See [policy actions][maintenance-policy-actions].

[maintenance-policy-actions]: ../docs/user/operations/policy.md#actions
3 changes: 3 additions & 0 deletions crates/omnigraph-api-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2013,6 +2013,9 @@ fn access_slot(action: omnigraph_policy::PolicyAction) -> Option<AccessSlot> {
P::InvokeQuery => Some(AccessSlot::GraphWide),
// Server- or operator-scoped: no graph's access report names them.
P::Admin | P::GraphList | P::ConfigManage => None,
// Maintenance runs only through the direct CLI and embedded callers;
// no served operation performs it, so the report does not name it.
P::Maintain | P::Reclaim => None,
}
}

Expand Down
5 changes: 4 additions & 1 deletion crates/omnigraph-bench/src/dataset_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,10 @@ pub(crate) async fn build_dataset(
Engine::V2,
)?;
if plan.needs_indices {
session.ensure_indices().await.map_err(|e| e.to_string())?;
session
.ensure_indices_as(None)
.await
.map_err(|e| e.to_string())?;
}
(session, case, Some(exact))
}
Expand Down
2 changes: 1 addition & 1 deletion crates/omnigraph-bench/src/legacy/branch_merge_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub async fn initialize_local_fixture(
let optimized_user_tables = match plan.compaction_recency {
CompactionRecency::Optimized => {
let outcomes = db
.optimize()
.optimize_as(None)
.await
.map_err(|error| fixture_error(format!("optimize fixture main branch: {error}")))?;
let intended_keys = (0..plan.node_tables())
Expand Down
11 changes: 7 additions & 4 deletions crates/omnigraph-cli/src/commands/maintenance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::io::Write;

use color_eyre::eyre::{Result, bail};
use omnigraph::db::{CleanupPolicyOptions, Omnigraph, RepairAction, RepairOptions};
use omnigraph::db::{CleanupPolicyOptions, Omnigraph, RepairAction};

use crate::app::Completion;
use crate::helpers::{confirm_destructive, parse_duration_arg, resolve_actor};
Expand Down Expand Up @@ -45,13 +45,14 @@ pub(crate) async fn run_optimize(
let OptimizeArgs { json } = args;
let uri = crate::scope::direct_graph_uri(scope.target, scope.graph).await?;
let binding = crate::scope::capture_storage_binding(scope.target)?.for_uri(&uri)?;
let actor = resolve_actor(scope.operator, scope.actor, stderr)?;
crate::admission::ensure_graph_with_binding(&binding, stderr).await?;
let db = Omnigraph::open_with_storage(
binding.uri(),
omnigraph::storage::storage_for_binding(&binding)?,
)
.await?;
let stats = db.optimize().await?;
let stats = db.optimize_as(actor.as_deref()).await?;
write_optimize(&uri, &stats, json, stdout)?;
Ok(Completion::success())
}
Expand Down Expand Up @@ -141,13 +142,14 @@ pub(crate) async fn run_repair(
let RepairArgs { json } = args;
let uri = crate::scope::direct_graph_uri(scope.target, scope.graph).await?;
let binding = crate::scope::capture_storage_binding(scope.target)?.for_uri(&uri)?;
let actor = resolve_actor(scope.operator, scope.actor, stderr)?;
crate::admission::ensure_graph_with_binding(&binding, stderr).await?;
let db = Omnigraph::open_with_storage(
binding.uri(),
omnigraph::storage::storage_for_binding(&binding)?,
)
.await?;
let stats = db.repair(RepairOptions::default()).await?;
let stats = db.repair_report_as(actor.as_deref()).await?;
let refused_count = stats
.datasets
.iter()
Expand Down Expand Up @@ -207,13 +209,14 @@ pub(crate) async fn run_cleanup(
keep_versions: keep,
older_than: older_than_dur,
};
let actor = resolve_actor(scope.operator, scope.actor, stderr)?;
crate::admission::ensure_graph_with_binding(&binding, stderr).await?;
let db = Omnigraph::open_with_storage(
binding.uri(),
omnigraph::storage::storage_for_binding(&binding)?,
)
.await?;
let stats = db.cleanup(options.clone()).await?;
let stats = db.cleanup_as(options.clone(), actor.as_deref()).await?;
write_cleanup(&uri, &options, &policy_desc, &stats, json, stdout)?;
Ok(Completion::success())
}
Expand Down
13 changes: 5 additions & 8 deletions crates/omnigraph-cli/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ pub(crate) fn write_repair(
if json {
let value = serde_json::json!({
"uri": uri,
"graph_manifest_version": stats.graph_manifest_version,
"datasets": stats.datasets.iter().map(|s| serde_json::json!({
"type_key": s.type_key,
"published_dataset_version": s.published_dataset_version,
Expand Down Expand Up @@ -1933,7 +1932,7 @@ mod tests {
#[tokio::test]
async fn maintenance_optimize_and_repair_reports_preserve_all_result_fields() {
use omnigraph::db::{
Omnigraph, PendingIndex, RepairAction, RepairClassification, RepairOptions, SkipReason,
Omnigraph, PendingIndex, RepairAction, RepairClassification, SkipReason,
};
// These engine result types are non_exhaustive. Obtain one valid value
// from a tiny graph, then set its public presentation fields; no engine
Expand All @@ -1947,7 +1946,7 @@ mod tests {
let db = Omnigraph::init(&uri, "node Person {\n slug: String @key\n}\n")
.await
.unwrap();
let mut compacted = db.optimize().await.unwrap().pop().unwrap();
let mut compacted = db.optimize_as(None).await.unwrap().pop().unwrap();
compacted.type_key = "node:Person".into();
compacted.fragments_removed = 3;
compacted.fragments_added = 1;
Expand Down Expand Up @@ -1999,7 +1998,7 @@ mod tests {
|json, writer| super::write_optimize("graph", &[], json, writer),
);

let mut repair = db.repair(RepairOptions::default()).await.unwrap();
let mut repair = db.repair_report_as(None).await.unwrap();
let mut clean = repair.datasets.pop().unwrap();
clean.type_key = "node:Person".into();
clean.published_dataset_version = 4;
Expand All @@ -2016,15 +2015,14 @@ mod tests {
refused.operations = vec!["Append".into(), "Delete".into()];
refused.error = Some("foreign write".into());
repair.datasets = vec![clean, refused];
repair.graph_manifest_version = Some(9);
assert_maintenance_report(
concat!(
"repair graph — 2 datasets\n",
" node type 'Person' no_op no_drift 4\n",
" edge type 'Knows' refused foreign_drift 4 → 6 [Append, Delete] (foreign write)\n",
),
serde_json::json!({
"uri":"graph", "graph_manifest_version":9,
"uri":"graph",
"datasets":[
{"type_key":"node:Person","published_dataset_version":4,"lance_head_version":4,"classification":"no_drift","action":"no_op","operations":[],"error":null},
{"type_key":"edge:Knows","published_dataset_version":4,"lance_head_version":6,"classification":"foreign_drift","action":"refused","operations":["Append","Delete"],"error":"foreign write"},
Expand All @@ -2033,10 +2031,9 @@ mod tests {
|json, writer| super::write_repair("graph", &repair, json, writer),
);
repair.datasets.clear();
repair.graph_manifest_version = None;
assert_maintenance_report(
"repair graph — 0 datasets\n",
serde_json::json!({"uri":"graph","graph_manifest_version":null,"datasets":[]}),
serde_json::json!({"uri":"graph","datasets":[]}),
|json, writer| super::write_repair("graph", &repair, json, writer),
);
}
Expand Down
5 changes: 3 additions & 2 deletions crates/omnigraph-cli/tests/integration/cli_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,8 @@ fn repair_json_reports_noop_on_clean_graph() {

assert!(payload.get("confirm").is_none());
assert!(payload.get("force").is_none());
assert_eq!(payload["graph_manifest_version"], Value::Null);
// The report publishes nothing, so it names no graph manifest version.
assert!(payload.get("graph_manifest_version").is_none());
assert!(payload.get("manifest_version").is_none());
assert!(payload.get("tables").is_none());
let datasets = payload["datasets"].as_array().unwrap();
Expand Down Expand Up @@ -1469,7 +1470,7 @@ fn repair_reports_foreign_drift_and_refuses_removed_flags() {
.arg(&graph),
);
let payload: Value = serde_json::from_slice(&output.stdout).unwrap();
assert_eq!(payload["graph_manifest_version"], Value::Null);
assert!(payload.get("graph_manifest_version").is_none());
let person = payload["datasets"]
.as_array()
.unwrap()
Expand Down
15 changes: 9 additions & 6 deletions crates/omnigraph-dst/src/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1753,12 +1753,15 @@ fn maintenance_life(
let mut occ_retries = 0usize;
loop {
let result = match kind {
0 => Box::pin(db.ensure_indices()).await.map(|_| ()),
1 => Box::pin(db.optimize()).await.map(|_| ()),
_ => Box::pin(db.cleanup(CleanupPolicyOptions {
keep_versions: Some(1),
older_than: None,
}))
0 => Box::pin(db.ensure_indices_as(None)).await.map(|_| ()),
1 => Box::pin(db.optimize_as(None)).await.map(|_| ()),
_ => Box::pin(db.cleanup_as(
CleanupPolicyOptions {
keep_versions: Some(1),
older_than: None,
},
None,
))
.await
.map(|_| ()),
};
Expand Down
17 changes: 10 additions & 7 deletions crates/omnigraph-dst/src/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1634,12 +1634,15 @@ async fn exec_op(db: &Session, branch: &str, op: &Op) -> OmniResult<()> {
)
.await
.map(|_| ()),
Op::Optimize => Box::pin(db.optimize()).await.map(|_| ()),
Op::Optimize => Box::pin(db.optimize_as(None)).await.map(|_| ()),
Op::Cleanup => {
let stats = Box::pin(db.cleanup(omnigraph::db::CleanupPolicyOptions {
keep_versions: Some(1),
older_than: None,
}))
let stats = Box::pin(db.cleanup_as(
omnigraph::db::CleanupPolicyOptions {
keep_versions: Some(1),
older_than: None,
},
None,
))
.await?;
let deferred: BTreeMap<String, String> = stats
.iter()
Expand All @@ -1655,7 +1658,7 @@ async fn exec_op(db: &Session, branch: &str, op: &Op) -> OmniResult<()> {
.insert(db.uri().to_string(), deferred);
Ok(())
}
Op::EnsureIndices => Box::pin(db.ensure_indices()).await.map(|_| ()),
Op::EnsureIndices => Box::pin(db.ensure_indices_as(None)).await.map(|_| ()),
Op::SchemaAddProperty { count } => Box::pin(db.apply_schema(&schema_with_extras(*count)))
.await
.map(|_| ()),
Expand Down Expand Up @@ -6432,7 +6435,7 @@ impl UniverseScenario<RustResources> for Scenario {
tokio::time::resume();
let lively = tokio::time::timeout(
std::time::Duration::from_secs(120),
Box::pin(db.ensure_indices()),
Box::pin(db.ensure_indices_as(None)),
)
.await;
tokio::time::pause();
Expand Down
Loading
Loading