Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
23a9824
feat(net): add application-level TCP connect timeout
bluestreak01 Jun 28, 2026
7dfedfe
test(net): make black-hole connect-timeout test CI-routing-robust
bluestreak01 Jun 28, 2026
9f5826c
ci(native): fix linux-x86-64 rebuild on manylinux_2_28
bluestreak01 Jun 28, 2026
5480282
Rebuild CXX libraries
Jun 28, 2026
2d1d997
feat(facade): expose ingest errorHandler/connectionListener on QuestDB
bluestreak01 Jun 28, 2026
00d3dcd
feat(facade): add write-only mode so the handle starts without a server
bluestreak01 Jun 28, 2026
783a508
test(facade): server-down -> start -> write -> server-up -> reader co…
bluestreak01 Jun 28, 2026
2e22da9
ci: build native .so/.dll on test runners instead of committing them
bluestreak01 Jun 28, 2026
d7f812b
ci: build macOS .dylib on test runners too; drop committed binaries
bluestreak01 Jun 28, 2026
85b50c3
ci: drop mac-x64 test leg (Intel macOS hardware retired)
bluestreak01 Jun 28, 2026
aee61cc
ci(gh-actions): build libquestdb.so before JDK 8 tests
bluestreak01 Jun 28, 2026
b7ac84d
fix(native): pin clock_gettime to GLIBC_2.2.5 to keep glibc floor low
bluestreak01 Jun 28, 2026
97d39c1
docs(design): add QWP client startup/failover behavior and ergonomics…
bluestreak01 Jun 28, 2026
a494675
ci: build native lib in the Coverage job too
bluestreak01 Jun 29, 2026
2cef2df
feat(facade): single cluster config for the QuestDB handle
bluestreak01 Jun 29, 2026
56d0eb6
feat(facade): writeOnly owns non-blocking startup; add write_only con…
bluestreak01 Jun 29, 2026
0b8c7f9
test(facade): prove a resilient (non-write-only) handle keeps reads e…
bluestreak01 Jun 29, 2026
7491d95
feat(facade): replace writeOnly with lazy_connect (read-capable toler…
bluestreak01 Jun 29, 2026
9fd80d2
fix(qwp): report connect_timeout, not auth_timeout, on a connect-phas…
bluestreak01 Jun 29, 2026
98fff9a
refactor(housekeeper): drop dead queryPool null-guard left by write-o…
bluestreak01 Jun 29, 2026
914c9b5
fix(config): list on/off in getBool's expected-values error message
bluestreak01 Jun 29, 2026
1245c17
Make query egress symmetric with sender ingest
bluestreak01 Jun 29, 2026
65e4912
fix(test): use Java 8 try-with-resources in QuestDBServerRecoveryTest
bluestreak01 Jun 29, 2026
f39e846
Fix M1: stale pooled handle can corrupt the pool under double-close/u…
bluestreak01 Jun 29, 2026
e30a59c
Fix lost query-worker dispatch under single-flight reuse
bluestreak01 Jun 29, 2026
f64567e
Assert lease wraps the same pooled QueryImpl
bluestreak01 Jun 30, 2026
bcb1e7a
Make watchdog cancel re-check lease generation under the pool lock
bluestreak01 Jun 30, 2026
da4bd1d
Bound the TLS handshake and drive it off the event loop
bluestreak01 Jun 30, 2026
e34fc1c
Use a fixed deadline in the native connect timeout
bluestreak01 Jun 30, 2026
09c75b3
Fix stale macOS comment in the test pipeline
bluestreak01 Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ defaults:
jobs:
# JDK 8 is the source of truth: the client ships as a Java 8 artifact
# (io.questdb:questdb-client) and is released from JDK 8, so on JDK 8 it must
# compile, the full test suite must pass against the committed native
# libraries, and the javadoc jar must build (-P javadoc attaches it at the
# package phase). The committed native .so/.dylib/.dll are enough -- the only
# git submodule (zstd) is needed solely for C++ native rebuilds, not here.
# compile, the full test suite must pass, and the javadoc jar must build
# (-P javadoc attaches it at the package phase). The native libraries are no
# longer committed, so this job compiles libquestdb.so from source (hence the
# zstd submodule + cmake/nasm/build-essential toolchain) before the tests run.
build-jdk8:
name: Build, test & javadoc (JDK 8)
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Check out
uses: actions/checkout@v4
with:
# zstd is required to compile the native library.
submodules: recursive

- name: Set up JDK 8
uses: actions/setup-java@v4
Expand All @@ -36,6 +39,23 @@ jobs:
java-version: "8"
cache: maven

- name: Install native build toolchain
run: sudo apt-get update && sudo apt-get install -y cmake nasm build-essential

- name: Build native libquestdb.so
# JAVA_HOME points at the JDK 8 above, so the lib is compiled against the
# Java 8 JNI headers -- the artifact's floor. Copy it into src resources
# (not target/) so it survives the `mvn clean` in the next step and gets
# packaged + loaded via the production bin/<platform> path.
run: |
cd core
cmake -DCMAKE_BUILD_TYPE=Release -B cmake-build-release -S.
cmake --build cmake-build-release --config Release
test -f target/classes/io/questdb/client/bin-local/libquestdb.so
mkdir -p src/main/resources/io/questdb/client/bin/linux-x86-64
cp target/classes/io/questdb/client/bin-local/libquestdb.so \
src/main/resources/io/questdb/client/bin/linux-x86-64/libquestdb.so

- name: Compile, test, and build javadoc
run: mvn -B -ntp -P javadoc clean install

Expand Down
55 changes: 18 additions & 37 deletions .github/workflows/rebuild_native_libs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,57 +68,38 @@ jobs:
key: nativelibs-osx-${{ github.sha }}
build-all-linux-x86-64:
runs-on: ubuntu-latest
# manylinux2014 is a container with new-ish compilers and tools, but old glibc - 2.17
# 2.17 is old enough to be compatible with most Linux distributions out there
# manylinux_2_28 (glibc 2.28) replaces the previous manylinux2014 (glibc
# 2.17) container: GitHub Actions now forces actions (checkout, cache) onto
# Node 24, whose binary requires glibc >= 2.27, so it can no longer run
# inside the glibc-2.17 image (the old Node-20-glibc-217 override hack only
# patched /__e/node20, not /__e/node24). 2.28 still runs stock Node 24 and
# matches the linux-aarch64 job, which already ships glibc-2.28 binaries.
#
# NOTE: the build container's glibc (2.28) does NOT dictate the artifact's
# runtime glibc floor. clock_gettime is pinned back to GLIBC_2.2.5 via
# src/main/c/share/glibc_compat.h so the linux-x86-64 .so keeps loading on
# glibc 2.14+ (its floor is memcpy@GLIBC_2.14), unchanged from before the
# container move. If you add a symbol with a higher version node here, the
# floor will rise -- check with: objdump -T libquestdb.so | grep GLIBC_.
container:
image: quay.io/pypa/manylinux2014_x86_64
volumes:
- /node20217:/node20217
- /node20217:/__e/node20
image: quay.io/pypa/manylinux_2_28_x86_64
steps:
- name: Install tools, most are needed to build nasm
run: |
ldd --version
yum update -y
yum install 'perl(Env)' perl-Font-TTF perl-Sort-Versions gcc wget perf asciidoc xmlto ghostscript adobe-source-sans-pro-fonts adobe-source-code-pro-fonts rpm-build zstd curl -y
- name: Build nasm
# we need nasm 2.14+ due to this bug https://bugzilla.nasm.us/show_bug.cgi?id=3392205
# manylinux2014 distribution includes nasm 2.10
# the nasm project itself provides RPMs, but they built against a newer glibc and other dependencies too
# thus we take src.rpm from nasm project and rebuild it in the manylinux2014 container
# this way we get a nasm binary that is compatible with the manylinux2014 environment
run: |
wget https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/linux/nasm-2.16.03-0.fc39.src.rpm
rpmbuild --rebuild ./nasm-2.16.03-0.fc39.src.rpm
rpm -i ~/rpmbuild/RPMS/x86_64/nasm-2.16.03-0.el7.x86_64.rpm
- name: Install Node.js 20 glibc2.17
# A hack to override default nodejs 20 to a build compatible with older glibc.
# Inspired by https://github.com/pytorch/test-infra/pull/5959 If it's good for pytorch, it's good for us too! :)
# Q: Why do we need this hack at all? A: Because many github actions, include action/checkout@v4, depend on nodejs 20.
# GitHub Actions runner provides a build of nodejs 20 that requires a newer glibc than manylinux2014 has.
# Thus we download a build of nodejs 20 that is compatible with manylinux2014 and override the default one.
run: |
curl -LO https://unofficial-builds.nodejs.org/download/release/v20.9.0/node-v20.9.0-linux-x64-glibc-217.tar.xz
tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217
ldd /__e/node20/bin/node
- uses: actions/checkout@v4
with:
submodules: true
- name: Install up-to-date CMake
- name: Install tooling
run: |
wget -nv https://github.com/Kitware/CMake/releases/download/v3.29.2/cmake-3.29.2-linux-x86_64.tar.gz
tar -zxf cmake-3.29.2-linux-x86_64.tar.gz
echo "PATH=`pwd`/cmake-3.29.2-linux-x86_64/bin/:$PATH" >> "$GITHUB_ENV"
yum update -y
yum install wget nasm zstd -y
- name: Install GraalVM JDK 25 (for jni.h)
run: |
wget -nv -O graalvm.tar.gz https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz
wget -v --timeout=180 -O graalvm.tar.gz https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz
mkdir graalvm
tar xfz graalvm.tar.gz -C graalvm --strip-components=1
echo "JAVA_HOME=`pwd`/graalvm" >> "$GITHUB_ENV"
- name: Generate Makefiles
run: |
cd ./core
# git submodule update --init
cmake -DCMAKE_BUILD_TYPE=Release -B cmake-build-release -S.
- name: Build linux-x86-64 CXX Library
run: |
Expand Down
92 changes: 92 additions & 0 deletions ci/build_native.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Builds the native libquestdb shared library on the test runner itself.
#
# The Linux (.so) and Windows (.dll) binaries are no longer committed to the
# repository -- they are produced and committed only by the release
# "Build and Push Release CXX Libraries" GitHub Action. So the test CI has to
# compile them locally before running the tests.
#
# All three platforms are built on their own native runner: Linux (.so),
# Windows (.dll) and macOS (.dylib). None of these binaries are committed.
#
# CMake writes the artifact to:
# core/target/classes/io/questdb/client/bin-local/libquestdb.<ext>
# which io.questdb.client.std.Os loads first (the "dev CXX lib" path), so the
# client tests pick it up directly. We additionally copy it into
# core/src/main/resources/io/questdb/client/bin/<platform>/libquestdb.<ext>
# so that `mvn install` packages it into the client jar exactly like the
# committed binary used to be -- this is what the downstream QuestDB OSS server
# tests load from the installed jar.
#
# JAVA_HOME (set to GraalVM JDK 25 by setup.yaml) provides jni.h / jni_md.h:
# - Linux: $JAVA_HOME/include + $JAVA_HOME/include/linux
# - macOS: $JAVA_HOME/include + $JAVA_HOME/include/darwin
# - Windows: %JAVA_HOME%\include + %JAVA_HOME%\include\win32
steps:
- bash: |
set -eux
git submodule update --init --recursive core/src/main/c/share/zstd
displayName: "Init zstd submodule"

- bash: |
set -eux
sudo apt-get update
sudo apt-get install -y cmake nasm build-essential
cd core
cmake -DCMAKE_BUILD_TYPE=Release -B cmake-build-release -S.
cmake --build cmake-build-release --config Release
lib="target/classes/io/questdb/client/bin-local/libquestdb.so"
test -f "$lib"
# Fail fast if the linker left an unresolved dependency in the .so.
if ldd "$lib" | grep -i "not found"; then
echo "libquestdb.so has unresolved dependencies"
exit 1
fi
mkdir -p src/main/resources/io/questdb/client/bin/linux-x86-64
cp "$lib" src/main/resources/io/questdb/client/bin/linux-x86-64/libquestdb.so
displayName: "Build native libquestdb.so (Linux x86-64)"
condition: eq(variables['Agent.OS'], 'Linux')

- bash: |
set -eux
command -v cmake >/dev/null 2>&1 || brew install cmake
command -v nasm >/dev/null 2>&1 || brew install nasm
# darwin-aarch64 on Apple silicon agents, darwin-x86-64 on Intel agents.
case "$(uname -m)" in
arm64) platform="darwin-aarch64" ;;
x86_64) platform="darwin-x86-64" ;;
*) echo "unsupported macOS arch: $(uname -m)"; exit 1 ;;
esac
cd core
# Pin the dylib's minimum macOS version so the artifact stays loadable on
# older macOS, matching the release build.
export MACOSX_DEPLOYMENT_TARGET=13.0
cmake -DCMAKE_BUILD_TYPE=Release -B cmake-build-release -S.
cmake --build cmake-build-release --config Release
lib="target/classes/io/questdb/client/bin-local/libquestdb.dylib"
test -f "$lib"
mkdir -p "src/main/resources/io/questdb/client/bin/${platform}"
cp "$lib" "src/main/resources/io/questdb/client/bin/${platform}/libquestdb.dylib"
displayName: "Build native libquestdb.dylib (macOS)"
condition: eq(variables['Agent.OS'], 'Darwin')

