Skip to content

0.1.6

Choose a tag to compare

@captainpacket captainpacket released this 11 Sep 16:26
· 28 commits to main since this release

Added

  • Paging no longer reports a stall on a query whose rows are identical. The
    guard compared each page's first and last row, so select {n: 1} produced the
    same signature on every page whether the offset advanced or not, and raised
    "paging is not advancing" at repeat_limit * page_size rows on a query that
    was paging correctly. A page whose first and last rows match is now skipped as
    carrying no evidence, and the message names the other possibility.

    Reported as a Forward-side cap at 250,000 rows. It is not one: 250,000 is the
    default repeat_limit of 25 times a 10,000-row page. Verified against a
    545,464-row result, which now pages to completion in 55 pages, and where
    Forward returns 3 rows at offset 545,461 and 0 at 545,464, so the offset is
    honoured to the last row.

    A genuinely stalled server returning uniform rows is no longer diagnosed by
    this guard. It still terminates, bounded by max_rows, max_pages and the
    reported total.

  • A failed NQE query now says what was wrong with it. Forward's message is the
    fixed string "Error encountered while executing the NQE query" for every
    failure, whatever went wrong; the detail lives in a separate errors list
    that the SDK carried on the exception but left out of its message, so every
    query failure read identically in a log. Up to three diagnostics, with line
    and column, now reach the message, and the full list stays on query_errors.

  • CounterSnapshot reads as a mapping, so dict(snapshot) and **snapshot
    work. It always had as_dict(), but nothing signalled that, and a consumer
    who tried the obvious thing concluded it could not be serialized.

  • error.denial on an API error, which says what kind of refusal it is. Read
    from Forward's server source rather than inferred: its access enforcer sets
    reason to null on every refusal, so no code distinguishes a missing
    permission from an unlicensed feature from a setting switched off, but its
    wording does. Six kinds are recognised, each from the enforcer's own format
    string. This is prose rather than a contract, so it is documented as something
    to show an operator rather than something to branch on.

    This narrows a question the SDK previously called unanswerable. Denials remain
    indistinguishable by status code; they are not indistinguishable in practice.

  • use_latest_data_files on nqe.execute(). A published field on the execution
    request that the SDK never sent, so a caller could not evaluate a query
    against the most recently uploaded data files instead of the versions the
    snapshot captured.

  • snapshot_cache_ttl="lifetime", which resolves a snapshot once and keeps that
    answer for the life of the client. A number of seconds was the wrong shape for
    the case the setting was added for: a run that has pinned one point in time
    does not want the answer to change underneath it, and a TTL expiring mid-run
    lets the next resolution return a different snapshot, so the run straddles two
    moments with nothing raising and the data real on both sides.

    Seconds remain right for repeated independent reads, and the documentation now
    says which shape suits which caller rather than leaving it to be discovered.
    "lifetime" still yields to an upload through the same client, because that is
    an event that makes the answer wrong rather than merely old. Suggested by the
    Nautobot integration, whose own cache is lifetime-scoped for this reason.