Skip to content

Commit 0f9d88f

Browse files
glasstigerclaude
andcommitted
Fix stale self-sufficient-frame comments
Several comments predated file-mode delta encoding and claimed every cursor frame is self-sufficient with a "symbol-dict delta from id 0". That is now only the fallback: in delta mode (memory mode, and file mode when the persisted dictionary opened) frames carry monotonic deltas that are NOT self-sufficient, and the fresh server's dictionary is re-established by an I/O-thread catch-up frame before replay. The worst offender was the deltaDictEnabled field doc ("Enabled only in memory-mode ... File-mode keeps full self-sufficient frames"), which directly contradicted the feature. Corrected it plus the two ensureConnected call-site comments, the append-failed-path comment, and the wasRecoveredFromDisk field doc (schema stays self-sufficient per frame; the dictionary does not). No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 4f44fb3 commit 0f9d88f

2 files changed

Lines changed: 20 additions & 17 deletions

File tree

core/src/main/java/io/questdb/client/cutlass/qwp/client/QwpWebSocketSender.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,14 @@ public class QwpWebSocketSender implements Sender {
224224
private boolean deferCommit;
225225
// True when the sender emits incremental (delta) symbol dictionaries: each
226226
// message carries only symbol ids not yet sent on the wire, rather than the
227-
// full dictionary from id 0. Enabled only in memory-mode, where a reconnect
228-
// replays from the in-process ring and the I/O thread re-registers the whole
229-
// dictionary via a catch-up frame before replaying. File-mode store-and-forward
230-
// keeps full self-sufficient frames (recovery/orphan-drain can replay mid-stream
231-
// to a fresh server, where a partial delta would leave gaps). Set in setCursorEngine.
227+
// full dictionary from id 0. Enabled in memory-mode (a reconnect replays from
228+
// the in-process ring) and in file-mode store-and-forward when the per-slot
229+
// persisted dictionary opened. In both, the I/O thread re-registers the whole
230+
// dictionary via a catch-up frame before replaying, so a non-self-sufficient
231+
// delta frame never dangles an id on a fresh server. Falls back to full
232+
// self-sufficient frames only when the persisted dictionary is unavailable in
233+
// file-mode (recovery/orphan-drain would then have nothing to rebuild the
234+
// deltas from). Set in setCursorEngine.
232235
private boolean deltaDictEnabled;
233236
// User-supplied observer for background orphan-slot drainer events.
234237
// Volatile: written by setDrainerListener (any thread, before or after
@@ -3386,18 +3389,18 @@ private void ensureConnected() {
33863389
host, port, client.getServerQwpVersion(), serverMaxBatchSize, effectiveAutoFlushBytes);
33873390
} else {
33883391
// Async mode: I/O thread will drive the connect. Encoder uses
3389-
// its default version (V1). The symbol-dict watermark still gets
3390-
// reset for consistency with the sync path; the post-connect replay
3391-
// path does not need a producer-side reset signal because every
3392-
// cursor frame is self-sufficient.
3392+
// its default version (V1). The per-batch symbol-dict watermark still
3393+
// gets reset for consistency with the sync path; the post-connect
3394+
// replay path needs no producer-side reset signal (see below).
33933395
Endpoint ep = endpoints.get(0);
33943396
LOG.info("Async initial connect deferred to I/O thread [firstHost={}, firstPort={}, endpointCount={}]",
33953397
ep.host, ep.port, endpoints.size());
33963398
}
3397-
// Server starts fresh on each connection, so reset the symbol-dict
3398-
// watermark. Cursor frames are self-sufficient (every frame carries its
3399-
// full inline schema + a symbol-dict delta from id 0), so post-reconnect
3400-
// replay needs no producer-side reset signal.
3399+
// Server starts fresh on each connection, so reset the per-batch
3400+
// symbol-dict watermark. Every frame still carries its full inline schema,
3401+
// and the fresh server's dictionary is re-established either by a full-dict
3402+
// frame (full-dict mode) or by an I/O-thread catch-up frame before replay
3403+
// (delta mode), so post-reconnect replay needs no producer-side reset signal.
34013404
resetSymbolDictStateForNewConnection();
34023405
connectionError.set(null);
34033406

@@ -3784,7 +3787,7 @@ private void sealAndSwapBuffer() {
37843787
// back to it; flushPendingRows aborts its post-enqueue state
37853788
// updates after this throw, so the source rows stay intact and the
37863789
// next batch re-emits the same rows along with the full inline
3787-
// schema and symbol-dict delta from id 0.
3790+
// schema and the symbol-dict delta the batch requires.
37883791
if (toSend.isSending()) {
37893792
toSend.markRecycled();
37903793
} else if (toSend.isSealed()) {

core/src/main/java/io/questdb/client/cutlass/qwp/client/sf/cursor/CursorSendEngine.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ public final class CursorSendEngine implements QuietCloseable {
8484
private final SlotLock slotLock;
8585
// True when the constructor recovered an existing on-disk slot rather
8686
// than starting fresh. Diagnostic accessor for tests and observability;
87-
// cursor frames are self-sufficient (every frame carries full schema +
88-
// full symbol-dict delta), so producer-side schema reset on recovery
89-
// is not required.
87+
// every frame carries its full inline schema, so producer-side schema reset
88+
// on recovery is not required (the symbol dictionary, which delta frames do
89+
// NOT carry in full, is re-registered by an I/O-thread catch-up instead).
9090
private final boolean wasRecoveredFromDisk;
9191
// FSN of the last commit-bearing (non-FLAG_DEFER_COMMIT) frame found in a
9292
// ring recovered from disk, or -1 for fresh/memory rings and recovered

0 commit comments

Comments
 (0)