- powershell: |
$ErrorActionPreference = "Stop"
# The CMake build is GCC/MinGW based (gcc flags, -static-libgcc/-static-libstdc++),
# so build the Windows DLL with the MinGW-w64 toolchain + NASM, not MSVC.
choco install -y --no-progress nasm mingw
Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
refreshenv
# choco's nasm package does not put nasm on PATH; add it explicitly.
$env:PATH = "C:\Program Files\NASM;" + $env:PATH
gcc --version
mingw32-make --version
nasm --version
cd core
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -B cmake-build-release -S .
cmake --build cmake-build-release --config Release
$lib = "target/classes/io/questdb/client/bin-local/libquestdb.dll"
if (!(Test-Path $lib)) { throw "native build produced no $lib" }
New-Item -ItemType Directory -Force -Path "src/main/resources/io/questdb/client/bin/windows-x86-64" | Out-Null
Copy-Item $lib "src/main/resources/io/questdb/client/bin/windows-x86-64/libquestdb.dll" -Force
displayName: "Build native libquestdb.dll (Windows x86-64)"
condition: eq(variables['Agent.OS'], 'Windows_NT')
14 changes: 10 additions & 4 deletions ci/run_tests_pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ stages:
imageName: "macos-15-arm64"
poolName: "Azure Pipelines"
jdkArch: "arm64"
mac-x64:
imageName: "macos-15"
poolName: "Azure Pipelines"
jdkArch: "x64"
windows-msvc-2022-x64:
imageName: "windows-2022"
poolName: "Azure Pipelines"
Expand All @@ -82,6 +78,13 @@ stages:
maven | "$(Agent.OS)"
path: $(HOME)/.m2/repository
displayName: "Cache Maven repository"
# Compile the native libquestdb shared library on the runner; no
# platform's binary is committed anymore. Must run before the client
# jar is installed so the freshly built lib is packaged into it. The
# template builds the right artifact for the current native agent --
# Linux (.so), Windows (.dll), and macOS (.dylib) alike (see
# build_native.yaml).
- template: build_native.yaml
- bash: |
BRANCH="${SYSTEM_PULLREQUEST_SOURCEBRANCH:-$BUILD_SOURCEBRANCHNAME}"
BRANCH="${BRANCH#refs/heads/}"
Expand Down Expand Up @@ -149,6 +152,9 @@ stages:
maven | "$(Agent.OS)"
path: $(HOME)/.m2/repository
displayName: "Cache Maven repository"
# Native binaries are no longer committed; compile libquestdb.so on the
# runner so the coverage test run can load it (same as BuildAndTest).
- template: build_native.yaml
- task: Maven@3
displayName: "Run tests with coverage"
inputs:
Expand Down
1 change: 1 addition & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set(
src/main/c/share/files.h
src/main/c/share/net.h
src/main/c/share/os.h
src/main/c/share/glibc_compat.h
src/main/c/share/ooo.cpp
src/main/c/share/cpprt_overrides.h
src/main/c/share/cpprt_overrides.cpp
Expand Down
53 changes: 53 additions & 0 deletions core/src/main/c/share/glibc_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*+*****************************************************************************
* ___ _ ____ ____
* / _ \ _ _ ___ ___| |_| _ \| __ )
* | | | | | | |/ _ \/ __| __| | | | _ \
* | |_| | |_| | __/\__ \ |_| |_| | |_) |
* \__\_\\__,_|\___||___/\__|____/|____/
*
* Copyright (c) 2014-2019 Appsicle
* Copyright (c) 2019-2026 QuestDB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/

#ifndef QUESTDB_GLIBC_COMPAT_H
#define QUESTDB_GLIBC_COMPAT_H

// Pin clock_gettime() to its original GLIBC_2.2.5 symbol version.
//
// glibc 2.17 moved clock_gettime() out of librt and into libc, exporting it
// under a NEW version node: clock_gettime@GLIBC_2.17. The release binaries are
// built in a modern toolchain container (CI uses manylinux_2_28 / glibc 2.28),
// so without this pin the linker binds our calls to clock_gettime@GLIBC_2.17.
// That single symbol raises the whole library's glibc floor to 2.17 and makes
// it fail to LOAD on hosts running glibc 2.14-2.16 with:
//
// version `GLIBC_2.17' not found (required by libquestdb.so)
//
// The original clock_gettime@GLIBC_2.2.5 symbol is still exported as a compat
// symbol by librt.so.1 on every glibc since (and by libc after the 2.34 librt
// merge), so forcing the reference back to it keeps the library loadable down
// to the previous floor (glibc 2.14, set by memcpy@GLIBC_2.14) with no change
// in runtime behaviour. librt is already a NEEDED dependency (CMake links rt).
//
// Scope: x86-64 glibc only. aarch64 glibc started at 2.17 and has only ever
// shipped clock_gettime in libc@GLIBC_2.17 -- there is no GLIBC_2.2.5 version
// there, so emitting the pin on aarch64 would fail the link with an undefined
// clock_gettime@GLIBC_2.2.5. The directive is a no-op on macOS/Windows.
#if defined(__linux__) && defined(__GLIBC__) && defined(__x86_64__)
__asm__(".symver clock_gettime,clock_gettime@GLIBC_2.2.5");
#endif

#endif // QUESTDB_GLIBC_COMPAT_H
Loading
Loading