Skip to content

Conversation

@Geoff-Robin
Copy link
Contributor

@Geoff-Robin Geoff-Robin commented Feb 5, 2026

Key Changes

  • Removed PyKey

    • The custom PyKey struct and its serialization logic were entirely deleted from rust/py/src/value.rs.
    • This type previously allowed wrapping arbitrary Python objects as keys by serializing them.
  • Adoption of StableKey

    • The code was updated to use StableKey instead.
    • This enforces a stricter, more deterministic type system for keys used in target states, likely improving reliability and cross-connector compatibility.
  • Rust Implementation Update

    • Target State: Updated TargetState in rust/py/src/target_state.rs to interact with this new key type.
    • Path Bridging: Added support code in rust/core/src/state/stable_path.rs and rust/py/src/stable_path.rs to bridge the new key references.

Resolves this particular issue

@badmonster0 badmonster0 requested a review from georgeh0 February 9, 2026 02:42
@badmonster0
Copy link
Member

thanks a lot @Geoff-Robin will get back on this shortly! thanks a lot for your contributions!

Comment on lines +189 to +216
impl crate::engine::profile::Persist for StableKey {
fn to_bytes(&self) -> Result<bytes::Bytes> {
let buf = storekey::encode_vec(self)
.map_err(|e| internal_error!("Failed to encode StableKey: {e}"))?;
Ok(bytes::Bytes::from(buf))
}

fn from_bytes(data: &[u8]) -> Result<Self> {
storekey::decode(std::io::Cursor::new(data))
.map_err(|e| internal_error!("Failed to decode StableKey: {e}"))
}
}

impl crate::engine::profile::StableFingerprint for StableKey {
fn stable_fingerprint(&self) -> utils::fingerprint::Fingerprint {
match self {
StableKey::Fingerprint(fp) => *fp,
_ => {
let mut fingerprinter = utils::fingerprint::Fingerprinter::default();
let bytes = crate::engine::profile::Persist::to_bytes(self)
.expect("StableKey encoding for fingerprint");
fingerprinter.write_raw_bytes(&bytes);
fingerprinter.into_fingerprint()
}
}
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to add these. StableKey itself is already serializable and deserializable.

Since StableKey is a type defined in the core crate, we can remove TargetStateKey and directly use StableKey. So we can directly serialize/deserialize it in the engine code.


use cocoindex_core::state::stable_path::{StableKey, StablePath};

impl PyStableKey {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to implement IntoPyObject for PyStableKey instead (which matches FromPyObject below)

#[pyfunction]
pub fn declare_target_state<'py>(
py: Python<'py>,
_py: Python<'py>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need this argument.

):
if isinstance(key, tuple) and not isinstance(key, _TableKey):
key = _TableKey(*key)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type annotation key: _TableKey is not right now. I think we want to use key: StableKey instead, since it's the actual type being passed around. We can remove KeyT / KeyT_contra here, and directly use StableKey.

This will also force each reconcile() implementation explicitly convert the type, so implementers won't forget.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants