@malloy-publisher/server 0.9.5 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/api-doc.yaml +17 -5
- package/dist/package_load_worker.mjs +8 -2
- package/dist/server.mjs +324 -41
- package/package.json +1 -1
package/dist/app/api-doc.yaml
CHANGED
|
@@ -5676,8 +5676,9 @@ components:
|
|
|
5676
5676
|
type: string
|
|
5677
5677
|
enum: [disable, no-verify, verify-ca, verify-full]
|
|
5678
5678
|
description:
|
|
5679
|
-
TLS mode for a connection reached through a
|
|
5680
|
-
|
|
5679
|
+
TLS mode for the connection. On a connection reached through a
|
|
5680
|
+
`proxy` (SSH bastion), the driver connects to a local tunnel
|
|
5681
|
+
endpoint, so the cert
|
|
5681
5682
|
hostname can't be checked from the tunnel address alone; use
|
|
5682
5683
|
`verify-full` to check it against the real host. `verify-ca`
|
|
5683
5684
|
validates the server cert chain against the trusted CA bundle (e.g.
|
|
@@ -5694,9 +5695,20 @@ components:
|
|
|
5694
5695
|
superset; it adds the hostname check without narrowing CA trust.
|
|
5695
5696
|
The server defaults it to
|
|
5696
5697
|
`no-verify` when a proxy is set (so a force-SSL target isn't rejected
|
|
5697
|
-
for plaintext) — a server-applied default, not a schema default.
|
|
5698
|
-
|
|
5699
|
-
deployment PGSSLMODE
|
|
5698
|
+
for plaintext) — a server-applied default, not a schema default. On
|
|
5699
|
+
a direct connection the same modes apply against the configured
|
|
5700
|
+
host; when omitted, the deployment PGSSLMODE applies. Ignored when
|
|
5701
|
+
connectionString is set, which carries its own sslmode. Not applied
|
|
5702
|
+
to a DuckLake catalog connection.
|
|
5703
|
+
statementTimeoutMilliseconds:
|
|
5704
|
+
type: integer
|
|
5705
|
+
minimum: 1
|
|
5706
|
+
maximum: 2147483647
|
|
5707
|
+
description:
|
|
5708
|
+
Maximum run time of each statement on the database, in
|
|
5709
|
+
milliseconds. The database cancels a statement that exceeds it.
|
|
5710
|
+
When omitted, the database's own statement_timeout applies. Not
|
|
5711
|
+
applied to a DuckLake catalog connection.
|
|
5700
5712
|
|
|
5701
5713
|
MysqlConnection:
|
|
5702
5714
|
type: object
|
|
@@ -1115,7 +1115,7 @@ function installRecordPath(environmentPath, packageName) {
|
|
|
1115
1115
|
function normalizeModelPath(p) {
|
|
1116
1116
|
return p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
1117
1117
|
}
|
|
1118
|
-
var API_PREFIX = "/api/v0", README_NAME = "README.md", PUBLISHER_CONFIG_NAME = "publisher.config.json", PACKAGE_MANIFEST_NAME = "publisher.json", PACKAGE_INSTALL_RECORDS_DIR = ".install-records", MODEL_FILE_SUFFIX = ".malloy", NOTEBOOK_FILE_SUFFIX = ".malloynb", INDEX_MODEL_NAME = "index.malloy", DEFAULT_QUERY_ROW_LIMIT = 1000, DEFAULT_MAX_QUERY_ROWS = 1e5, DEFAULT_MAX_RESPONSE_BYTES = 50000000, DEFAULT_QUERY_TIMEOUT_MS = 300000, DEFAULT_MAX_CONCURRENT_QUERIES = 32, TEMP_DIR_PATH, PUBLISHER_DATA_DIR = "publisher_data";
|
|
1118
|
+
var API_PREFIX = "/api/v0", README_NAME = "README.md", PUBLISHER_CONFIG_NAME = "publisher.config.json", PACKAGE_MANIFEST_NAME = "publisher.json", PACKAGE_INSTALL_RECORDS_DIR = ".install-records", MODEL_FILE_SUFFIX = ".malloy", NOTEBOOK_FILE_SUFFIX = ".malloynb", INDEX_MODEL_NAME = "index.malloy", DEFAULT_QUERY_ROW_LIMIT = 1000, DEFAULT_MAX_QUERY_ROWS = 1e5, DEFAULT_MAX_RESPONSE_BYTES = 50000000, DEFAULT_QUERY_TIMEOUT_MS = 300000, DEFAULT_MAX_CONCURRENT_QUERIES = 32, DEFAULT_POSTGRES_POOL_MAX = 5, TEMP_DIR_PATH, PUBLISHER_DATA_DIR = "publisher_data";
|
|
1119
1119
|
var init_constants = __esm(() => {
|
|
1120
1120
|
TEMP_DIR_PATH = os.tmpdir();
|
|
1121
1121
|
});
|
|
@@ -13199,7 +13199,7 @@ function toQueryTextProblem(problem) {
|
|
|
13199
13199
|
...problem.at ? { at: { range: problem.at.range } } : {}
|
|
13200
13200
|
};
|
|
13201
13201
|
}
|
|
13202
|
-
var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, RenderTagRefusedError, UnparseableTextError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, ChainedUpstreamMissingError, ChainedShapeNotCarriedError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, WriteVerifyError, InvalidStateTransitionError, ServiceUnavailableError, PackageAdmissionRefusedError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
13202
|
+
var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, RenderTagRefusedError, UnparseableTextError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, ConnectionPoolExhaustedError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, ChainedUpstreamMissingError, ChainedShapeNotCarriedError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, WriteVerifyError, InvalidStateTransitionError, ServiceUnavailableError, PackageAdmissionRefusedError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
13203
13203
|
var init_errors = __esm(() => {
|
|
13204
13204
|
init_constants();
|
|
13205
13205
|
init_logger();
|
|
@@ -13268,6 +13268,12 @@ var init_errors = __esm(() => {
|
|
|
13268
13268
|
this.callerSafe = options?.callerSafe ?? false;
|
|
13269
13269
|
}
|
|
13270
13270
|
};
|
|
13271
|
+
ConnectionPoolExhaustedError = class ConnectionPoolExhaustedError extends ConnectionError {
|
|
13272
|
+
constructor(message) {
|
|
13273
|
+
super(message, { callerSafe: true });
|
|
13274
|
+
this.name = "ConnectionPoolExhaustedError";
|
|
13275
|
+
}
|
|
13276
|
+
};
|
|
13271
13277
|
DestinationNotFoundError = class DestinationNotFoundError extends Error {
|
|
13272
13278
|
constructor(message) {
|
|
13273
13279
|
super(message);
|
package/dist/server.mjs
CHANGED
|
@@ -205143,7 +205143,7 @@ function installRecordPath(environmentPath, packageName) {
|
|
|
205143
205143
|
function normalizeModelPath(p) {
|
|
205144
205144
|
return p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
205145
205145
|
}
|
|
205146
|
-
var API_PREFIX = "/api/v0", README_NAME = "README.md", PUBLISHER_CONFIG_NAME = "publisher.config.json", PACKAGE_MANIFEST_NAME = "publisher.json", PACKAGE_INSTALL_RECORDS_DIR = ".install-records", MODEL_FILE_SUFFIX = ".malloy", NOTEBOOK_FILE_SUFFIX = ".malloynb", INDEX_MODEL_NAME = "index.malloy", DEFAULT_QUERY_ROW_LIMIT = 1000, DEFAULT_MAX_QUERY_ROWS = 1e5, DEFAULT_MAX_RESPONSE_BYTES = 50000000, DEFAULT_QUERY_TIMEOUT_MS = 300000, DEFAULT_MAX_CONCURRENT_QUERIES = 32, TEMP_DIR_PATH, PUBLISHER_DATA_DIR = "publisher_data";
|
|
205146
|
+
var API_PREFIX = "/api/v0", README_NAME = "README.md", PUBLISHER_CONFIG_NAME = "publisher.config.json", PACKAGE_MANIFEST_NAME = "publisher.json", PACKAGE_INSTALL_RECORDS_DIR = ".install-records", MODEL_FILE_SUFFIX = ".malloy", NOTEBOOK_FILE_SUFFIX = ".malloynb", INDEX_MODEL_NAME = "index.malloy", DEFAULT_QUERY_ROW_LIMIT = 1000, DEFAULT_MAX_QUERY_ROWS = 1e5, DEFAULT_MAX_RESPONSE_BYTES = 50000000, DEFAULT_QUERY_TIMEOUT_MS = 300000, DEFAULT_MAX_CONCURRENT_QUERIES = 32, DEFAULT_POSTGRES_POOL_MAX = 5, TEMP_DIR_PATH, PUBLISHER_DATA_DIR = "publisher_data";
|
|
205147
205147
|
var init_constants = __esm(() => {
|
|
205148
205148
|
TEMP_DIR_PATH = os.tmpdir();
|
|
205149
205149
|
});
|
|
@@ -205300,7 +205300,7 @@ function toQueryTextProblem(problem) {
|
|
|
205300
205300
|
...problem.at ? { at: { range: problem.at.range } } : {}
|
|
205301
205301
|
};
|
|
205302
205302
|
}
|
|
205303
|
-
var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, RenderTagRefusedError, UnparseableTextError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, ChainedUpstreamMissingError, ChainedShapeNotCarriedError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, WriteVerifyError, InvalidStateTransitionError, ServiceUnavailableError, PackageAdmissionRefusedError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
205303
|
+
var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, RenderTagRefusedError, UnparseableTextError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, ConnectionPoolExhaustedError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, ChainedUpstreamMissingError, ChainedShapeNotCarriedError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, WriteVerifyError, InvalidStateTransitionError, ServiceUnavailableError, PackageAdmissionRefusedError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
205304
205304
|
var init_errors = __esm(() => {
|
|
205305
205305
|
init_constants();
|
|
205306
205306
|
init_logger();
|
|
@@ -205369,6 +205369,12 @@ var init_errors = __esm(() => {
|
|
|
205369
205369
|
this.callerSafe = options?.callerSafe ?? false;
|
|
205370
205370
|
}
|
|
205371
205371
|
};
|
|
205372
|
+
ConnectionPoolExhaustedError = class ConnectionPoolExhaustedError extends ConnectionError {
|
|
205373
|
+
constructor(message) {
|
|
205374
|
+
super(message, { callerSafe: true });
|
|
205375
|
+
this.name = "ConnectionPoolExhaustedError";
|
|
205376
|
+
}
|
|
205377
|
+
};
|
|
205372
205378
|
DestinationNotFoundError = class DestinationNotFoundError extends Error {
|
|
205373
205379
|
constructor(message) {
|
|
205374
205380
|
super(message);
|
|
@@ -206423,6 +206429,14 @@ var BUNDLED_DEFAULT_CONFIG_PATH, PER_MODE_COLOR_KEYS, DEFAULT_HIGH_WATER_FRACTIO
|
|
|
206423
206429
|
throw new Error(`PUBLISHER_MAX_CONCURRENT_QUERIES must be a non-negative integer (got ${raw})`);
|
|
206424
206430
|
}
|
|
206425
206431
|
return raw;
|
|
206432
|
+
}, getPostgresPoolMax = () => {
|
|
206433
|
+
const raw = parseIntEnv("PUBLISHER_POSTGRES_POOL_MAX");
|
|
206434
|
+
if (raw === undefined)
|
|
206435
|
+
return DEFAULT_POSTGRES_POOL_MAX;
|
|
206436
|
+
if (raw < 1) {
|
|
206437
|
+
throw new Error(`PUBLISHER_POSTGRES_POOL_MAX must be a positive integer (got ${raw})`);
|
|
206438
|
+
}
|
|
206439
|
+
return raw;
|
|
206426
206440
|
}, getExtensionFetchPolicy = () => {
|
|
206427
206441
|
const raw = process.env.EXTENSION_FETCH_POLICY;
|
|
206428
206442
|
if (raw === undefined || raw.trim() === "")
|
|
@@ -283563,6 +283577,26 @@ var init_query_metadata = __esm(() => {
|
|
|
283563
283577
|
import { createPrivateKey } from "crypto";
|
|
283564
283578
|
import { existsSync } from "fs";
|
|
283565
283579
|
import path4 from "path";
|
|
283580
|
+
function validatePostgresSslmode(subject, sslmode) {
|
|
283581
|
+
if (!PROXIED_SSLMODES.includes(sslmode)) {
|
|
283582
|
+
throw new Error(`${subject} has unsupported sslmode '${sslmode}' ` + `(expected ${PROXIED_SSLMODES.join(" | ")}).`);
|
|
283583
|
+
}
|
|
283584
|
+
if (sslmode === "verify-ca") {
|
|
283585
|
+
const caBundle = process.env.NODE_EXTRA_CA_CERTS;
|
|
283586
|
+
if (!caBundle || !existsSync(caBundle)) {
|
|
283587
|
+
throw new Error(`${subject} uses sslmode 'verify-ca' but no readable ` + `CA bundle is available (NODE_EXTRA_CA_CERTS is unset or points at a missing file). ` + `Add the CA bundle to the image or use sslmode 'no-verify'.`);
|
|
283588
|
+
}
|
|
283589
|
+
}
|
|
283590
|
+
}
|
|
283591
|
+
function postgresStatementTimeoutMs(name, pg) {
|
|
283592
|
+
const value = pg.statementTimeoutMilliseconds;
|
|
283593
|
+
if (value === undefined || value === null)
|
|
283594
|
+
return;
|
|
283595
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > POSTGRES_MAX_STATEMENT_TIMEOUT_MS) {
|
|
283596
|
+
throw new Error(`Connection '${name}' has an invalid statementTimeoutMilliseconds ` + `${JSON.stringify(value)} (expected an integer from 1 to ${POSTGRES_MAX_STATEMENT_TIMEOUT_MS}).`);
|
|
283597
|
+
}
|
|
283598
|
+
return value;
|
|
283599
|
+
}
|
|
283566
283600
|
function nullToUndefined(value) {
|
|
283567
283601
|
return value ?? undefined;
|
|
283568
283602
|
}
|
|
@@ -283657,7 +283691,7 @@ function getStaticConnectionAttributes(type) {
|
|
|
283657
283691
|
case "postgres":
|
|
283658
283692
|
return {
|
|
283659
283693
|
dialectName: "postgres",
|
|
283660
|
-
isPool:
|
|
283694
|
+
isPool: true,
|
|
283661
283695
|
canPersist: true,
|
|
283662
283696
|
canStream: true
|
|
283663
283697
|
};
|
|
@@ -283724,12 +283758,34 @@ function parseServiceAccountKey(json2) {
|
|
|
283724
283758
|
}
|
|
283725
283759
|
return keyData;
|
|
283726
283760
|
}
|
|
283727
|
-
function
|
|
283728
|
-
|
|
283761
|
+
function directSslParams(sslmode) {
|
|
283762
|
+
switch (sslmode) {
|
|
283763
|
+
case "disable":
|
|
283764
|
+
case "no-verify":
|
|
283765
|
+
case "verify-full":
|
|
283766
|
+
return { sslmode };
|
|
283767
|
+
case "verify-ca":
|
|
283768
|
+
return {
|
|
283769
|
+
uselibpqcompat: "true",
|
|
283770
|
+
sslmode: "verify-ca",
|
|
283771
|
+
sslrootcert: process.env.NODE_EXTRA_CA_CERTS ?? ""
|
|
283772
|
+
};
|
|
283773
|
+
}
|
|
283774
|
+
}
|
|
283775
|
+
function buildPostgresConnectionString(config2, { applySslmode }) {
|
|
283776
|
+
if (config2.connectionString) {
|
|
283729
283777
|
return config2.connectionString;
|
|
283730
283778
|
}
|
|
283731
283779
|
const params = new URLSearchParams;
|
|
283732
|
-
|
|
283780
|
+
if (applySslmode && config2.sslmode != null) {
|
|
283781
|
+
for (const [key, value] of Object.entries(directSslParams(config2.sslmode))) {
|
|
283782
|
+
params.set(key, value);
|
|
283783
|
+
}
|
|
283784
|
+
} else if (process.env.PGSSLMODE) {
|
|
283785
|
+
params.set("sslmode", process.env.PGSSLMODE);
|
|
283786
|
+
} else {
|
|
283787
|
+
return;
|
|
283788
|
+
}
|
|
283733
283789
|
const auth = config2.userName && config2.password ? `${encodeURIComponent(config2.userName)}:${encodeURIComponent(config2.password)}@` : config2.userName ? `${encodeURIComponent(config2.userName)}@` : "";
|
|
283734
283790
|
const host = config2.host ?? "localhost";
|
|
283735
283791
|
const port = config2.port ? `:${config2.port}` : "";
|
|
@@ -283800,23 +283856,21 @@ function validateConnectionShape(connection) {
|
|
|
283800
283856
|
}
|
|
283801
283857
|
const sslmode = connection.postgresConnection?.sslmode;
|
|
283802
283858
|
if (sslmode != null) {
|
|
283803
|
-
|
|
283804
|
-
throw new Error(`Connection proxy on '${connection.name}' has unsupported sslmode '${sslmode}' ` + `(expected ${PROXIED_SSLMODES.join(" | ")}).`);
|
|
283805
|
-
}
|
|
283806
|
-
if (sslmode === "verify-ca") {
|
|
283807
|
-
const caBundle = process.env.NODE_EXTRA_CA_CERTS;
|
|
283808
|
-
if (!caBundle || !existsSync(caBundle)) {
|
|
283809
|
-
throw new Error(`Connection proxy on '${connection.name}' uses sslmode 'verify-ca' but no readable ` + `CA bundle is available (NODE_EXTRA_CA_CERTS is unset or points at a missing file). ` + `Add the CA bundle to the image or use sslmode 'no-verify'.`);
|
|
283810
|
-
}
|
|
283811
|
-
}
|
|
283859
|
+
validatePostgresSslmode(`Connection proxy on '${connection.name}'`, sslmode);
|
|
283812
283860
|
}
|
|
283813
283861
|
const dbName = connection.postgresConnection?.databaseName;
|
|
283814
283862
|
if (dbName && decodeURI(encodeURIComponent(dbName)) !== dbName) {
|
|
283815
283863
|
throw new Error(`Connection proxy on '${connection.name}' has a database name with characters that can't ` + `be carried over a proxied connection (${JSON.stringify(dbName)}). Use a database name ` + `without URI-reserved characters (; , / ? : @ & = + $ #).`);
|
|
283816
283864
|
}
|
|
283817
283865
|
}
|
|
283818
|
-
if (!connection.proxy && connection.postgresConnection?.sslmode) {
|
|
283819
|
-
|
|
283866
|
+
if (!connection.proxy && connection.postgresConnection?.sslmode != null) {
|
|
283867
|
+
validatePostgresSslmode(`Connection '${connection.name}'`, connection.postgresConnection.sslmode);
|
|
283868
|
+
if (connection.postgresConnection.connectionString) {
|
|
283869
|
+
logger.warn(`Connection '${connection.name}' sets both postgresConnection.sslmode and ` + `connectionString; sslmode is ignored and the connectionString's own sslmode applies.`);
|
|
283870
|
+
}
|
|
283871
|
+
}
|
|
283872
|
+
if (connection.postgresConnection) {
|
|
283873
|
+
postgresStatementTimeoutMs(connection.name ?? "", connection.postgresConnection);
|
|
283820
283874
|
}
|
|
283821
283875
|
switch (connection.type) {
|
|
283822
283876
|
case "postgres":
|
|
@@ -284113,7 +284167,9 @@ function assembleEnvironmentConnections(connections = [], environmentPath = "")
|
|
|
284113
284167
|
username: postgresConnection?.userName,
|
|
284114
284168
|
password: postgresConnection?.password,
|
|
284115
284169
|
databaseName: postgresConnection?.databaseName,
|
|
284116
|
-
connectionString: postgresConnection ? buildPostgresConnectionString(postgresConnection
|
|
284170
|
+
connectionString: postgresConnection ? buildPostgresConnectionString(postgresConnection, {
|
|
284171
|
+
applySslmode: !connection.proxy
|
|
284172
|
+
}) : undefined
|
|
284117
284173
|
};
|
|
284118
284174
|
break;
|
|
284119
284175
|
}
|
|
@@ -284252,7 +284308,7 @@ function validateAndBuildTrinoCoreConfig(trinoConfig) {
|
|
|
284252
284308
|
}
|
|
284253
284309
|
throw new Error(`Invalid Trino connection: expected "http://server:port" or "https://server:port".`);
|
|
284254
284310
|
}
|
|
284255
|
-
var PROXIED_SSLMODES, PUBLISHER_DUCKDB_API_FIELDS, DECLARABLE_STORAGE_DESTINATION_TYPES, STORAGE_DESTINATIONS_DIR = ".storage-destinations";
|
|
284311
|
+
var PROXIED_SSLMODES, POSTGRES_MAX_STATEMENT_TIMEOUT_MS = 2147483647, PUBLISHER_DUCKDB_API_FIELDS, DECLARABLE_STORAGE_DESTINATION_TYPES, STORAGE_DESTINATIONS_DIR = ".storage-destinations";
|
|
284256
284312
|
var init_connection_config = __esm(() => {
|
|
284257
284313
|
init_config();
|
|
284258
284314
|
init_errors();
|
|
@@ -294890,9 +294946,117 @@ async function attachSnowflake(connection, attachedDb) {
|
|
|
294890
294946
|
await connection.runSQL(attachCommand);
|
|
294891
294947
|
logger.info(`Successfully attached Snowflake database: ${attachedDb.name}`);
|
|
294892
294948
|
}
|
|
294893
|
-
function
|
|
294949
|
+
function mergeStatementTimeoutOption(existing, ms) {
|
|
294950
|
+
const tokens = existing.split(/(?<!\\)\s+/).filter((t2) => t2 !== "");
|
|
294951
|
+
const kept = [];
|
|
294952
|
+
let replaced = false;
|
|
294953
|
+
for (let i2 = 0;i2 < tokens.length; i2++) {
|
|
294954
|
+
if (tokens[i2] === "-c" && /^statement[_-]timeout=/i.test(tokens[i2 + 1] ?? "")) {
|
|
294955
|
+
i2++;
|
|
294956
|
+
replaced = true;
|
|
294957
|
+
} else if (STATEMENT_TIMEOUT_SWITCH.test(tokens[i2])) {
|
|
294958
|
+
replaced = true;
|
|
294959
|
+
} else {
|
|
294960
|
+
kept.push(tokens[i2]);
|
|
294961
|
+
}
|
|
294962
|
+
}
|
|
294963
|
+
kept.push("-c", `statement_timeout=${ms}`);
|
|
294964
|
+
return { value: kept.join(" "), replaced };
|
|
294965
|
+
}
|
|
294966
|
+
function conninfoPairs(conninfo) {
|
|
294967
|
+
const pairs = [];
|
|
294968
|
+
const isSpace = (c) => c !== undefined && /\s/.test(c);
|
|
294969
|
+
let i2 = 0;
|
|
294970
|
+
while (i2 < conninfo.length) {
|
|
294971
|
+
while (isSpace(conninfo[i2]))
|
|
294972
|
+
i2++;
|
|
294973
|
+
if (i2 >= conninfo.length)
|
|
294974
|
+
break;
|
|
294975
|
+
const start = i2;
|
|
294976
|
+
let key = "";
|
|
294977
|
+
while (i2 < conninfo.length && conninfo[i2] !== "=" && !isSpace(conninfo[i2])) {
|
|
294978
|
+
key += conninfo[i2++];
|
|
294979
|
+
}
|
|
294980
|
+
while (isSpace(conninfo[i2]))
|
|
294981
|
+
i2++;
|
|
294982
|
+
if (conninfo[i2] !== "=")
|
|
294983
|
+
break;
|
|
294984
|
+
i2++;
|
|
294985
|
+
while (isSpace(conninfo[i2]))
|
|
294986
|
+
i2++;
|
|
294987
|
+
let value = "";
|
|
294988
|
+
if (conninfo[i2] === "'") {
|
|
294989
|
+
i2++;
|
|
294990
|
+
while (i2 < conninfo.length && conninfo[i2] !== "'") {
|
|
294991
|
+
if (conninfo[i2] === "\\" && i2 + 1 < conninfo.length)
|
|
294992
|
+
i2++;
|
|
294993
|
+
value += conninfo[i2++];
|
|
294994
|
+
}
|
|
294995
|
+
i2++;
|
|
294996
|
+
} else {
|
|
294997
|
+
while (i2 < conninfo.length && !isSpace(conninfo[i2])) {
|
|
294998
|
+
if (conninfo[i2] === "\\" && i2 + 1 < conninfo.length)
|
|
294999
|
+
i2++;
|
|
295000
|
+
value += conninfo[i2++];
|
|
295001
|
+
}
|
|
295002
|
+
}
|
|
295003
|
+
pairs.push({ key, value, start, end: Math.min(i2, conninfo.length) });
|
|
295004
|
+
}
|
|
295005
|
+
return pairs;
|
|
295006
|
+
}
|
|
295007
|
+
function decodeUriComponentOrRaw(value) {
|
|
295008
|
+
try {
|
|
295009
|
+
return decodeURIComponent(value);
|
|
295010
|
+
} catch {
|
|
295011
|
+
return value;
|
|
295012
|
+
}
|
|
295013
|
+
}
|
|
295014
|
+
function withLibpqStatementTimeout(name, connectionString, pg) {
|
|
295015
|
+
const ms = postgresStatementTimeoutMs(name, pg);
|
|
295016
|
+
if (ms === undefined)
|
|
295017
|
+
return connectionString;
|
|
295018
|
+
const merged = (existing2) => {
|
|
295019
|
+
if (existing2 === undefined)
|
|
295020
|
+
return `-c statement_timeout=${ms}`;
|
|
295021
|
+
const { value, replaced } = mergeStatementTimeoutOption(existing2, ms);
|
|
295022
|
+
if (replaced) {
|
|
295023
|
+
logger.warn(`Connection '${name}' sets statementTimeoutMilliseconds and its connectionString's ` + `options also set statement_timeout; statementTimeoutMilliseconds applies.`);
|
|
295024
|
+
}
|
|
295025
|
+
return value;
|
|
295026
|
+
};
|
|
295027
|
+
if (/^postgres(ql)?:\/\//i.test(connectionString)) {
|
|
295028
|
+
const queryStart = connectionString.indexOf("?");
|
|
295029
|
+
if (queryStart === -1) {
|
|
295030
|
+
return `${connectionString}?options=${encodeURIComponent(merged(undefined))}`;
|
|
295031
|
+
}
|
|
295032
|
+
const params = connectionString.slice(queryStart + 1).split("&");
|
|
295033
|
+
const isOptions = (param) => decodeUriComponentOrRaw(param.split("=", 1)[0]) === "options";
|
|
295034
|
+
const last = params.map(isOptions).lastIndexOf(true);
|
|
295035
|
+
if (last === -1) {
|
|
295036
|
+
params.push(`options=${encodeURIComponent(merged(undefined))}`);
|
|
295037
|
+
} else {
|
|
295038
|
+
const raw = params[last].slice(params[last].indexOf("=") + 1);
|
|
295039
|
+
params[last] = `options=${encodeURIComponent(merged(decodeUriComponentOrRaw(raw)))}`;
|
|
295040
|
+
}
|
|
295041
|
+
return `${connectionString.slice(0, queryStart)}?${params.join("&")}`;
|
|
295042
|
+
}
|
|
295043
|
+
const existing = conninfoPairs(connectionString).filter((pair) => pair.key === "options").pop();
|
|
295044
|
+
if (!existing) {
|
|
295045
|
+
return `${connectionString} ${pgConninfoPair("options", merged(undefined))}`;
|
|
295046
|
+
}
|
|
295047
|
+
return connectionString.slice(0, existing.start) + pgConninfoPair("options", merged(existing.value)) + connectionString.slice(existing.end);
|
|
295048
|
+
}
|
|
295049
|
+
function buildPgConnectionString(pg, {
|
|
295050
|
+
name,
|
|
295051
|
+
applyConnectionOptions
|
|
295052
|
+
}) {
|
|
294894
295053
|
if (pg.connectionString) {
|
|
294895
|
-
|
|
295054
|
+
if (!applyConnectionOptions)
|
|
295055
|
+
return pg.connectionString;
|
|
295056
|
+
if (pg.sslmode != null) {
|
|
295057
|
+
logger.warn(`Connection '${name}' sets both postgresConnection.sslmode and ` + `connectionString; sslmode is ignored and the connectionString's own sslmode applies.`);
|
|
295058
|
+
}
|
|
295059
|
+
return withLibpqStatementTimeout(name, pg.connectionString, pg);
|
|
294896
295060
|
}
|
|
294897
295061
|
const parts = [];
|
|
294898
295062
|
if (pg.host)
|
|
@@ -294905,6 +295069,13 @@ function buildPgConnectionString(pg) {
|
|
|
294905
295069
|
parts.push(`user=${pg.userName}`);
|
|
294906
295070
|
if (pg.password)
|
|
294907
295071
|
parts.push(`password=${pg.password}`);
|
|
295072
|
+
if (applyConnectionOptions) {
|
|
295073
|
+
parts.push(...libpqStatementTimeoutParts(name, pg));
|
|
295074
|
+
if (pg.sslmode != null) {
|
|
295075
|
+
parts.push(...libpqSslmodeParts(`Connection '${name}'`, pg.sslmode, defaultProxiedAttachTrust()));
|
|
295076
|
+
return parts.join(" ");
|
|
295077
|
+
}
|
|
295078
|
+
}
|
|
294908
295079
|
const pgSSLMode = process.env.PGSSLMODE;
|
|
294909
295080
|
if (pgSSLMode) {
|
|
294910
295081
|
const mapping = {
|
|
@@ -294931,7 +295102,10 @@ async function attachPostgres(connection, attachedDb) {
|
|
|
294931
295102
|
}
|
|
294932
295103
|
await installAndLoadExtension(connection, "postgres");
|
|
294933
295104
|
const config2 = attachedDb.postgresConnection;
|
|
294934
|
-
const attachString = buildPgConnectionString(config2
|
|
295105
|
+
const attachString = buildPgConnectionString(config2, {
|
|
295106
|
+
name: attachedDb.name,
|
|
295107
|
+
applyConnectionOptions: true
|
|
295108
|
+
});
|
|
294935
295109
|
const attachCommand = `ATTACH '${escapeSQL(attachString)}' AS ${quoteIdentifier(attachedDb.name, "duckdb")} (TYPE postgres, READ_ONLY);`;
|
|
294936
295110
|
await connection.runSQL(attachCommand);
|
|
294937
295111
|
logger.info(`Successfully attached PostgreSQL database: ${attachedDb.name}`);
|
|
@@ -295026,7 +295200,10 @@ async function attachDuckLakeWithMode(connection, dbName, ducklakeConfig, option
|
|
|
295026
295200
|
});
|
|
295027
295201
|
}
|
|
295028
295202
|
const pg = ducklakeConfig.catalog.postgresConnection;
|
|
295029
|
-
const pgConnString = buildPgConnectionString(pg
|
|
295203
|
+
const pgConnString = buildPgConnectionString(pg, {
|
|
295204
|
+
name: dbName,
|
|
295205
|
+
applyConnectionOptions: false
|
|
295206
|
+
});
|
|
295030
295207
|
const mode = options.readOnly ? "READ_ONLY" : "READ_WRITE";
|
|
295031
295208
|
logger.debug(`pgConnString: ${redactPgSecrets(pgConnString)}`);
|
|
295032
295209
|
const escapedPgConnString = escapeSQL(pgConnString);
|
|
@@ -295193,7 +295370,10 @@ async function federatePostgres(connection, config2, deps = {}) {
|
|
|
295193
295370
|
});
|
|
295194
295371
|
attachString = buildProxiedPgAttachString(config2.name, pg, endpoint);
|
|
295195
295372
|
} else {
|
|
295196
|
-
attachString = buildPgConnectionString(pg
|
|
295373
|
+
attachString = buildPgConnectionString(pg, {
|
|
295374
|
+
name: config2.name,
|
|
295375
|
+
applyConnectionOptions: true
|
|
295376
|
+
});
|
|
295197
295377
|
}
|
|
295198
295378
|
logger.info(`Federating Postgres source for passthrough as alias '${alias}'${endpoint ? " through its SSH proxy" : ""}: ${redactPgSecrets(attachString)}`);
|
|
295199
295379
|
await connection.runSQL(`ATTACH OR REPLACE '${escapeSQL(attachString)}' AS ${quoteIdentifier(alias, "duckdb")} (TYPE postgres, READ_ONLY);`);
|
|
@@ -295256,30 +295436,39 @@ function buildProxiedPgAttachString(name, pg, endpoint, trust = defaultProxiedAt
|
|
|
295256
295436
|
parts.push(pgConninfoPair("user", pg.userName));
|
|
295257
295437
|
if (pg.password)
|
|
295258
295438
|
parts.push(pgConninfoPair("password", pg.password));
|
|
295259
|
-
|
|
295439
|
+
parts.push(...libpqSslmodeParts(`Connection proxy on '${name}'`, pg.sslmode ?? "no-verify", trust));
|
|
295440
|
+
parts.push(...libpqStatementTimeoutParts(name, pg));
|
|
295441
|
+
return parts.join(" ");
|
|
295442
|
+
}
|
|
295443
|
+
function libpqSslmodeParts(subject, mode, trust) {
|
|
295260
295444
|
switch (mode) {
|
|
295261
295445
|
case "disable":
|
|
295262
|
-
|
|
295263
|
-
break;
|
|
295446
|
+
return ["sslmode=disable"];
|
|
295264
295447
|
case "no-verify":
|
|
295265
|
-
|
|
295266
|
-
break;
|
|
295448
|
+
return ["sslmode=require"];
|
|
295267
295449
|
case "verify-ca": {
|
|
295268
295450
|
if (!trust.caBundle) {
|
|
295269
|
-
throw new Error(
|
|
295451
|
+
throw new Error(`${subject} uses sslmode 'verify-ca' but no trusted CA bundle is available (NODE_EXTRA_CA_CERTS is unset).`);
|
|
295270
295452
|
}
|
|
295271
|
-
|
|
295272
|
-
|
|
295453
|
+
return [
|
|
295454
|
+
"sslmode=verify-ca",
|
|
295455
|
+
pgConninfoPair("sslrootcert", trust.caBundle)
|
|
295456
|
+
];
|
|
295273
295457
|
}
|
|
295274
295458
|
case "verify-full":
|
|
295275
|
-
|
|
295276
|
-
|
|
295459
|
+
return [
|
|
295460
|
+
"sslmode=verify-full",
|
|
295461
|
+
pgConninfoPair("sslrootcert", trust.ambientBundle())
|
|
295462
|
+
];
|
|
295277
295463
|
default: {
|
|
295278
295464
|
const unhandled = mode;
|
|
295279
|
-
throw new Error(
|
|
295465
|
+
throw new Error(`${subject} has unsupported sslmode '${String(unhandled)}' (expected ${PROXIED_SSLMODES.join(" | ")}).`);
|
|
295280
295466
|
}
|
|
295281
295467
|
}
|
|
295282
|
-
|
|
295468
|
+
}
|
|
295469
|
+
function libpqStatementTimeoutParts(name, pg) {
|
|
295470
|
+
const ms = postgresStatementTimeoutMs(name, pg);
|
|
295471
|
+
return ms === undefined ? [] : [pgConninfoPair("options", `-c statement_timeout=${ms}`)];
|
|
295283
295472
|
}
|
|
295284
295473
|
function shouldRenewStorageSecret(opts) {
|
|
295285
295474
|
return opts.hasRenewer && !opts.alreadyRenewing && isExpiredCredentialError(opts.error);
|
|
@@ -295601,14 +295790,40 @@ function buildProxiedPostgresConnection(metadata, endpoint) {
|
|
|
295601
295790
|
const db = pg.databaseName ? `/${enc(pg.databaseName)}` : "";
|
|
295602
295791
|
const { query, ssl } = resolveProxiedTls(name, pg.host, pg.sslmode);
|
|
295603
295792
|
const connectionString = `postgresql://${auth}${endpoint.host}:${endpoint.port}${db}${query}`;
|
|
295793
|
+
const setupSQL = statementTimeoutSetupSQL(name, pg);
|
|
295604
295794
|
return new PooledPostgresConnection({
|
|
295605
295795
|
name,
|
|
295606
295796
|
connectionString,
|
|
295607
295797
|
...ssl ? { ssl } : {},
|
|
295798
|
+
...setupSQL ? { setupSQL } : {},
|
|
295608
295799
|
poolMin: 1,
|
|
295609
295800
|
poolMax: 20
|
|
295610
295801
|
});
|
|
295611
295802
|
}
|
|
295803
|
+
function buildEnvironmentPostgresConnection(metadata) {
|
|
295804
|
+
const name = metadata.apiConnection.name;
|
|
295805
|
+
const pg = metadata.apiConnection.postgresConnection;
|
|
295806
|
+
if (!pg) {
|
|
295807
|
+
throw new Error(`Connection '${name}' has type 'postgres' but no postgresConnection config.`);
|
|
295808
|
+
}
|
|
295809
|
+
const setupSQL = statementTimeoutSetupSQL(name, pg);
|
|
295810
|
+
return new EnvironmentPooledPostgresConnection({
|
|
295811
|
+
name,
|
|
295812
|
+
connectionString: buildPostgresConnectionString(pg, {
|
|
295813
|
+
applySslmode: true
|
|
295814
|
+
}),
|
|
295815
|
+
host: pg.host,
|
|
295816
|
+
port: pg.port,
|
|
295817
|
+
username: pg.userName,
|
|
295818
|
+
password: pg.password,
|
|
295819
|
+
databaseName: pg.databaseName,
|
|
295820
|
+
...setupSQL ? { setupSQL } : {}
|
|
295821
|
+
});
|
|
295822
|
+
}
|
|
295823
|
+
function statementTimeoutSetupSQL(name, pg) {
|
|
295824
|
+
const ms = postgresStatementTimeoutMs(name, pg);
|
|
295825
|
+
return ms === undefined ? undefined : `SET statement_timeout = ${ms}`;
|
|
295826
|
+
}
|
|
295612
295827
|
function buildDuckLakeConnection(metadata, entry) {
|
|
295613
295828
|
return new DuckLakeConnection(entryToDuckDBOptions(metadata.apiConnection.name, entry, metadata.workingDirectory));
|
|
295614
295829
|
}
|
|
@@ -295634,6 +295849,7 @@ function buildEnvironmentMalloyConfig(connections = [], environmentPath = "", is
|
|
|
295634
295849
|
const snowflakeJwtCache = new Map;
|
|
295635
295850
|
const azureDuckDBCache = new Map;
|
|
295636
295851
|
const proxyConnectionCache = new Map;
|
|
295852
|
+
const postgresConnectionCache = new Map;
|
|
295637
295853
|
const proxyEndpoints = new Map;
|
|
295638
295854
|
const attachPromises = new WeakMap;
|
|
295639
295855
|
const malloyConfig = new MalloyConfig(assembled.pojo, {
|
|
@@ -295724,6 +295940,21 @@ function buildEnvironmentMalloyConfig(connections = [], environmentPath = "", is
|
|
|
295724
295940
|
await attachOnce(connection2, metadata);
|
|
295725
295941
|
return connection2;
|
|
295726
295942
|
}
|
|
295943
|
+
if (metadata?.apiConnection.type === "postgres") {
|
|
295944
|
+
let connectionPromise = postgresConnectionCache.get(name);
|
|
295945
|
+
if (!connectionPromise) {
|
|
295946
|
+
connectionPromise = Promise.resolve(buildEnvironmentPostgresConnection(metadata));
|
|
295947
|
+
postgresConnectionCache.set(name, connectionPromise);
|
|
295948
|
+
connectionPromise.catch(() => {
|
|
295949
|
+
if (postgresConnectionCache.get(name) === connectionPromise) {
|
|
295950
|
+
postgresConnectionCache.delete(name);
|
|
295951
|
+
}
|
|
295952
|
+
});
|
|
295953
|
+
}
|
|
295954
|
+
const connection2 = await connectionPromise;
|
|
295955
|
+
await attachOnce(connection2, metadata);
|
|
295956
|
+
return connection2;
|
|
295957
|
+
}
|
|
295727
295958
|
const connection = await base.lookupConnection(name);
|
|
295728
295959
|
if (metadata) {
|
|
295729
295960
|
await attachOnce(connection, metadata);
|
|
@@ -295749,7 +295980,8 @@ function buildEnvironmentMalloyConfig(connections = [], environmentPath = "", is
|
|
|
295749
295980
|
...duckLakeCache.values(),
|
|
295750
295981
|
...snowflakeJwtCache.values(),
|
|
295751
295982
|
...azureDuckDBCache.values(),
|
|
295752
|
-
...proxyConnectionCache.values()
|
|
295983
|
+
...proxyConnectionCache.values(),
|
|
295984
|
+
...postgresConnectionCache.values()
|
|
295753
295985
|
];
|
|
295754
295986
|
const closeResults = await Promise.allSettled([
|
|
295755
295987
|
malloyConfig.shutdown("close"),
|
|
@@ -295763,6 +295995,7 @@ function buildEnvironmentMalloyConfig(connections = [], environmentPath = "", is
|
|
|
295763
295995
|
snowflakeJwtCache.clear();
|
|
295764
295996
|
azureDuckDBCache.clear();
|
|
295765
295997
|
proxyConnectionCache.clear();
|
|
295998
|
+
postgresConnectionCache.clear();
|
|
295766
295999
|
proxyEndpoints.clear();
|
|
295767
296000
|
const failures = [...closeResults, ...endpointResults].filter((result) => result.status === "rejected");
|
|
295768
296001
|
for (const failure of failures) {
|
|
@@ -295945,7 +296178,7 @@ async function testConnectionConfig(connectionConfig) {
|
|
|
295945
296178
|
}
|
|
295946
296179
|
}
|
|
295947
296180
|
}
|
|
295948
|
-
var import_db_publisher, extensionSessionPinned, sessionLimitsApplied, ducklakePreflightSeq = 0, ambientTrustBundles, ambientTrustDir, AzureDuckDBConnection, DuckLakeConnection, CONFIG_SECRET_KEY;
|
|
296181
|
+
var import_db_publisher, extensionSessionPinned, sessionLimitsApplied, STATEMENT_TIMEOUT_SWITCH, ducklakePreflightSeq = 0, ambientTrustBundles, ambientTrustDir, AzureDuckDBConnection, DuckLakeConnection, POSTGRES_POOL_MAX_USES = 1, PG_POOL_WAIT_TIMEOUT_MESSAGE = "timeout exceeded when trying to connect", EnvironmentPooledPostgresConnection, CONFIG_SECRET_KEY;
|
|
295949
296182
|
var init_connection = __esm(() => {
|
|
295950
296183
|
init_axios2();
|
|
295951
296184
|
init_config();
|
|
@@ -295963,6 +296196,7 @@ var init_connection = __esm(() => {
|
|
|
295963
296196
|
import_db_publisher = __toESM(require_dist6(), 1);
|
|
295964
296197
|
extensionSessionPinned = new WeakSet;
|
|
295965
296198
|
sessionLimitsApplied = new WeakMap;
|
|
296199
|
+
STATEMENT_TIMEOUT_SWITCH = /^(?:-c|--)statement[_-]timeout=/i;
|
|
295966
296200
|
ambientTrustBundles = new Map;
|
|
295967
296201
|
AzureDuckDBConnection = class AzureDuckDBConnection extends DuckDBConnection {
|
|
295968
296202
|
azureDatabases;
|
|
@@ -296054,6 +296288,38 @@ var init_connection = __esm(() => {
|
|
|
296054
296288
|
return result;
|
|
296055
296289
|
}
|
|
296056
296290
|
};
|
|
296291
|
+
EnvironmentPooledPostgresConnection = class EnvironmentPooledPostgresConnection extends PooledPostgresConnection {
|
|
296292
|
+
poolLimits() {
|
|
296293
|
+
return { max: getPostgresPoolMax(), connectionTimeoutMillis: 30000 };
|
|
296294
|
+
}
|
|
296295
|
+
buildClientConfig(cfg) {
|
|
296296
|
+
const base = super.buildClientConfig(cfg);
|
|
296297
|
+
return {
|
|
296298
|
+
...base,
|
|
296299
|
+
...this.poolLimits(),
|
|
296300
|
+
maxUses: POSTGRES_POOL_MAX_USES,
|
|
296301
|
+
application_name: "malloy-publisher"
|
|
296302
|
+
};
|
|
296303
|
+
}
|
|
296304
|
+
async withTlsHint(op) {
|
|
296305
|
+
try {
|
|
296306
|
+
return await super.withTlsHint(op);
|
|
296307
|
+
} catch (err) {
|
|
296308
|
+
if (err instanceof Error && err.message === PG_POOL_WAIT_TIMEOUT_MESSAGE) {
|
|
296309
|
+
const { max, connectionTimeoutMillis } = this.poolLimits();
|
|
296310
|
+
const waitSeconds = connectionTimeoutMillis / 1000;
|
|
296311
|
+
logger.warn("Postgres connection pool exhausted", {
|
|
296312
|
+
connection: this.name,
|
|
296313
|
+
poolMax: max,
|
|
296314
|
+
waitSeconds,
|
|
296315
|
+
remedy: "fewer concurrent queries on this connection, or raise PUBLISHER_POSTGRES_POOL_MAX"
|
|
296316
|
+
});
|
|
296317
|
+
throw new ConnectionPoolExhaustedError(`Connection '${this.name}' has no free database session: this server opens at most ${max} at a time for it, and none came free within ${waitSeconds} s. Retry once fewer queries are running on this connection.`);
|
|
296318
|
+
}
|
|
296319
|
+
throw err;
|
|
296320
|
+
}
|
|
296321
|
+
}
|
|
296322
|
+
};
|
|
296057
296323
|
CONFIG_SECRET_KEY = /pass(word)?|secret|private_?key|service_?account|access_?key|token|peaka_?key/i;
|
|
296058
296324
|
});
|
|
296059
296325
|
|
|
@@ -328412,6 +328678,9 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
|
|
|
328412
328678
|
});
|
|
328413
328679
|
throw new BadRequestError(err instanceof Error ? err.message : String(err));
|
|
328414
328680
|
}
|
|
328681
|
+
if (err instanceof ConnectionError) {
|
|
328682
|
+
throw err;
|
|
328683
|
+
}
|
|
328415
328684
|
if (err instanceof MalloyError7) {
|
|
328416
328685
|
throw err;
|
|
328417
328686
|
}
|
|
@@ -358133,7 +358402,8 @@ var POSTGRES = {
|
|
|
358133
358402
|
port: "scalar",
|
|
358134
358403
|
databaseName: "scalar",
|
|
358135
358404
|
userName: "scalar",
|
|
358136
|
-
sslmode: "scalar"
|
|
358405
|
+
sslmode: "scalar",
|
|
358406
|
+
statementTimeoutMilliseconds: "scalar"
|
|
358137
358407
|
};
|
|
358138
358408
|
var BIGQUERY = {
|
|
358139
358409
|
defaultProjectId: "scalar",
|
|
@@ -359919,7 +360189,7 @@ class ConnectionController {
|
|
|
359919
360189
|
try {
|
|
359920
360190
|
return await streamSqlWithBudget(malloyConnection, sqlStatement, optionsWithSignal, { maxRows, maxBytes });
|
|
359921
360191
|
} catch (error2) {
|
|
359922
|
-
if (error2 instanceof PayloadTooLargeError)
|
|
360192
|
+
if (error2 instanceof PayloadTooLargeError || error2 instanceof ConnectionError)
|
|
359923
360193
|
throw error2;
|
|
359924
360194
|
throw new ConnectionError(error2.message);
|
|
359925
360195
|
}
|
|
@@ -359934,6 +360204,8 @@ class ConnectionController {
|
|
|
359934
360204
|
try {
|
|
359935
360205
|
return await malloyConnection.runSQL(sqlStatement, optionsWithSignal);
|
|
359936
360206
|
} catch (error2) {
|
|
360207
|
+
if (error2 instanceof ConnectionError)
|
|
360208
|
+
throw error2;
|
|
359937
360209
|
throw new ConnectionError(error2.message);
|
|
359938
360210
|
}
|
|
359939
360211
|
}, getQueryTimeoutMs());
|
|
@@ -359966,6 +360238,8 @@ class ConnectionController {
|
|
|
359966
360238
|
} catch (error2) {
|
|
359967
360239
|
if (signal.aborted)
|
|
359968
360240
|
throw error2;
|
|
360241
|
+
if (error2 instanceof ConnectionError)
|
|
360242
|
+
throw error2;
|
|
359969
360243
|
throw new ConnectionError(error2.message);
|
|
359970
360244
|
}
|
|
359971
360245
|
}, getQueryTimeoutMs());
|
|
@@ -365238,6 +365512,15 @@ function classifyToolError(operation, identifier, error2) {
|
|
|
365238
365512
|
suggestions: [...BACK_PRESSURE_SUGGESTIONS]
|
|
365239
365513
|
};
|
|
365240
365514
|
}
|
|
365515
|
+
if (error2 instanceof ConnectionPoolExhaustedError) {
|
|
365516
|
+
return {
|
|
365517
|
+
message: error2.message,
|
|
365518
|
+
suggestions: [
|
|
365519
|
+
"Retry shortly; this clears as other queries on the connection finish.",
|
|
365520
|
+
"If it persists, run fewer queries at once on this connection, or ask the operator to raise PUBLISHER_POSTGRES_POOL_MAX."
|
|
365521
|
+
]
|
|
365522
|
+
};
|
|
365523
|
+
}
|
|
365241
365524
|
if (error2 instanceof ResponseUnserializableError) {
|
|
365242
365525
|
return {
|
|
365243
365526
|
message: error2.message,
|
|
@@ -381636,7 +381919,7 @@ ${query}`);
|
|
|
381636
381919
|
// src/service/environment_store.ts
|
|
381637
381920
|
init_google_credentials();
|
|
381638
381921
|
// package.json
|
|
381639
|
-
var version2 = "0.9.
|
|
381922
|
+
var version2 = "0.9.6";
|
|
381640
381923
|
|
|
381641
381924
|
// src/version.ts
|
|
381642
381925
|
var SERVER_VERSION = version2;
|
package/package.json
CHANGED