mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Track history initialization in Responses turn metadata (#52325)
## What changed Add `history_initialization` to `x-codex-turn-metadata`, distinguishing `new`, `cleared`, `cold_resume`, `warm_fork`, `cold_fork`, and `supplied_history`. Classify forks by whether the source runtime is loaded and has not shut down. Preserve the classification for the runtime's lifetime, including warm resumes and compaction. This records how history was initialized; it does not establish whether tool metadata is missing. Reserve the field against client-supplied overrides. ## Testing Extend coverage for warm and cold forks, cold resumes, warm reconnects, supplied history, WebSocket metadata serialization, and reserved-field filtering. GitOrigin-RevId: 468153512a84d0f4d4ea742198a29e0fa3873a72
This commit is contained in:
committed by
copyberry
parent
99aa05341d
commit
780d7ab097
@@ -541,6 +541,34 @@ async fn thread_resume_with_empty_path_uses_running_thread_id() -> Result<()> {
|
||||
} = timeout(DEFAULT_READ_TIMEOUT, mcp.read_response(resume_id)).await??;
|
||||
|
||||
assert_eq!(resumed.id, thread.id);
|
||||
mcp.start_turn_and_wait_for_completion(TurnStartParams {
|
||||
thread_id: resumed.id,
|
||||
input: vec![UserInput::Text {
|
||||
text: "after warm resume".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let requests = responses::received_responses_requests(&server).await;
|
||||
let initialization = requests
|
||||
.iter()
|
||||
.map(|request| {
|
||||
let body = request.body_json();
|
||||
let metadata: serde_json::Value = serde_json::from_str(
|
||||
body["client_metadata"]["x-codex-turn-metadata"]
|
||||
.as_str()
|
||||
.expect("turn metadata"),
|
||||
)
|
||||
.expect("valid turn metadata");
|
||||
metadata["history_initialization"].clone()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// Rejoining the live runtime must not relabel it as reconstructed history.
|
||||
assert_eq!(
|
||||
serde_json::Value::Array(initialization),
|
||||
json!(["new", "new"])
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -6102,6 +6130,24 @@ async fn thread_resume_supports_history_and_overrides() -> Result<()> {
|
||||
assert_eq!(resumed.preview, history_text);
|
||||
assert_eq!(resumed.status, ThreadStatus::Idle);
|
||||
|
||||
mcp.start_turn_and_wait_for_completion(TurnStartParams {
|
||||
thread_id: resumed.id,
|
||||
input: vec![UserInput::Text {
|
||||
text: "after supplied history".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let requests = responses::received_responses_requests(&server).await;
|
||||
let body = requests.last().expect("resumed model request").body_json();
|
||||
let metadata: serde_json::Value = serde_json::from_str(
|
||||
body["client_metadata"]["x-codex-turn-metadata"]
|
||||
.as_str()
|
||||
.expect("turn metadata"),
|
||||
)?;
|
||||
assert_eq!(metadata["history_initialization"], "supplied_history");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ use codex_api::AgentIdentityTelemetry;
|
||||
use codex_api::ApiError;
|
||||
use codex_api::ResponseEvent;
|
||||
use codex_api::TransportError;
|
||||
use codex_history::HistoryInitialization;
|
||||
use codex_http_client::HttpClientFactory;
|
||||
use codex_http_client::OutboundProxyPolicy;
|
||||
use codex_login::AuthManager;
|
||||
@@ -1541,13 +1542,14 @@ fn build_ws_client_metadata_includes_window_lineage_and_turn_metadata() {
|
||||
|
||||
let thread_id = client.state.thread_id.to_string();
|
||||
let expected_window_id = format!("{thread_id}:1");
|
||||
let responses_metadata = test_responses_metadata_for_client(
|
||||
let mut responses_metadata = test_responses_metadata_for_client(
|
||||
&client,
|
||||
Some("turn-123"),
|
||||
expected_window_id.clone(),
|
||||
Some(parent_thread_id),
|
||||
TestCodexResponsesRequestKind::Turn,
|
||||
);
|
||||
responses_metadata.history_initialization = Some(HistoryInitialization::WarmFork);
|
||||
let client_metadata = client.build_ws_client_metadata(
|
||||
&responses_metadata,
|
||||
/*include_internal*/ true,
|
||||
@@ -1560,6 +1562,7 @@ fn build_ws_client_metadata_includes_window_lineage_and_turn_metadata() {
|
||||
.expect("turn metadata"),
|
||||
)
|
||||
.expect("valid turn metadata");
|
||||
assert_eq!(turn_metadata["history_initialization"], "warm_fork");
|
||||
for (client_key, metadata_key, expected) in [
|
||||
(
|
||||
X_CODEX_INSTALLATION_ID_HEADER,
|
||||
|
||||
@@ -31,6 +31,7 @@ use crate::session::session::Session;
|
||||
use crate::session::startup::SessionStartup;
|
||||
use crate::session::startup::SessionStartupGuard;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use codex_history::HistoryInitialization;
|
||||
use codex_history::InitialHistory;
|
||||
use codex_login::AuthManager;
|
||||
use codex_models_manager::manager::SharedModelsManager;
|
||||
@@ -80,6 +81,13 @@ pub(crate) async fn run_codex_thread_interactive(
|
||||
|
||||
let conversation_history = initial_history.unwrap_or(InitialHistory::New);
|
||||
let forked_from_thread_id = conversation_history.forked_from_id();
|
||||
let history_initialization = if matches!(&conversation_history, InitialHistory::Forked(_))
|
||||
&& forked_from_thread_id == Some(parent_session.thread_id)
|
||||
{
|
||||
HistoryInitialization::WarmFork
|
||||
} else {
|
||||
HistoryInitialization::from_history(&conversation_history)
|
||||
};
|
||||
let runtime = parent_session.services.local_agent_runtime.clone();
|
||||
let startup = Arc::new(SessionStartup::default());
|
||||
startup.hold_membership(runtime.admit_start()?);
|
||||
@@ -113,6 +121,7 @@ pub(crate) async fn run_codex_thread_interactive(
|
||||
code_mode_session_provider: parent_session.services.code_mode_service.session_provider(),
|
||||
extensions,
|
||||
conversation_history,
|
||||
history_initialization,
|
||||
disabled_plugin_ids: (isolation == codex_extension_api::SessionIsolation::Inherit)
|
||||
.then(|| parent_ctx.disabled_plugin_ids.clone()),
|
||||
requested_history_mode: None,
|
||||
|
||||
@@ -26,6 +26,7 @@ use crate::client::X_CODEX_PARENT_THREAD_ID_HEADER;
|
||||
use crate::client::X_CODEX_TURN_METADATA_HEADER;
|
||||
use crate::client::X_CODEX_WINDOW_ID_HEADER;
|
||||
use crate::client::X_OPENAI_SUBAGENT_HEADER;
|
||||
use codex_history::HistoryInitialization;
|
||||
|
||||
pub(crate) const INSTALLATION_ID_KEY: &str = "installation_id";
|
||||
pub(crate) const SESSION_ID_KEY: &str = "session_id";
|
||||
@@ -43,6 +44,7 @@ pub(crate) const TOOL_NAMESPACES_INFO_KEY: &str = "tool_namespaces_info";
|
||||
pub(crate) const TURN_STARTED_AT_UNIX_MS_KEY: &str = "turn_started_at_unix_ms";
|
||||
pub(crate) const HISTORY_INGEST_REQUESTED_KEY: &str = "history_ingest_requested";
|
||||
pub(crate) const ANALYTICS_ENABLED_KEY: &str = "analytics_enabled";
|
||||
pub(crate) const HISTORY_INITIALIZATION_KEY: &str = "history_initialization";
|
||||
pub(crate) const MCP_ATTRIBUTION_CLIENT_METADATA_KEY: &str = "mcp_attribution";
|
||||
pub(crate) const MAX_MCP_ATTRIBUTION_BYTES: usize = 16 * 1024;
|
||||
|
||||
@@ -86,6 +88,7 @@ const RESERVED_METADATA_KEYS: &[&str] = &[
|
||||
TURN_STARTED_AT_UNIX_MS_KEY,
|
||||
HISTORY_INGEST_REQUESTED_KEY,
|
||||
ANALYTICS_ENABLED_KEY,
|
||||
HISTORY_INITIALIZATION_KEY,
|
||||
FORKED_FROM_THREAD_ID_KEY,
|
||||
FORKED_FROM_ORDINAL_EXCLUSIVE_KEY,
|
||||
PARENT_THREAD_ID_KEY,
|
||||
@@ -240,6 +243,7 @@ pub struct CodexResponsesMetadata {
|
||||
pub(crate) window_id: String,
|
||||
pub(crate) window_number: Option<u64>,
|
||||
pub(crate) context_window_id: Option<Uuid>,
|
||||
pub(crate) history_initialization: Option<HistoryInitialization>,
|
||||
pub(crate) request_kind: Option<CodexResponsesRequestKind>,
|
||||
pub(crate) forked_from_thread_id: Option<ThreadId>,
|
||||
pub(crate) forked_from_ordinal_exclusive: Option<u64>,
|
||||
@@ -285,6 +289,7 @@ impl CodexResponsesMetadata {
|
||||
window_id,
|
||||
window_number: None,
|
||||
context_window_id: None,
|
||||
history_initialization: None,
|
||||
request_kind: None,
|
||||
forked_from_thread_id: None,
|
||||
forked_from_ordinal_exclusive: None,
|
||||
@@ -428,6 +433,7 @@ impl CodexResponsesMetadata {
|
||||
.then_some(self.context_window_id)
|
||||
.flatten(),
|
||||
request_kind: request_kind_value,
|
||||
history_initialization: self.history_initialization,
|
||||
forked_from_thread_id: self.forked_from_thread_id,
|
||||
forked_from_ordinal_exclusive: self.forked_from_ordinal_exclusive,
|
||||
parent_thread_id: self.parent_thread_id,
|
||||
@@ -559,6 +565,8 @@ struct CodexTurnMetadataPayload<'a> {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
request_kind: Option<&'static str>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
history_initialization: Option<HistoryInitialization>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
forked_from_thread_id: Option<ThreadId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
forked_from_ordinal_exclusive: Option<u64>,
|
||||
|
||||
@@ -84,6 +84,7 @@ use codex_features::FEATURES;
|
||||
use codex_features::Feature;
|
||||
use codex_features::Features;
|
||||
use codex_features::unstable_features_warning_event;
|
||||
use codex_history::HistoryInitialization;
|
||||
use codex_history::RolloutItem;
|
||||
use codex_hooks::Hooks;
|
||||
use codex_hooks::HooksConfig;
|
||||
@@ -458,6 +459,7 @@ pub(crate) struct SessionSpawnArgs {
|
||||
pub(crate) code_mode_session_provider: Arc<dyn codex_code_mode::CodeModeSessionProvider>,
|
||||
pub(crate) extensions: Arc<codex_extension_api::ExtensionRegistry<crate::config::Config>>,
|
||||
pub(crate) conversation_history: InitialHistory,
|
||||
pub(crate) history_initialization: HistoryInitialization,
|
||||
pub(crate) disabled_plugin_ids: Option<Vec<String>>,
|
||||
pub(crate) requested_history_mode: Option<ThreadHistoryMode>,
|
||||
pub(crate) fork_persistence: ForkPersistence,
|
||||
@@ -572,6 +574,7 @@ impl Session {
|
||||
code_mode_session_provider,
|
||||
extensions,
|
||||
conversation_history,
|
||||
history_initialization,
|
||||
disabled_plugin_ids,
|
||||
requested_history_mode,
|
||||
fork_persistence,
|
||||
@@ -935,6 +938,7 @@ impl Session {
|
||||
tx_event.clone(),
|
||||
agent_status_tx.clone(),
|
||||
conversation_history,
|
||||
history_initialization,
|
||||
fork_persistence,
|
||||
session_source_clone,
|
||||
skills_service,
|
||||
|
||||
@@ -95,6 +95,7 @@ pub(crate) struct Session {
|
||||
pub(crate) services: SessionServices,
|
||||
pub(super) git_enrichment_policy: GitEnrichmentPolicy,
|
||||
pub(super) fork_persistence: ForkPersistence,
|
||||
pub(super) history_initialization: HistoryInitialization,
|
||||
pub(super) forked_from_ordinal_exclusive: Option<u64>,
|
||||
pub(super) next_internal_sub_id: AtomicU64,
|
||||
}
|
||||
@@ -740,6 +741,7 @@ impl Session {
|
||||
context_window_id: uuid::Uuid,
|
||||
) -> CodexResponsesMetadata {
|
||||
CodexResponsesMetadata {
|
||||
history_initialization: Some(self.history_initialization),
|
||||
window_number: Some(window_number),
|
||||
context_window_id: Some(context_window_id),
|
||||
mcp_attribution: Some(self.services.executed_tool_calls.mcp_attribution_snapshot()),
|
||||
@@ -774,6 +776,7 @@ impl Session {
|
||||
tx_event: Sender<Event>,
|
||||
agent_status: watch::Sender<AgentStatus>,
|
||||
mut initial_history: InitialHistory,
|
||||
history_initialization: HistoryInitialization,
|
||||
fork_persistence: ForkPersistence,
|
||||
session_source: SessionSource,
|
||||
skills_service: Arc<HostSkillsService>,
|
||||
@@ -1839,6 +1842,7 @@ impl Session {
|
||||
services,
|
||||
git_enrichment_policy,
|
||||
fork_persistence,
|
||||
history_initialization,
|
||||
forked_from_ordinal_exclusive,
|
||||
next_internal_sub_id: AtomicU64::new(0),
|
||||
});
|
||||
|
||||
@@ -6968,6 +6968,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
services,
|
||||
git_enrichment_policy: GitEnrichmentPolicy::Fresh,
|
||||
fork_persistence: ForkPersistence::Copied,
|
||||
history_initialization: HistoryInitialization::New,
|
||||
forked_from_ordinal_exclusive: None,
|
||||
next_internal_sub_id: AtomicU64::new(0),
|
||||
};
|
||||
@@ -7142,6 +7143,7 @@ async fn make_session_with_config_and_rx(
|
||||
tx_event,
|
||||
agent_status_tx,
|
||||
InitialHistory::New,
|
||||
HistoryInitialization::New,
|
||||
ForkPersistence::Copied,
|
||||
SessionSource::Exec,
|
||||
skills_service,
|
||||
@@ -7260,6 +7262,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
|
||||
));
|
||||
let environment_manager = Arc::new(EnvironmentManager::default_for_tests());
|
||||
|
||||
let history_initialization = HistoryInitialization::from_history(&initial_history);
|
||||
let session = Session::new(
|
||||
/*startup*/ None,
|
||||
session_configuration,
|
||||
@@ -7275,6 +7278,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
|
||||
tx_event,
|
||||
agent_status_tx,
|
||||
initial_history,
|
||||
history_initialization,
|
||||
ForkPersistence::Copied,
|
||||
session_source,
|
||||
skills_service,
|
||||
@@ -9231,6 +9235,7 @@ where
|
||||
services,
|
||||
git_enrichment_policy: GitEnrichmentPolicy::Fresh,
|
||||
fork_persistence: ForkPersistence::Copied,
|
||||
history_initialization: HistoryInitialization::New,
|
||||
forked_from_ordinal_exclusive: None,
|
||||
next_internal_sub_id: AtomicU64::new(0),
|
||||
});
|
||||
|
||||
@@ -1303,6 +1303,7 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {
|
||||
code_mode_session_provider: Arc::new(codex_code_mode::DisabledCodeModeSessionProvider),
|
||||
extensions: codex_extension_api::empty_extension_registry(),
|
||||
conversation_history: InitialHistory::New,
|
||||
history_initialization: HistoryInitialization::New,
|
||||
disabled_plugin_ids: None,
|
||||
requested_history_mode: None,
|
||||
fork_persistence: ForkPersistence::Copied,
|
||||
|
||||
@@ -10,6 +10,7 @@ pub(crate) use shutdown::thread_store_error_kind;
|
||||
|
||||
use crate::CodexAppsToolsCache;
|
||||
use crate::CodexThreadSettingsOverrides;
|
||||
use crate::agent::AgentStatus;
|
||||
use crate::agent::LocalAgentControl;
|
||||
use crate::agent::api::AgentConfigUpdate;
|
||||
use crate::agent::api::AgentControl;
|
||||
@@ -56,6 +57,7 @@ use codex_extension_api::ThreadInstructionsProvider;
|
||||
use codex_extension_api::UserInstructionsProvider;
|
||||
use codex_extension_api::empty_extension_registry;
|
||||
use codex_features::Feature;
|
||||
use codex_history::HistoryInitialization;
|
||||
use codex_history::InitialHistory;
|
||||
use codex_history::ResumedHistory;
|
||||
use codex_history::RolloutItem;
|
||||
@@ -2043,6 +2045,21 @@ impl ThreadManagerState {
|
||||
inherited_exec_policy,
|
||||
user_shell_override,
|
||||
} = request;
|
||||
let history_initialization = if matches!(
|
||||
&options.initial_history,
|
||||
InitialHistory::New | InitialHistory::Forked(_)
|
||||
) && let Some(source_thread_id) = forked_from_thread_id
|
||||
{
|
||||
if let Ok(source) = self.get_thread(source_thread_id).await
|
||||
&& source.agent_status().await != AgentStatus::Shutdown
|
||||
{
|
||||
HistoryInitialization::WarmFork
|
||||
} else {
|
||||
HistoryInitialization::ColdFork
|
||||
}
|
||||
} else {
|
||||
HistoryInitialization::from_history(&options.initial_history)
|
||||
};
|
||||
let StartThreadOptions {
|
||||
mut config,
|
||||
thread_instructions_provider,
|
||||
@@ -2281,6 +2298,7 @@ impl ThreadManagerState {
|
||||
code_mode_session_provider: Arc::clone(&self.code_mode_session_provider),
|
||||
extensions,
|
||||
conversation_history: initial_history,
|
||||
history_initialization,
|
||||
disabled_plugin_ids,
|
||||
requested_history_mode: history_mode,
|
||||
fork_persistence,
|
||||
|
||||
@@ -708,6 +708,10 @@ fn turn_metadata_state_ignores_client_reserved_metadata_before_start() {
|
||||
("parent_turn_id".to_string(), "client-supplied".to_string()),
|
||||
(ROOT_TURN_ID_KEY.to_string(), "client-supplied".to_string()),
|
||||
("subagent_kind".to_string(), "client-supplied".to_string()),
|
||||
(
|
||||
"history_initialization".to_string(),
|
||||
"client-supplied".to_string(),
|
||||
),
|
||||
(
|
||||
SANDBOX_MODE_KEY.to_string(),
|
||||
"danger-full-access".to_string(),
|
||||
@@ -731,6 +735,7 @@ fn turn_metadata_state_ignores_client_reserved_metadata_before_start() {
|
||||
assert!(json.get("parent_turn_id").is_none());
|
||||
assert!(json.get(ROOT_TURN_ID_KEY).is_none());
|
||||
assert!(json.get("subagent_kind").is_none());
|
||||
assert!(json.get("history_initialization").is_none());
|
||||
assert_eq!(json[SANDBOX_MODE_KEY].as_str(), Some("read-only"));
|
||||
assert_eq!(json[AUTO_REVIEW_ENABLED_KEY].as_bool(), Some(false));
|
||||
assert_eq!(
|
||||
|
||||
@@ -654,11 +654,13 @@ async fn direct_function_and_tool_search_mark_complete_attempts(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(false; "ungranted_provider")]
|
||||
#[test_case(true; "granted_provider")]
|
||||
#[test_case(false, false; "ungranted_provider")]
|
||||
#[test_case(true, false; "granted_provider_cold_fork")]
|
||||
#[test_case(true, true; "granted_provider_warm_fork")]
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn direct_metadata_limit_respects_provider_support(
|
||||
include_internal_metadata: bool,
|
||||
fork_from_running_thread: bool,
|
||||
) -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
let server = start_mock_server().await;
|
||||
@@ -844,7 +846,14 @@ async fn direct_metadata_limit_respects_provider_support(
|
||||
}
|
||||
|
||||
let rollout_path = test.codex.rollout_path().expect("rollout path");
|
||||
test.codex.shutdown_and_wait().await?;
|
||||
if fork_from_running_thread {
|
||||
test.codex.flush_rollout().await?;
|
||||
} else {
|
||||
test.codex.shutdown_and_wait().await?;
|
||||
test.thread_manager
|
||||
.remove_thread(&test.session_configured.thread_id)
|
||||
.await;
|
||||
}
|
||||
let rollout = tokio::fs::read_to_string(&rollout_path).await?;
|
||||
let rollout = rollout
|
||||
.lines()
|
||||
@@ -887,6 +896,10 @@ async fn direct_metadata_limit_respects_provider_support(
|
||||
.await
|
||||
.expect("shutdown fork");
|
||||
|
||||
if fork_from_running_thread {
|
||||
test.codex.shutdown_and_wait().await?;
|
||||
}
|
||||
|
||||
let resumed = search_capable_apps_builder(apps.chatgpt_base_url)
|
||||
.with_config(configure_metadata)
|
||||
.resume(&server, test.home.clone(), rollout_path)
|
||||
@@ -907,6 +920,36 @@ async fn direct_metadata_limit_respects_provider_support(
|
||||
|
||||
let requests = responses.requests();
|
||||
assert_eq!(requests.len(), 7);
|
||||
let expected_fork = if fork_from_running_thread {
|
||||
"warm_fork"
|
||||
} else {
|
||||
"cold_fork"
|
||||
};
|
||||
let initialization = requests
|
||||
.iter()
|
||||
.map(|request| {
|
||||
let body = request.body_json();
|
||||
let metadata: Value = serde_json::from_str(
|
||||
body["client_metadata"]["x-codex-turn-metadata"]
|
||||
.as_str()
|
||||
.expect("turn metadata"),
|
||||
)
|
||||
.expect("valid turn metadata");
|
||||
metadata["history_initialization"].clone()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
Value::Array(initialization),
|
||||
json!([
|
||||
"new",
|
||||
"new",
|
||||
"new",
|
||||
expected_fork,
|
||||
expected_fork,
|
||||
"cold_resume",
|
||||
"cold_resume"
|
||||
])
|
||||
);
|
||||
for request in &requests[3..] {
|
||||
for original in [&first_output, &second_output] {
|
||||
let call_id = original["call_id"].as_str().expect("call ID");
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
//! Request-only provenance for the history installed when a runtime starts.
|
||||
//! Warm resumes retain this value: reconnecting does not reconstruct history or
|
||||
//! explain metadata that was already missing before the reconnect.
|
||||
|
||||
use crate::InitialHistory;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Describes a reconstruction path, not proof that tool metadata was captured or lost.
|
||||
/// Fork temperature records whether the source runtime was loaded and not shut down
|
||||
/// at initialization. The value lasts for the runtime, including after compaction;
|
||||
/// consumers must check missing tool metadata independently for each window.
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum HistoryInitialization {
|
||||
New,
|
||||
Cleared,
|
||||
ColdResume,
|
||||
WarmFork,
|
||||
ColdFork,
|
||||
SuppliedHistory,
|
||||
}
|
||||
|
||||
impl HistoryInitialization {
|
||||
/// Classifies history without assuming that a fork's source runtime is available.
|
||||
pub fn from_history(history: &InitialHistory) -> Self {
|
||||
match history {
|
||||
InitialHistory::New => Self::New,
|
||||
InitialHistory::Cleared => Self::Cleared,
|
||||
InitialHistory::Resumed(_) => Self::ColdResume,
|
||||
// Callers with a known fork source supply its runtime availability.
|
||||
InitialHistory::Forked(_) => Self::SuppliedHistory,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,9 @@ pub use compaction_resume_metadata::resume_multi_agent_version;
|
||||
mod compaction_checkpoint;
|
||||
pub use compaction_checkpoint::CompactionCheckpoint;
|
||||
|
||||
mod initialization;
|
||||
pub use initialization::HistoryInitialization;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
Reference in New Issue
Block a user