mirror of
https://github.com/Kaelio/ktx.git
synced 2026-07-22 11:51:01 +02:00
feat(connectors): generalize readiness and constraint handling (#212)
* feat(connectors): add postgres maxConnections * feat(connectors): add mysql maxConnections * feat(connectors): add sqlserver maxConnections * feat(connectors): rename snowflake pool config * docs: document connector maxConnections * feat(scan): add constraint discovery warning helper * feat(scan): carry structural warnings through reports * feat(postgres): soft-fail denied constraint discovery * feat(mysql): soft-fail denied constraint discovery * feat(sqlserver): soft-fail denied constraint discovery * feat(bigquery): soft-fail denied primary key discovery * feat(snowflake): report denied primary key discovery * test(scan): verify constraint discovery warnings * feat(historic-sql): use shared readiness probes * docs: document query history readiness probes * test(historic-sql): verify readiness probe registry * test(ingest): account for live database warnings artifact * Add skip option for agent setup
This commit is contained in:
parent
cfd1749ab9
commit
78b8a0c025
42 changed files with 2763 additions and 554 deletions
70
packages/cli/src/context/scan/constraint-discovery.test.ts
Normal file
70
packages/cli/src/context/scan/constraint-discovery.test.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { constraintDiscoveryWarning, tryConstraintQuery } from './constraint-discovery.js';
|
||||
|
||||
describe('tryConstraintQuery', () => {
|
||||
it('returns the query value when the query succeeds', async () => {
|
||||
await expect(
|
||||
tryConstraintQuery(
|
||||
{
|
||||
schema: 'public',
|
||||
kind: 'primary_key',
|
||||
isDeniedError: () => false,
|
||||
},
|
||||
async () => ['id'],
|
||||
),
|
||||
).resolves.toEqual({ ok: true, value: ['id'] });
|
||||
});
|
||||
|
||||
it('returns a recoverable warning when the classifier recognizes denial', async () => {
|
||||
const error = Object.assign(new Error('permission denied'), { code: '42501' });
|
||||
|
||||
await expect(
|
||||
tryConstraintQuery(
|
||||
{
|
||||
schema: 'analytics',
|
||||
kind: 'foreign_key',
|
||||
isDeniedError: (candidate) => candidate === error,
|
||||
},
|
||||
async () => {
|
||||
throw error;
|
||||
},
|
||||
),
|
||||
).resolves.toEqual({
|
||||
ok: false,
|
||||
warning: {
|
||||
code: 'constraint_discovery_unauthorized',
|
||||
message: 'Skipped foreign-key discovery in analytics (insufficient grants on system catalogs)',
|
||||
recoverable: true,
|
||||
metadata: { schema: 'analytics', kind: 'foreign_key' },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('rethrows non-denial errors unchanged', async () => {
|
||||
const error = Object.assign(new Error('connection reset'), { code: 'ECONNRESET' });
|
||||
|
||||
await expect(
|
||||
tryConstraintQuery(
|
||||
{
|
||||
schema: 'public',
|
||||
kind: 'primary_key',
|
||||
isDeniedError: () => false,
|
||||
},
|
||||
async () => {
|
||||
throw error;
|
||||
},
|
||||
),
|
||||
).rejects.toBe(error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('constraintDiscoveryWarning', () => {
|
||||
it('formats stable primary-key warning text and metadata', () => {
|
||||
expect(constraintDiscoveryWarning({ schema: 'public', kind: 'primary_key' })).toEqual({
|
||||
code: 'constraint_discovery_unauthorized',
|
||||
message: 'Skipped primary-key discovery in public (insufficient grants on system catalogs)',
|
||||
recoverable: true,
|
||||
metadata: { schema: 'public', kind: 'primary_key' },
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue