Skip to content

v1.2.0

@crajah crajah tagged this 02 Sep 00:19
Polling a growing vertex table must not mean fetching it. A production
consumer's event scheduler loaded every event per realm each tick to find
the few whose due_at had passed, and its work queue loaded the whole ledger
to find undone rows -- client-side filtering that OOMed workers. The
predicate now pushes into SQL.

find_vertices and find_edges callers keep their exact behaviour; new
optional parameters extend both clients identically:

- where: (key, op, value) triples over the JSONB payload, ops
  = != < <= > >= is_null not_null in, ANDed with the containment filters.
  Values always bind as parameters; keys validate against
  ^[A-Za-z0-9_.-]+$ before entering the accessor. int/float compare via
  (payload->>'k')::numeric; str compares as text, so zero-padded sortable
  strings keep their text ordering. is_null covers absent keys and JSON
  null alike, which is what "not done yet" means to a queue.
- order_by / descending: ORDER BY on a payload key with a stable id
  tie-break, numeric when a numeric predicate references the same key.
- count_vertices: the same predicates under COUNT(*), no row transfer.
- delete_vertices: bulk delete returning rows deleted, cascading edges and
  audited like delete_vertex. Refuses an empty where -- a full-table wipe
  must be the explicit delete_realm.
- create_payload_index: CREATE INDEX IF NOT EXISTS on the accessor
  expression (cast when numeric=True), deterministically named, so calling
  it at startup is the whole deployment story.

34 new tests cover every operator, the numeric-vs-text cast rule,
order_by with limit, is_null on absent keys, the empty-where refusal,
hostile keys and ops, and schema_per_realm on and off for every new
method, against live PostgreSQL through both clients. 614 pass in total.
Assets 2
Loading