Skip to content

feat: Implement indexed_timestamp field for package records - #2502

Draft
pavelzw wants to merge 4 commits into
mainfrom
claude/zealous-rubin-e3vdnx
Draft

feat: Implement indexed_timestamp field for package records#2502
pavelzw wants to merge 4 commits into
mainfrom
claude/zealous-rubin-e3vdnx

Conversation

@pavelzw

@pavelzw pavelzw commented Jun 11, 2026

Copy link
Copy Markdown
Member

Description

This PR implements support for the indexed_timestamp field in package records, as specified in CEP 154. The indexed_timestamp field tracks when a package was first added to a channel index by an indexing tool, distinct from the build timestamp set by build tools.

Key changes:

  1. Core field addition: Added indexed_timestamp: Option<TimestampMs> to PackageRecord in rattler_conda_types, with proper serialization/deserialization support.

  2. Indexing logic:

    • New packages are always assigned the current indexing time
    • Previously indexed packages preserve their indexed_timestamp across re-indexing runs, even with force mode
    • Packages with future build timestamps are rejected to prevent invalid state
    • Backfill modes for records lacking the field:
      • FromCondaPackageTimestamp (default): Seeds from package build timestamp, clamped to indexing time
      • Now: Seeds with current indexing time
      • Off: Leaves records untouched
  3. Solver integration: The exclude_newer constraint now prefers indexed_timestamp over build timestamp when filtering packages, with appropriate messaging to users.

  4. Configuration: Added BackfillIndexedTimestamps enum to rattler_config with CLI and config file support.

  5. Python bindings: Exposed indexed_timestamp property in PackageRecord and PrefixRecord Python classes.

  6. Comprehensive testing: Added tests covering timestamp assignment, preservation across re-indexing, backfill modes, future timestamp rejection, and solver behavior with indexed timestamps.

How Has This Been Tested?

  • Added integration tests in basic_indexing.rs:

    • test_indexed_timestamp_assignment_and_preservation: Verifies assignment on new packages and preservation across re-indexing
    • test_indexed_timestamp_backfill_modes: Tests all three backfill modes
    • test_index_rejects_future_build_timestamp: Validates rejection of future-dated packages
  • Added solver tests in min_age_tests.rs:

    • solve_min_age_prefers_indexed_timestamp: Confirms indexed time takes precedence
    • solve_min_age_indexed_timestamp_overrides_new_build_timestamp: Tests override behavior
    • solve_min_age_falls_back_to_build_timestamp: Validates fallback for records without indexed_timestamp
  • Added Python tests in test_index.py and test_package_record.py covering roundtrip serialization and timestamp assignment

  • Existing tests updated to include the new backfill_indexed_timestamps configuration field

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (README.md updated)
  • I have added sufficient tests to cover my changes

https://claude.ai/code/session_01KvrZfUCxfjQzPBJKzPG5Ez

Implements the indexed_timestamp CEP (conda/ceps#154): an optional field on
package records holding the Unix epoch milliseconds at which an indexing tool
first added the artifact to the channel index.

- Add `indexed_timestamp: Option<TimestampMs>` to `PackageRecord`. Build
  tools never set it (`IndexJson` is unchanged) and repodata patching cannot
  modify it (it is not part of the `PackageRecordPatch` whitelist).
- rattler-index stamps newly indexed packages with the indexing time (one
  value per subdir run), preserves previously assigned values across
  re-indexing runs including `--force`, and rejects packages whose build
  timestamp is in the future of the indexing time.
- New `backfill-indexed-timestamps` option (TOML config, CLI flag, and
  py-rattler kwarg) controlling how records in existing repodata that lack
  the field are seeded: `from-conda-package-timestamp` (default, clamped to
  the indexing time), `now`, or `off`.
- `exclude-newer` filtering in both solver backends now prefers
  `indexed_timestamp` over the builder-provided `timestamp`, with an
  aggregated warning when records lack the field.
- Expose an `indexed_timestamp` property on py-rattler's `PackageRecord`.

https://claude.ai/code/session_01KvrZfUCxfjQzPBJKzPG5Ez
@pavelzw pavelzw changed the title Implement indexed_timestamp field for package records feat: Implement indexed_timestamp field for package records Jun 11, 2026
@baszalmstra

Copy link
Copy Markdown
Collaborator

Tiny nitpick: Its not CEP 154, its just a draft CEP without a name.

Comment on lines +83 to +115
impl BackfillIndexedTimestamps {
const FROM_CONDA_PACKAGE_TIMESTAMP: &str = "from-conda-package-timestamp";
const NOW: &str = "now";
const OFF: &str = "off";
}

impl FromStr for BackfillIndexedTimestamps {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
Self::FROM_CONDA_PACKAGE_TIMESTAMP => Ok(Self::FromCondaPackageTimestamp),
Self::NOW => Ok(Self::Now),
Self::OFF => Ok(Self::Off),
_ => Err(format!(
"invalid value `{s}`, expected one of `{}`, `{}`, `{}`",
Self::FROM_CONDA_PACKAGE_TIMESTAMP,
Self::NOW,
Self::OFF
)),
}
}
}

impl std::fmt::Display for BackfillIndexedTimestamps {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::FromCondaPackageTimestamp => Self::FROM_CONDA_PACKAGE_TIMESTAMP,
Self::Now => Self::NOW,
Self::Off => Self::OFF,
})
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The derive-more crates has some functionality for this.

@pavelzw

pavelzw commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

please don't review this pr yet, i haven't even looked at the code myself 😭

claude added 2 commits June 11, 2026 09:52
- Derive `Display`/`FromStr` for `BackfillIndexedTimestamps` via strum
  (already a workspace dependency) instead of hand-rolled impls.
- Clarify that the indexed_timestamp CEP is a draft proposal without an
  assigned number.

https://claude.ai/code/session_01KvrZfUCxfjQzPBJKzPG5Ez
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants