Skip to content

docs: introduce Connect section, connect-string reference, QWP stubs#444

Open
bluestreak01 wants to merge 120 commits into
mainfrom
docs/connect-and-qwp-scaffolding
Open

docs: introduce Connect section, connect-string reference, QWP stubs#444
bluestreak01 wants to merge 120 commits into
mainfrom
docs/connect-and-qwp-scaffolding

Conversation

@bluestreak01

@bluestreak01 bluestreak01 commented May 13, 2026

Copy link
Copy Markdown
Member

Summary

Consolidates how-applications-talk-to-QuestDB content under a single Connect supersection. The native QWP clients, the compatibility protocols (ILP / PGWire / REST), and the wire-protocol specifications now share one home. The connect-string reference at documentation/client-configuration/connect-string.md anchors the section as the comprehensive knob doc.

Related PR: URL redirects for all the moved pages are handled in questdb/questdb.io#2917 (parent-website netlify.toml).

What's new

Sidebar restructure

  • New top-level Connect section absorbs Client Libraries, Compatibility Protocols, and Wire Protocols.
  • Per-language client pages grouped under Connect → Client Libraries.
  • ILP, PGWire, REST API live under Connect → Compatibility Protocols.
  • Wire-protocol specs (QWP) live under Connect → Wire Protocols for the client-implementer audience.

Connect → Overview (documentation/ingestion/overview.md)

  • Rewritten as "Connect to QuestDB" — QWP-native framing.
  • Decision table mapping situation → recommended path.
  • Per-language QWP support matrix (Java, C & C++, Rust, Go, .NET shipping; Python and Node.js planned).
  • Highlights: binary on the wire, streaming both directions (sustained 800 MiB/s ingress, up to 2.5 GiB/s egress), automatic failover, store-and-forward with sub-200 ns offload latency.

Connect → Connect string reference (documentation/client-configuration/connect-string.md, new)

  • Vertical TOC at the top.
  • Common patterns — 5 worked connect strings for local dev, basic-auth TLS, custom trust store, SF + multi-host, replica + zone-aware query.
  • Recipes — 21-row goal → keys table with direction (ingress / egress / both).
  • Per-section direction tags (*Applies to: ingress.* / *Applies to: ingress and egress.*).
  • Sender restart and replay sub-section: API trigger, lock semantics, replay mechanism, at-least-once + DEDUP contract.
  • Enterprise admonitions for multi-host failover, durable ACK, and egress failover.
  • DEDUP warning for tables ingested through a failover connect string.
  • Default ports column in the schemas table — explicit "wss does NOT default to 443" call-out.
  • sf_dir path handling (no shell expansion, parent must exist).
  • sender_id validation (allowed characters, lock-collision semantics).
  • Alphabetical Key index appendix.

Wire Protocols scaffolding (documentation/protocols/, new)

  • Overview + three stubs: QWP Ingress (WebSocket), QWP Ingress (UDP), QWP Egress (WebSocket).
  • Audience banners on each page identify the implementer-only readership.

Touch-ups

  • Repointed broken anchor #first-party-clients#client-libraries in capacity-planning.md, monitoring-alerting.md, datatypes/overview.md, and src/components/Resources/index.tsx.
  • Rewrote the date-to-timestamp-conversion frontmatter description from a bare language list to an actual summary.

Project handoff (ONBOARDING.md)

Bundle B / A / C team handoff document captured at repo root — assignments, coordination rules, first-prompt templates for the remaining work streams (Wire-protocol content, Client failover, Store-and-forward concepts). Reviewers can opt to keep or remove from this PR.

Out of scope (intentionally)

  • HTTP / HTTPS / TCP / TCPS ILP transports are documented only under Connect → Compatibility Protocols → ILP. The connect-string reference is QWP-native; ILP-specific knobs (protocol_version, retry_timeout, request_timeout, request_min_throughput) are not duplicated.
  • Client failover behavioural model and Store-and-forward concepts pages are scaffolded as forward-refs from the connect-string reference; they'll land in a follow-up PR.

Known follow-ups

  • Replace "Coming with Bundle C" project-internal phrasing in the connect-string reference with neutral cross-refs once the failover and SF concept pages land.
  • Strengthen the visual treatment of reserved-but-not-shipping options (sf_durability=flush|append, the on_*_error family) so LLM auto-completion is less likely to surface them as available.
  • Add per-language file moves and HTTP-side URL redirects in a separate restructure PR. Redirects now handled in questdb/questdb.io#2917.

Test plan

  • yarn build — 353 pages generated, no broken links / anchors
  • Visual review of the Connect → Connect string reference page on desktop and mobile (the Recipes and Key index tables are wide)
  • Confirm the target / zone framing matches the QuestDB Enterprise feature story
  • Verify the QWP support matrix accurately reflects shipping languages
  • Decide whether ONBOARDING.md should remain at repo root

🤖 Generated with Claude Code

glasstiger and others added 2 commits May 13, 2026 18:34
Consolidate how-applications-talk-to-QuestDB content under a single
Connect supersection. Rewrite the ingestion overview as QWP-native
"Connect to QuestDB", add a comprehensive connect-string reference at
documentation/client-configuration/, and scaffold the Wire Protocols
sub-section under documentation/protocols/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 13, 2026

Copy link
Copy Markdown

🤖 Component Converter Reminder

A component in src/components/ or src/theme/ was modified in this pull request.

We are creating markdown correspondents of every path (e.g. questdb.com/docs/quick-start/ → questdb.com/docs/quick-start.md) for LLM consumption.
If the component usage is shadowing useful content, it may need a converter for markdown output in convert-components.js.

Quick Check

  • Content component (code, tables, data) → Add converter if not exists
  • UI/visual component (styling, buttons, decorative) → No converter needed

💡 This is a friendly reminder, not a blocker. Ignore if not applicable.

@github-actions

github-actions Bot commented May 13, 2026

Copy link
Copy Markdown

🚀 Build success!

Latest successful preview: https://preview-444--questdb-documentation.netlify.app/docs/

Commit SHA: 549d492

📦 Build generates a preview & updates link on each commit.

@glasstiger glasstiger mentioned this pull request May 14, 2026
glasstiger and others added 19 commits May 14, 2026 14:24
- Add "Why implement a QWP client" pitch and "Client lifecycle" narrative
  so new implementers can orient before diving into encoding details.
- Spell out sequence numbering (server-assigned by receive order, not in
  the wire header), Gorilla first-DoD anchor, decimal scale formula
  (value = unscaled / 10^scale), and VARCHAR offset endianness — closes
  silent-wrong-guess risks for one-shot client generation.
- Collapse Symbol section to WebSocket-only (per-table dict is UDP) and
  drop the now-stranded per-table example.
- Document the practical WebSocket frame cap: http.recv.buffer.size
  (default 2 MiB) is the real ceiling, not the 16 MB protocol limit;
  exceeding it returns close code 1009 MESSAGE_TOO_BIG.
- Fill out durable-ack semantics: watermark trails OK, empty messages
  trivially durable, reconnects discard in-flight tracking.
- Note X-QWP-Client-Id may influence version selection.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…/questdb/documentation into docs/connect-and-qwp-scaffolding

# Conflicts:
#	documentation/protocols/qwp-ingress-websocket.md
- Add "Why implement a QWP query client" pitch and "Client lifecycle"
  narrative paralleling the ingress doc; surfaces the java-questdb-client
  reference impl link upfront.
- Document the practical WebSocket frame cap on /read/v1: client-to-server
  frames (QUERY_REQUEST in particular) are bounded by http.recv.buffer.size
  (default 2 MiB), not the 16 MiB protocol limit; oversized frames are
  rejected with close code 1009 MESSAGE_TOO_BIG.
- Clarify X-QWP-Max-Batch-Rows only asks for smaller batches than the
  server default (clamps to server's hard limit).
- Tighten NULL sentinel docs: FLOAT/DOUBLE sentinel is *any* NaN (incl.
  0.0/0.0); IPv4 0.0.0.0 and all-ones GEOHASH cannot round-trip as
  non-null.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sage Brokers up to Connect

- Add a "Use QWP for new clients" tip callout to ilp/overview.md naming
  QWP's wins (binary, type-rich, faster, failover, store-and-forward)
  and framing ILP as the path for InfluxDB / Telegraf / Kafka / Flink
  users who already emit ILP.
- Shorter callout on ilp/columnset-types.md reframing the page as
  "extensions on top of the InfluxDB type model" and noting QWP exposes
  the full QuestDB type system natively (no suffix encoding, no casts).
- Operator-facing callout on ilp/advanced-settings.md flagging this page
  as the legacy ILP tuning surface and pointing new deployments at QWP.
- Sidebar: lift Java Embedded and Message Brokers out from under ILP
  (they're protocol-agnostic delivery mechanisms, not ILP sub-pages).
  Final Connect order: Overview, Connect string, Date to Timestamp,
  Client Libraries, Message Brokers, Compatibility Protocols, Java
  Embedded, Wire Protocols.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eader)

The egress endpoint /read/v1 is asymmetric on the wire: server-to-client
frames carry the 12-byte QWP header, but client-to-server frames start
directly with msg_kind — no QWP header. Including the header makes the
server read 0x51 (the ASCII 'Q' of "QWP1") as an unknown msg_kind and
close the WebSocket with code 1006, partway through send.

Verified against server (QwpEgressUpgradeProcessor.dispatchEgressMessage
calls peekMsgKind at offset 0 of the WS frame body) and Java reference
client (QwpEgressIoThread.sendQueryRequest writes msg_kind as the first
byte, no header). The upstream wire-egress.md spec is wrong on this
point and should be filed separately.

- Rewrite Message structure section with two ASCII diagrams (server-to-
  client with header, client-to-server without) and a warning callout
  naming the symptom and the reason (server keeps the header for
  RESULT_BATCH's flags + payload_length; client control frames have no
  analogous need).
- Fix Example 1: drop the bogus 12-byte header from the QUERY_REQUEST
  hex dump; RESULT_BATCH / RESULT_END below unchanged.
- Client lifecycle step 4: inline note that the binary frame body starts
  directly with msg_kind for client-to-server frames.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New page (documentation/connect/agents.md) covering how AI agents operate
QuestDB across three angles: protocols, tooling, and operational practices.

Positioning:
- QWP egress is the recommended path for SQL execution (DDL + streaming
  SELECT), with native client libraries when available and the protocol
  spec for clean-room implementations.
- QWP ingress is the recommended path for all writes (bulk and sustained),
  including local-file uploads — the recipe explicitly calls out the
  failure mode where agents reach for read_parquet/read_csv/COPY, which
  require server-side filesystem access.
- REST is positioned for schema discovery and small ad-hoc queries that
  fit in a single HTTP response.
- PGWire and /imp are intentionally not recommended (superseded by QWP).
- No MCP framing: an MCP server would just wrap REST + QWP without adding
  capability, so the page tells agents to use the underlying protocols
  directly.

Includes a Recipes section seeded with the local-file upload recipe;
links to the existing Getting Started > AI Coding Agents page for the
tooling quickstart and the QuestDB / TSBS Claude skills.

Sidebar:
- Add Connect > Agents (between Client Libraries and Message Brokers).
- Move Date to Timestamp inside Client Libraries (cross-cutting reference
  for all language clients).
- Move Connect string inside Client Libraries as the first item (config
  schema shared by every QWP client).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The connect/QWP scaffolding rename sweep missed two files, leaving 8
internal link references pointing at moved pages and breaking the build
(onBrokenLinks: throw).

- changelog.mdx: ilp/overview and telegraf -> /docs/connect/...
- concepts/deep-dive/sql-extensions.md: six pgwire links ->
  /docs/connect/compatibility/pgwire/...

yarn build now passes (365 pages, 0 broken links).
The connect-string error-handling section linked to
questdb/questdb-enterprise (a private repo, and the referenced
sf-client.md path does not even exist there), leaving the QWP
error-policy precedence rules inaccessible to public readers.

Replace the dead private link with the precedence model inlined and a
pointer to the public spec in questdb/java-questdb-client.

Cross-checked against the client source:
- on_*_error knobs and errorPolicy/errorPolicyResolver are NOT yet
  implemented (parser does not recognise them, no builder methods);
  they exist only as the SenderError.Policy spec. Reword accordingly.
- errorHandler(...) and error_inbox_capacity are the only wired
  error-handling surfaces today (WebSocket/QWP only).
- Document accepted values + defaults per category and the forced-halt
  behaviour for PROTOCOL_VIOLATION/UNKNOWN.
The reference client (java-questdb-client) accepts only
[http, https, tcp, tcps, ws, wss, udp] and rejects qwpws/qwpwss, so the
"long-form alias" claims would break any connect string a reader copies.
Standardize on ws/wss across connect-string, rust, and c-and-cpp docs
(C/C++ API symbol names like line_sender_qwpws_* are left intact).

Also ship the wire-protocols overview as a clean page: remove the
"Page in draft" admonition and both TODO stubs, fill Versioning with the
actual X-QWP-Max-Version / min(clientMax, serverMax) negotiation, and fix
stale "Protocols section" naming. Confirmed wss defaults to 9000 (not 443)
against the parser; the explicit call-out stays.
Add a deeper, multi-agent review pass to the docs review-pr skill,
modeled on the questdb repo's adversarial reviewer, in both harness
variants (.pi uses subagent, .claude uses the Agent tool).

- Add review levels (0-2) and a gh pr-based target step that checks out
  a PR or falls back to the current branch.
- Add a change surface map (inbound/outbound links, sidebar neighbors,
  shared schema/vocabulary, reading paths) as input for the agents.
- Add six review agents: structured agents for correctness, placement,
  information flow, and cross-page navigation/coherence (human + LLM),
  plus two fresh-context adversarial agents (skeptical reader and LLM
  one-shot consumer) that run without checklists to escape anchoring.
- Add a verification pass that moves false positives to a Downgraded
  section before reporting.
@bluestreak01

Copy link
Copy Markdown
Member Author

Review: Connect section, connect-string reference, QWP specs

Reviewed at level 2 (flagship restructure: new top-level section + 25 page moves + marquee reference pages). Build run against the PR branch; findings verified directly (build, grep, link/anchor resolution, source cross-checks).

Verdict: request-changes

The content is genuinely strong — the QWP wire specs and the connect-string reference are some of the best dual-audience material in the repo, the build is clean across 365 pages, and the cross-client schema drift flagged earlier has been properly fixed. But the PR ships with a missing-redirects regression on 25+ indexed pages, an internal self-contradiction in the flagship reference page, several unaddressed review items, unverified performance claims, and non-docs scope creep. These block merge.


Blocking issues

Cross-cutting

1. [Critical] 25+ moved pages have no redirects in this repo's static/_redirects.
The PR moves query/rest-api, the entire query/pgwire/* tree, ingestion/ilp/*, ingestion/clients/*, ingestion/message-brokers/*, etc. to /connect/.... These are canonical, indexed, heavily-inbound URLs (in-repo alone: rest-api ×22, pgwire/overview ×22, ilp/overview ×31; plus external SEO). This repo already owns doc-move redirects in static/_redirects (the window-functions precedent), but the PR adds zero entries there. The body defers to questdb.io#2917, but bypassing the in-repo mechanism means the standalone docs deployment 404s every old URL and the two redirect sources can drift.
Fix: add 301s to static/_redirects for all 25 moves (mirror REDIRECTS-connect-qwp.md), or confirm the parent redirects ship in the same release and intentionally own this — then delete the scratch REDIRECTS-connect-qwp.md.

2. [Major] Scope creep — non-docs artifacts bundled into a docs-content PR.

  • .pi/skills/review-pr/SKILL.md — modified with an unrelated "adversarial review agents" change.
  • .claude/skills/review-client/SKILL.md, .claude/skills/review-pr/SKILL.md — new tooling files.
  • ONBOARDING.md — internal handoff doc referencing private repos (questdb-enterprise/...) and "ping in your team channel."
  • REDIRECTS-connect-qwp.md — scratch file.

None are documentation content. Split into separate PR(s); remove ONBOARDING.md / REDIRECTS-connect-qwp.md before merge.

3. [Major] PR description is stale and understates scope. It calls the wire-protocol pages "stubs" and lists client-failover and store-and-forward concepts as out of scope — but the PR ships a ~1,200-line ingress spec, a full egress spec, and complete high-availability/client-failover/* and store-and-forward/* concept+config+tuning pages. Update the description so reviewers and the changelog reflect what's landing.

documentation/connect/clients/connect-string.md

4. [Major] Self-contradiction on builder error-policy support.

  • ~L670 (Error handling): "…the connect-string parser does not recognise them and there is no builder equivalent."
  • ~L760 (Key index footnote): "…the Java connect-string parser does not yet recognise these — they are currently wired only via the fluent builder API."

Mutually exclusive. Pick one truth and make the prose, the precedence list (items 1–2), and the footnote agree.

5. [Major] Authentication section has an OIDC one-shot gap (previously raised, still open). It documents token and states mTLS is unsupported, but never says how an app acquires an OIDC token, what happens on expiry, or that there's no auto-refresh — and doesn't link /docs/security/oidc/ (the ingress wire spec does). For the canonical knob doc, an LLM can't one-shot Enterprise token auth from it.

6. [Major] request_durable_ack=on lacks a client-support caveat (previously raised, open). The Recipes table (L180), Durable ACK section (L604), and rust.md:529/799 present it as usable, while go.md documents that the Go client rejects it at construction. Verify the Rust client and add a "client support varies" note here and in rust.md, mirroring the tls_roots treatment.

documentation/connect/overview.md

7. [Major] Unverified / implausible performance claims (L52–57). "sustained 800 MiB/s ingress, up to 2.5 GiB/s egress on a single connection" and especially "Sub-200 ns offload latency" read as marketing numbers; 200 ns for a store-and-forward disk offload isn't credible without qualification (what's measured, on what hardware/payload). Verify against benchmarks or qualify/soften.

documentation/concepts/delivery-semantics.md

8. [Major] Canonical DEDUP recipe uses an off-convention schema. The DDL and example use qty (L95, L107) and instrument ETH-USD, while the demo trades table and every client page (go/java/rust) now use amount and EURUSD. This is the page the connect-string reference and _sf-dedup-warning partial point to for the exactly-once recipe, so the drift hurts coherence exactly where it matters. Fix: rename qtyamount and use EURUSD.


Non-blocking

  • [Minor] connect-string.md:672 — "see Error handling" links to its own section. Drop the link.
  • [Minor] Link text "Ingestion overview" now points to a page titled "Connect to QuestDB" in connect/agents.md (177, 239), query/overview.md:61, getting-started/enterprise-quick-start.md:576, connect/compatibility/ilp/advanced-settings.md:29. Update text to "Connect overview."
  • [Minor] _sf-dedup-warning.partial.mdx uses :::caution while connect-string.md/delivery-semantics.md use :::warning for the same content. Standardize.
  • [Nit] connect-string.md size-suffix section omits auto_flush_bytes/max_datagram_size, both documented as accepting suffixes.
  • [Nit] Verify the "wss does not default to 443; both ws and wss use 9000" claim — correct-but-surprising, worth a product confirmation.

What works (reinforce these)

  • Clean production build across 365 pages despite a 25-page move + new top-level section — onBrokenLinks/onBrokenAnchors are throw, so every internal link/anchor resolves (incl. deep #protocol-limits, #version-negotiation, #server_info-0x18 refs).
  • The QWP wire specs are exemplary implementer docs: byte-layout tables, worked hex examples, reference-impl commit pins, and high-value guardrails (ingress↔egress DATE asymmetry warnings, the "asymmetric framing → close 1006" pitfall, pipeline-don't-lockstep guidance).
  • Sidebar placement is sound: all new pages wired into sidebars.js at sensible depth; Connect flows Overview → Client Libraries (connect-string first) → Agents → Compatibility → Wire Protocols.
  • delivery-semantics.md is a clean canonical at-least-once/exactly-once explainer (aside from the qty slip) with correct cross-links.
  • Good partial reuse (_qwp.message-header, _sf-dedup-warning) keeps duplicated content in sync.
  • Earlier findings genuinely fixed: amount now DOUBLE everywhere, symsymbol, order book unified on book, FX unified on EURUSD, and go.md message_sequence now carries the reset-on-reconnect / not-a-standalone-correlation-key framing.

Downgraded (raised during analysis, dismissed on verification)

9 findings verified, 4 dropped as false positives:

  • "agents.md / wire-spec anchors are broken." — Build passes in throw mode and target headings exist.
  • "Cross-client schema drift (amount/sym/order-book/EUR-USD)." — Verified fixed across go/java/rust in later commits.
  • "go.md message_sequence contradicts rust.md." — Verified go.md:810 now mirrors the Rust framing.
  • "http:: examples inside a QWP-only reference." — Already switched to ws::; none remain.

🤖 Generated with adversarial-review pass (level 2).

mtopolnik and others added 23 commits June 18, 2026 10:52
The .NET client no longer accepts the `auth` key (a pre-built
Authorization header value); credentials are supplied as
`username`/`password` or `token`. Drop `auth` from the egress query
client's Auth key table and update the mutual-exclusivity note to
`username`/`password` versus `token`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restructures java.md around QuestDB.connect / Query / Completion / pooled
senders, with the existing Sender and QwpQueryClient sections retained as
low-level primitives. Switches connect-string examples to ws::/wss:: to
match the page's stated QWP focus.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bring the Java client page in line with the current QWP-only facade
(client commit 84da57d) and the single-version protocol (PR #39), and
make it readable for someone building against the public API.

Accuracy:
- The facade takes one ws/wss connect string and uses it verbatim for
  both the ingress sender and the egress query client; each side reads
  the keys it owns. Drop the old http/https schema-translation model
  and references to the removed `auth=` key.
- Fix wrong reference values: close_flush_timeout_millis defaults to
  60s (not 5s), and a Query.submit() acquire timeout throws
  QueryException, not LineSenderException.
- Remove the stale "ingress pins QWP v1" claim and the "v1" fallback in
  the failover example; the protocol is now a single negotiated
  version.
- State that ingestion only writes to the primary (replicas reject the
  write upgrade), so failing over to another host needs that host to be
  promoted to primary.

Flushing and store-and-forward:
- Describe flush() as a hand-off to the always-on async send engine (in
  RAM by default, memory-mapped files when sf_dir is set), not a server
  ack. Cover memory vs store-and-forward mode, memory-grade durability
  (fsync modes are rejected), and the close-time drain.
- Explain that the pool assigns each sender its own slot directory, the
  exclusive lock that keeps a live sender's data safe, restart
  recovery, and when to use a separate vs shared sf_dir (with
  drain_orphans).

Readability:
- De-jargonize the connection pool, Query builder, Completion, and
  failover sections (slot, reap, terminal, decorator, worker, "block
  until terminal" -> plain behavior).
- Standardize directional wording on ingress/egress and give the
  failover section a friendlier tone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The QWP client config in the Java page was accurate on every documented
default but missed three real connect-string options. Add them so the page
matches the client registry:

- compression: note the auto value (compress only when the server offers
  zstd), alongside the existing raw/zstd.
- compression_level: state the default (1) and accepted range (1-22,
  clamped server-side to 1-9).
- client_id: add a configuration-reference row for the egress label sent
  as the X-QWP-Client-Id header, matching the C/C++ page wording.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite the Rust client page around the v7 `QuestDb` pool API:
- store-and-forward column/row senders: flush() + optional wait(ack, timeout)
- db-level synchronous DataFrame/Arrow ingestion (db.flush_arrow_batch /
  db.flush_polars_dataframe)
- query -> polars (fetch_all_polars / iter_polars / next_polars), DDL/DML,
  flow control (byte credits), cancellation, zstd compression
- automatic failover/HA: multi-endpoint, reconnect tuning, durable replay
- rewritten concurrency section (pool is Send+Sync; borrows are !Send,
  returned to the pool on Drop; fail-fast at pool_max)
- quick start; wait() does-not-guarantee-visibility caveat

Also add the C/C++ pooled API draft page + sidebar entry, the API-reference
generator scripts, and fix a broken connect-string anchor
(rust#flushing -> #sending-data-column-major).
`QuestDb::connect` opens no connection: it validates the connect string and
starts the pool, and the first borrow opens the connection (where unreachable/
TLS/auth errors surface). Fix the docs that wrongly claimed eager pre-warming:

- pool_size: "warm minimum the reaper keeps; opened lazily on first borrow,
  not at connect()" (was "opened eagerly at connect()")
- add initial_connect_retry row (off=fail fast, on=sync retry, async=background)
- Connecting: add a lazy-connect note (errors surface at first borrow)
- Concurrency: drop the misleading "pre-warm" wording
Add a normative cross-client behaviour spec for QWP clients (startup,
connection, failover, store-and-forward), placed under Wire Protocols
alongside the QWP ingress/egress specs. Derived from the Java reference
client; the behaviour/config tables are the contract all language clients
are aligned to.

- frontmatter + "client implementers" audience admonition + scope
- reframed from a Java user doc into a normative spec (Java = reference impl)
- fixed broken links: dropped the ./qwp-client-ergonomics-issues.md
  references and corrected #sharp-edges anchors to #known-sharp-edges
- Implementation appendix marked non-normative (Java reference internals)
- sidebar: Connect > Wire Protocols > QWP Client Behaviour
…erence

Add a Connection pooling section (QuestDBClient handle: sender + query pools, BorrowSender/NewQuery/ExecuteSqlAsync, separate ingress/egress configs, pool tuning table); document connect-string keys present in the client but previously undocumented (connect_timeout, max_name_len, sf_* sizing, sf_durability, max_background_drainers, durable_ack_keepalive_interval_millis, ping_timeout, inbox capacities); widen compression_level to 1-22 (server clamps to 9); and fix the close_flush_timeout_millis default (60000, was mis-stated as 5000).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ery contradiction

Pre-create the book table with explicit DDL so the SELECT read-back on the
ts column works (auto-created tables name the designated timestamp
`timestamp`), and document the auto-create naming rule. Reword the
At/AtNow/Flush caution so it no longer claims a non-nil return is only ever
a local error, matching the store-and-forward and Ingestion errors sections.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix correctness and usability gaps flagged in the level-3 review, all
verified against the qwip_go source:

- m4: distinguish auto_flush=off (disables all triggers) from
  WithAutoFlushDisabled() (leaves the 8 MiB byte trigger live on QWP).
- m6: role mismatch surfaces from Connect (the query pool prewarms
  query_pool_min at construction), or first BorrowQuery under lazy_connect.
- m8: scope the At/AtNano conflict to "within a single flush"; cross-flush
  mismatches become async server rejections.
- m3: document error_inbox_capacity / connection_listener_inbox_capacity
  (default 256, range 16-1048576, facade-forwarded) in the config table
  and prose, with the standalone option names.
- m7: connection-event inbox is drop-oldest for all payloads; note
  LastTerminalError() as the reliable terminal-state backstop.
- m9: make the AtNano and Decimal snippets define qs inline.
- m11: add UUID-reassembly and decimal-scaling decode snippets.
- nit: derive hi/lo in the QWP-only column-types snippet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…al guidance

Refresh the C/C++ pooled API draft (c-api-reference.md) against the
current jh_conn_pool_refactor branch and grow it from a surface tour
into a usable guide.

API corrections (the draft predated recent renames):
- borrow_column_sender/column_sender -> borrow_sf_column_sender/
  sf_column_sender; column_sender_sync/ack_level -> sf_column_sender_wait/
  qwpws_ack_level_*
- drop the stale "no new_buffer()" note: row_sender_new_buffer /
  borrowed_row_sender::new_buffer() now exist and the examples use them
- return-vs-drop guidance rewritten for the new contract: the return
  path retires terminally-latched conns itself; drop_on_return is only
  for in-doubt frames (must_close inspection is gone by design)

New guidance sections:
- Which borrow? decision table; pool sizing (borrow-at-cap fails fast,
  no blocking acquire); Authentication and TLS summary
- Arrow ingestion via the C Data Interface (C + C++ fragments)
- error-class table (failover_retry/server_rejection/... -> borrow
  state + action); consolidated durability & backpressure story
- null-validity examples, full column-setter table, concurrency
  (one borrow per worker, runnable 4-thread example), orderly close,
  and a production-shape example (wss + token + multi-host + sf_dir)
- GO-G1: add a pre-release banner (the pooled facade + QWP query API are not
  yet in a tagged v4 release, so `go get .../v4` alone won't resolve them)
- GO-1: fix the UuidColumn example — pass uint64 halves (int64 wouldn't compile)
- GO-2: pre-create `trades TIMESTAMP(ts)` in the quick start so `ts` is the
  canonical designated-timestamp name; `SELECT ts ... FROM trades` no longer
  errors with "Invalid column: ts"
- GO-3: keep `side` a SYMBOL to match the DDL; move the CharColumn demo to a
  genuine CHAR column
- GO-4: add a FlushAndGetSequence/AwaitAckedFsn ack barrier before the
  read-back in the full example, so it can't race the async commit
- GO-5: drop the empty `qwp-pool` RemoteRepoExample (inline quick start covers it)
- GO-6/GO-7: reframe the `qwp-ingest`/`qwp-query` prose to match what the
  rendered standalone examples actually show
- GO-8: repoint the timestamp-naming rule to the designated-timestamp concept
  page instead of the legacy ILP overview

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- M1: Quick start now registers WithQuestDBErrorHandler and waits for the
  server ack (FlushAndGetSequence + AwaitAckedFsn) before the read-back, so
  it no longer models the async-error and read-your-writes anti-patterns;
  add the async-publish/commit-race hazard to the "Read before building" list.
- M2: surface the DEDUP-or-duplicate warning in the Ingestion failover
  section — the rule applies to every reconnecting/multi-host connection,
  not only store-and-forward.
- M3: make the pre-release install consistent and concrete — pin to the
  qwip_go branch (go get ...v4@qwip_go) in both the banner and Quick start.
- M4: rewrite the Full example on the canonical trades schema (symbol, side,
  price, amount); leave `book` to mean only the array table. Add DEDUP since
  the example reconnects over multi-host + sf_dir.
- M5: finalize the QWP-only column-types example with AtNow, not AtNano —
  trades is a microsecond table, so AtNano would conflict with its resolution.

Build verified green (onBrokenLinks/onBrokenAnchors: throw); both full
programs pass gofmt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Curated minor pass on the Go QWP client page — the correctness/one-shot
breakers plus cheap wins:

- m6: bind-parameter errors surface from the first Batches() yield (Query
  returns only a cursor), not from Query.
- m7: name the per-category on_*_error connect-string keys instead of the glob.
- m8: soften "never as a Flush error" — a latched PolicyHalt rejection can
  resurface on a later producer call.
- m9: mark the config table a curated subset; name the omitted data-loss-timing
  keys (close_flush_timeout_millis, sf_append_deadline_millis, auto_flush=off).
- m11: document the Close ctx asymmetry (db/sender Close take ctx; query/cursor
  Close do not).
- m13: add the read-your-writes / replica-lag caveat to durable ack.
- m14: reframe the pgwire/go.md inbound link (QWP, not ILP ingestion).
- m16: mark the three LineSender constructors as alternatives (paste-whole
  compile trap).
- nit: add "WebSocket" to the page description for search parity.

Build verified green (onBrokenLinks/onBrokenAnchors: throw).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…matches

The Go client now retries transport outages indefinitely:
reconnect_max_duration_millis bounds only the blocking sync initial
connect, and the budget-exhausted terminal event kind is gone. Update
the reconnect key tables, connection-event kinds, and the
ingress-reconnect section accordingly; document the new
WithQuestDBDrainerListener facade option and query_close_timeout_ms
key.

Also fix documented behavior that diverged from the code: multi-address
WithAddress usage (single comma-separated string), Exec never returns
QwpFailoverReset, single-addr failover retries the same host, GEOHASH
has a value accessor, Query streams during iteration rather than
blocking, producer backpressure applies in memory mode too, the
fixed-width decimal columns are the QwpSender-only ones, and the
failover example now genuinely accumulates and clears on reset.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants