Skip to content

CFE-4681: default timer_policy => reset for classes: promises (3.28.0)#6174

Open
nickanderson wants to merge 3 commits into
cfengine:masterfrom
nickanderson:CFE-4681/default-reset-master
Open

CFE-4681: default timer_policy => reset for classes: promises (3.28.0)#6174
nickanderson wants to merge 3 commits into
cfengine:masterfrom
nickanderson:CFE-4681/default-reset-master

Conversation

@nickanderson

@nickanderson nickanderson commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Flips the default timer_policy for classes: promises from absolute to reset for 3.28.0.

#6167 introduced the timer_policy attribute on classes: promises with a default of absolute (preserve) for backward compatibility. This PR changes that default to reset so that:

  • classes: promises align with classes bodies, whose timer_policy has always defaulted to reset.
  • A persistent class that keeps being rediscovered keeps persisting, rather than lapsing once its original timer expires — matching what most users expect.

Setting timer_policy => "absolute" explicitly restores the previous skip-and-preserve behavior.

⚠️ Stacked on #6167 — merge that first

This branch is based on CFE-4681/timer-policy-classes-promises (the #6167 head), so until #6167 merges to master this PR's diff shows both. The change unique to this PR is the final commit, 07657cce4.

⚠️ Master-only — do NOT backport

The timer_policy attribute is being backported to the LTS streams (3.27.2, 3.24.5) with the long-standing absolute default preserved, so behavior on those releases is unchanged and reset stays opt-in there. This default flip is intentional for 3.28.0 only.

Changes

  • GetContextConstraints() (attributes.c): resolve the timer policy to RESET by default; only an explicit timer_policy => "absolute" selects PRESERVE.
  • ExpandDeRefPromise() (promises.c): an already-defined persistent class is no longer skipped unless timer_policy => "absolute" is set, so the default reset can refresh the timer.
  • mod_common.c: syntax doc default for the classes: promise timer_policy updated to reset.
  • Acceptance test persistent_timer_policy_default.cf: a classes: promise with no timer_policy resets the timer on a subsequent run.

Test plan

  • libpromises compiles clean (full-binary link blocked locally by an unrelated ASan toolchain issue; relying on CI for the binary build + acceptance run)
  • CI acceptance tests pass, including the existing persistent_timer_policy.cf (explicit absolute → still skipped) and the new persistent_timer_policy_default.cf (default → reset)

Ticket: CFE-4681

…ntSave

ValueSizeDB() was called with strlen(key), but WriteDB(), ReadDB() and
DeleteDB() store and look up keys with strlen(key) + 1 (including the
terminating NUL), and LMDB matches keys by exact byte length. The lookup
therefore never found the stored record and always reported size 0.

Passing strlen(key) + 1 makes the lookup match the key as written. This
lets EvalContextHeapPersistentSave() find an existing record and act on
it: preserve an already-set, unexpired timer (CONTEXT_STATE_POLICY_PRESERVE)
and log "Resetting" rather than "Creating" on a RESET save.

Ticket: CFE-4681
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nickanderson

Copy link
Copy Markdown
Member Author

@cf-bottom jenkins please

@cf-bottom

Copy link
Copy Markdown

nickanderson and others added 2 commits June 12, 2026 13:34
Add a timer_policy attribute to classes: promises, controlling whether a
persistent class timer resets on re-evaluation ("reset") or preserves the
original expiry ("absolute"). Defaults to "absolute" for backward
compatibility; planned to change to "reset" in 3.28.0 to match classes
bodies, keeping "absolute" on the 3.24 and 3.27 LTS backports.

timer_policy without persistence is now an error, since it only governs
the persistence timer.

Ticket: CFE-4681
Changelog: Title
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CFE-4681 added a timer_policy attribute to classes: promises with the
default "absolute" (preserve) for backward compatibility. For 3.28.0 the
default becomes "reset", aligning classes: promises with classes bodies
(whose timer_policy has always defaulted to reset) and matching the
common expectation that a persistent class which keeps being
rediscovered should keep persisting rather than lapsing.

- GetContextConstraints(): default the resolved timer policy to RESET;
  only an explicit timer_policy => "absolute" selects PRESERVE.
- ExpandDeRefPromise(): an already-defined persistent class is no longer
  skipped unless timer_policy => "absolute" is set, so the default reset
  can refresh the timer.
- Update the classes: promise syntax doc default to "reset".
- Acceptance test persistent_timer_policy_default.cf: a classes: promise
  with no timer_policy resets the timer on a subsequent run.

This is a master-only change. The timer_policy attribute itself is being
backported to the 3.27.x and 3.24.x LTS streams (3.27.2, 3.24.5) with
the long-standing "absolute" default preserved, so behavior there is
unchanged and reset remains opt-in.

Ticket: CFE-4681
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nickanderson

Copy link
Copy Markdown
Member Author

@cf-bottom jenkins please

@cf-bottom

Copy link
Copy Markdown

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants