Skip to content

Commit ba9dea9

Browse files
spec: add hard state-byte limits
1 parent 90a51ae commit ba9dea9

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

docs/spec/picante.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,11 @@ impl Label {
662662
> r[intern.dedup]
663663
> Interning MUST be value-deduplicating: if two calls intern values `v1` and `v2` such that `v1 ≈ v2` (per `r[equality.relation]` for that interned kind), they MUST return the same intern ID.
664664
665+
> r[intern.limits]
666+
> If interning a value would require creating a new unique intern entry and doing so would exceed the configured state-byte limit (see `r[limit.enforced]`), the intern operation MUST fail with `LimitExceeded` and MUST have no observable effects.
667+
>
668+
> If the value is already present in the intern table, the intern operation MUST succeed and return the existing intern ID regardless of the current state-byte usage.
669+
665670
> r[intern.immutable]
666671
> The observable value of an interned record addressed by an intern ID MUST be immutable for the lifetime of the process.
667672
> Reads through an intern ID MUST always return the same value.
@@ -734,6 +739,36 @@ Such sharing MUST NOT change observable behavior: the values and errors returned
734739

735740
This section specifies which in-memory structures MAY be bounded and evicted without changing observable semantics.
736741

742+
## Hard size limits (non-evictable state)
743+
744+
To avoid unbounded growth of long-lived in-memory database state, Picante MUST support a hard limit on the size of the non-evictable portion of the database.
745+
746+
The **non-evictable state** is:
747+
748+
- all input slots and their stored values (including keys and metadata needed to preserve their observable behavior), and
749+
- the intern table (including values needed to preserve the meaning of existing intern IDs).
750+
751+
Derived-query memoization, dependency metadata, and other caches are not part of the non-evictable state (they may be evicted per the rules below).
752+
753+
> r[limit.state-bytes]
754+
> The implementation MUST define a byte accounting scheme for the non-evictable state (“state bytes”).
755+
> The accounting is implementation-defined but MUST be deterministic and conservative:
756+
>
757+
> - If an operation would increase the implementation’s actual retained memory for non-evictable state, it MUST NOT decrease the accounted state bytes.
758+
> - State bytes MUST be measured per database (shared across views).
759+
>
760+
> The accounting MUST include keys and values (or their retained representations) for input slots and interned values.
761+
762+
> r[limit.enforced]
763+
> The implementation MUST allow configuring a maximum number of state bytes per database.
764+
> If a mutation would cause state bytes to exceed the configured maximum, the mutation MUST fail with a `LimitExceeded` error and MUST have no observable effects:
765+
>
766+
> - No partial state changes are permitted.
767+
> - The view revision MUST NOT advance.
768+
> - No invalidation or events may be emitted as a result of the failed mutation.
769+
>
770+
> This applies equally to single mutations and batches.
771+
737772
## Inputs are not implicitly evictable
738773

739774
Input ingredients are part of the observable database state.
@@ -778,4 +813,6 @@ Poisoning is an observable behavior at a given revision (errors are memoized for
778813
Interned records are stable identity tokens.
779814

780815
> r[evict.interned]
781-
> Intern tables MUST be treated as unbounded within a process: implementations MUST NOT evict or compact interned records in a way that changes the meaning of an existing intern ID.
816+
> Intern tables are part of the non-evictable state and MUST NOT be evicted or compacted in a way that changes the meaning of an existing intern ID.
817+
>
818+
> Intern tables MAY still be bounded via `r[limit.enforced]` by refusing to create new unique intern entries once the configured state-byte limit would be exceeded.

0 commit comments

Comments
 (0)