refactor(sqlserver): isolate vendored TDS ATTENTION from standalone agents

This commit is contained in:
Rendegou
2026-10-06 18:57:44 +08:00
committed by GitHub
parent ae86a8c73c
commit c87351e0df
11 changed files with 44 additions and 5 deletions
+2 -2
View File
@@ -8,14 +8,14 @@ export function rustCommand(action, group, mode) {
|| (group !== "workspace" && !Object.hasOwn(rustGroups, group)) || (action === "clippy" && group !== "workspace")) {
throw new Error(`Unknown Rust CI configuration: ${action}/${group}/${mode}`);
}
const capabilityFeatures = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-sqlcipher"];
const capabilityFeatures = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-sqlcipher", "sqlserver-native-attention"];
if (mode === "full") capabilityFeatures.push("system-fonts");
const appFeatures = ["dbx", "dbx-core", "dbx-web"].flatMap((name) => capabilityFeatures.map((feature) => `${name}/${feature}`));
const foundationFeatures = ["dbx-types/mq-admin", "dbx-types/openapi", "dbx-sql/duckdb-sidecar", "dbx-sql/openapi",
"dbx-sql-data/openapi", "dbx-sql-schema/duckdb-sidecar",
"dbx-platform/downloads", "dbx-platform/host-prompts", "dbx-platform/test-support", "dbx-plugin-runtime/default", "dbx-plugin-runtime/test-support"];
const features = group === "foundation" ? foundationFeatures : group === "drivers" ? [
...["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-bundled", "sqlite-sqlcipher", "test-support"].map((feature) => `dbx-drivers/${feature}`),
...["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-bundled", "sqlite-sqlcipher", "sqlserver-native-attention", "test-support"].map((feature) => `dbx-drivers/${feature}`),
"dbx-driver-agent/test-support", "dbx-driver-mysql/test-support", "dbx-driver-redis/test-support",
"dbx-driver-support/test-support",
"dbx-sqlite-worker/runtime", "dbx-types/openapi", "dbx-sql-data/openapi",
+1 -1
View File
@@ -82,7 +82,7 @@ dev: node_modules/.modules.yaml check-tauri-dev-port
dev-fast: node_modules/.modules.yaml check-tauri-dev-port
# os-keyring must stay in sync with src-tauri defaults: without it the keychain
# key is unreadable and the secret-store migration wizard reappears on every launch.
RUST_MIN_STACK=16777216 $(PNPM) dev:tauri -- --no-default-features --features duckdb-sidecar,dynamodb,sqlite-bundled,os-keyring
RUST_MIN_STACK=16777216 $(PNPM) dev:tauri -- --no-default-features --features duckdb-sidecar,dynamodb,sqlite-bundled,os-keyring,sqlserver-native-attention
dev-web: node_modules/.modules.yaml
$(PNPM) dev:web
+2
View File
@@ -5886,6 +5886,8 @@ dependencies = [
[[package]]
name = "tiberius"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1446cb4198848d1562301a3340424b4f425ef79f35ef9ee034769a9dd92c10d"
dependencies = [
"async-trait",
"asynchronous-codec",
-1
View File
@@ -42,7 +42,6 @@ tokio-postgres = { git = "https://github.com/t8y2/tokio-postgres-gaussdb.git", r
postgres-types = { git = "https://github.com/t8y2/tokio-postgres-gaussdb.git", rev = "ac8ad476de59093d33ab9f294531c956e0c6a724" }
postgres-protocol = { git = "https://github.com/t8y2/tokio-postgres-gaussdb.git", rev = "ac8ad476de59093d33ab9f294531c956e0c6a724" }
mysql_async = { git = "https://github.com/t8y2/mysql_async.git", rev = "b615bb0b10b5975182a4aa069cabc3d09021f6ab" }
tiberius = { path = "../../../vendor/tiberius" }
[profile.release]
panic = "abort"
+4
View File
@@ -10,6 +10,10 @@ default = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-sqlcipher", "system
duckdb-sidecar = ["dbx-sql/duckdb-sidecar", "dbx-drivers/duckdb-sidecar"]
dynamodb = ["dbx-drivers/dynamodb"]
mq-admin = ["dep:rumqttc", "dbx-types/mq-admin", "dbx-drivers/mq-admin"]
# SQL Server native TDS ATTENTION on interrupt (SQL Server 2000 batch abort).
# Requires the vendored tiberius patched in by the root workspace; standalone
# agent driver workspaces build dbx-core without it. Desktop enables this.
sqlserver-native-attention = ["dbx-drivers/sqlserver-native-attention"]
sqlite-sqlcipher = ["rusqlite/bundled-sqlcipher-vendored-openssl", "dbx-drivers/sqlite-sqlcipher"]
sqlite-multiple-ciphers = ["dbx-drivers/sqlite-multiple-ciphers"]
# Keeps bundled SQLite for consumers that enable no other sqlite source
@@ -362,6 +362,8 @@ impl Drop for ExecutionGuard {
/// TCP FIN alone need not stop a SQL2000 batch immediately. ATTENTION is
/// best effort, never proof of rollback; callers always discard the connection.
/// The wire call needs the vendored tiberius (dbx-driver-sqlserver feature
/// `native-attention`); standalone crates.io builds no-op inside the client.
async fn send_native_attention(conn: &mut TxnConnection) {
if let TxnConnection::SqlServer { client: Some(client), .. } = conn {
let attention = async { client.lock().await.send_attention().await };
+7
View File
@@ -5,6 +5,13 @@ edition = "2021"
license = "Apache-2.0"
publish = false
[features]
# TDS ATTENTION (tiberius Client::send_attention) exists only in the vendored
# tiberius that the root workspace patches in (vendor/tiberius). Standalone
# agent driver workspaces resolve tiberius from crates.io and must keep this
# off; SqlServerClient::send_attention then degrades to a no-op.
native-attention = []
[dependencies]
dbx-driver-support = { path = "../dbx-driver-support" }
dbx-sql-core = { path = "../dbx-sql-core" }
@@ -91,6 +91,24 @@ impl SqlServerClient {
self.inner.query(query, params).await
}
}
/// Best-effort TDS ATTENTION to interrupt the in-flight batch. SQL Server
/// 2000 keeps executing a batch after TCP FIN, so desktop builds (feature
/// `native-attention`, vendored tiberius) signal the server over the wire
/// before the connection is discarded. ATTENTION is never proof of
/// rollback: every caller discards the connection right after.
#[cfg(feature = "native-attention")]
pub async fn send_attention(&mut self) -> tiberius::Result<()> {
self.inner.send_attention().await
}
/// No-op fallback for builds whose tiberius comes from crates.io
/// (standalone agent driver workspaces), where the wire call above does
/// not exist. Connection discard still aborts the session.
#[cfg(not(feature = "native-attention"))]
pub async fn send_attention(&mut self) -> tiberius::Result<()> {
Ok(())
}
}
impl Deref for SqlServerClient {
+2
View File
@@ -10,6 +10,8 @@ default = []
duckdb-sidecar = []
dynamodb = ["dep:aws-sdk-dynamodb"]
mq-admin = ["dbx-types/mq-admin"]
# Desktop/native SQL Server batch interruption; see dbx-driver-sqlserver.
sqlserver-native-attention = ["dbx-driver-sqlserver/native-attention"]
sqlite-bundled = ["rusqlite/bundled"]
sqlite-sqlcipher = ["rusqlite/bundled-sqlcipher-vendored-openssl"]
sqlite-multiple-ciphers = ["dep:libsqlite3-hotbundle"]
+4
View File
@@ -15,6 +15,10 @@ dynamodb = ["dbx-core/dynamodb"]
mq-admin = ["dbx-core/mq-admin", "dbx-mcp/mq-admin"]
sqlite-sqlcipher = ["dbx-core/sqlite-sqlcipher"]
system-fonts = ["dbx-core/system-fonts"]
# Pass-through so CI feature lanes can compile-check the vendored ATTENTION
# path; the web server never executes manual transactions, so it stays off by
# default here.
sqlserver-native-attention = ["dbx-core/sqlserver-native-attention"]
# Embed the frontend build output (../../dist) into the binary. When enabled
# and DBX_STATIC_DIR is not set, the embedded files are served by default.
# Requires the frontend to have been built before invoking cargo.
+2 -1
View File
@@ -13,10 +13,11 @@ name = "dbx_lib"
crate-type = ["rlib"]
[features]
default = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-multiple-ciphers", "system-fonts", "os-keyring"]
default = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-multiple-ciphers", "system-fonts", "os-keyring", "sqlserver-native-attention"]
custom-protocol = ["tauri/custom-protocol"]
duckdb-sidecar = ["dbx-core/duckdb-sidecar"]
os-keyring = ["dbx-core/os-keyring"]
sqlserver-native-attention = ["dbx-core/sqlserver-native-attention"]
dynamodb = ["dbx-core/dynamodb"]
mq-admin = ["dbx-core/mq-admin"]
sqlite-sqlcipher = ["dbx-core/sqlite-sqlcipher"]