@malloy-publisher/server 0.0.196-dev → 0.0.198-dev
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 +213 -214
- package/dist/app/assets/EnvironmentPage-1j6QDWAy.js +1 -0
- package/dist/app/assets/HomePage-DMop21VG.js +1 -0
- package/dist/app/assets/MainPage-BbE8ETz1.js +2 -0
- package/dist/app/assets/ModelPage-D2jvfe3t.js +1 -0
- package/dist/app/assets/PackagePage-BbnhGoD3.js +1 -0
- package/dist/app/assets/{RouteError-DefbDO7F.js → RouteError-D3LGEZ3i.js} +1 -1
- package/dist/app/assets/WorkbookPage-DttVIj4u.js +1 -0
- package/dist/app/assets/{core-BrfQApxh.es-DnvCX4oH.js → core-w79IMXAG.es-Bd0UlzOL.js} +1 -1
- package/dist/app/assets/{index-Bu0ub036.js → index-5K9YjIxF.js} +117 -117
- package/dist/app/assets/{index-CkzK3JIl.js → index-C513UodQ.js} +1 -1
- package/dist/app/assets/{index-CoA6HIGS.js → index-DIgzgp69.js} +1 -1
- package/dist/app/assets/{index.umd-B6Ms2PpL.js → index.umd-BMeMPq_9.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/server.mjs +1947 -1317
- package/package.json +1 -1
- package/publisher.config.json +2 -2
- package/src/config.spec.ts +74 -66
- package/src/config.ts +50 -47
- package/src/controller/compile.controller.ts +10 -7
- package/src/controller/connection.controller.ts +79 -58
- package/src/controller/database.controller.ts +10 -7
- package/src/controller/manifest.controller.ts +23 -14
- package/src/controller/materialization.controller.ts +14 -14
- package/src/controller/model.controller.ts +35 -20
- package/src/controller/package.controller.ts +83 -49
- package/src/controller/query.controller.ts +11 -8
- package/src/controller/watch-mode.controller.ts +35 -29
- package/src/errors.ts +2 -2
- package/src/mcp/error_messages.ts +2 -2
- package/src/mcp/handler_utils.ts +23 -20
- package/src/mcp/mcp_constants.ts +1 -1
- package/src/mcp/prompts/handlers.ts +3 -3
- package/src/mcp/prompts/prompt_service.ts +5 -5
- package/src/mcp/prompts/utils.ts +12 -12
- package/src/mcp/resource_metadata.ts +3 -3
- package/src/mcp/resources/environment_resource.ts +187 -0
- package/src/mcp/resources/model_resource.ts +19 -17
- package/src/mcp/resources/notebook_resource.ts +13 -13
- package/src/mcp/resources/package_resource.ts +30 -27
- package/src/mcp/resources/query_resource.ts +15 -10
- package/src/mcp/resources/source_resource.ts +10 -10
- package/src/mcp/resources/view_resource.ts +11 -11
- package/src/mcp/server.ts +16 -14
- package/src/mcp/tools/discovery_tools.ts +67 -49
- package/src/mcp/tools/execute_query_tool.ts +14 -14
- package/src/server-old.ts +1139 -0
- package/src/server.ts +191 -159
- package/src/service/connection.spec.ts +158 -133
- package/src/service/connection.ts +42 -39
- package/src/service/connection_config.spec.ts +13 -11
- package/src/service/connection_config.ts +28 -19
- package/src/service/connection_service.spec.ts +63 -43
- package/src/service/connection_service.ts +106 -89
- package/src/service/{project.ts → environment.ts} +92 -77
- package/src/service/{project_compile.spec.ts → environment_compile.spec.ts} +1 -1
- package/src/service/{project_store.spec.ts → environment_store.spec.ts} +99 -85
- package/src/service/{project_store.ts → environment_store.ts} +368 -326
- package/src/service/manifest_service.spec.ts +15 -15
- package/src/service/manifest_service.ts +26 -21
- package/src/service/materialization_service.spec.ts +93 -59
- package/src/service/materialization_service.ts +71 -62
- package/src/service/materialized_table_gc.spec.ts +15 -15
- package/src/service/materialized_table_gc.ts +3 -3
- package/src/service/model.ts +2 -2
- package/src/service/package.spec.ts +2 -2
- package/src/service/package.ts +23 -21
- package/src/service/resolve_environment.ts +15 -0
- package/src/storage/DatabaseInterface.ts +34 -25
- package/src/storage/StorageManager.mock.ts +3 -3
- package/src/storage/StorageManager.ts +24 -23
- package/src/storage/duckdb/ConnectionRepository.ts +13 -11
- package/src/storage/duckdb/DuckDBConnection.ts +1 -1
- package/src/storage/duckdb/DuckDBManifestStore.ts +6 -6
- package/src/storage/duckdb/DuckDBRepository.ts +47 -47
- package/src/storage/duckdb/{ProjectRepository.ts → EnvironmentRepository.ts} +35 -35
- package/src/storage/duckdb/ManifestRepository.ts +21 -20
- package/src/storage/duckdb/MaterializationRepository.ts +31 -28
- package/src/storage/duckdb/PackageRepository.ts +11 -11
- package/src/storage/duckdb/manifest_store.spec.ts +2 -2
- package/src/storage/duckdb/schema.ts +20 -20
- package/src/storage/ducklake/DuckLakeManifestStore.ts +14 -14
- package/tests/fixtures/publisher.config.json +1 -1
- package/tests/harness/e2e.ts +1 -1
- package/tests/harness/mcp_test_setup.ts +1 -1
- package/tests/harness/mocks.ts +10 -8
- package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
- package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +27 -48
- package/tests/integration/mcp/mcp_resource.integration.spec.ts +26 -35
- package/tests/unit/duckdb/attached_databases.test.ts +51 -33
- package/tests/unit/ducklake/ducklake.test.ts +24 -22
- package/tests/unit/mcp/prompt_happy.test.ts +8 -8
- package/dist/app/assets/HomePage-DbZS0N7G.js +0 -1
- package/dist/app/assets/MainPage-CBuWkbmr.js +0 -2
- package/dist/app/assets/ModelPage-Bt37smot.js +0 -1
- package/dist/app/assets/PackagePage-DLZe50WG.js +0 -1
- package/dist/app/assets/ProjectPage-FQTEPXP4.js +0 -1
- package/dist/app/assets/WorkbookPage-CkAo16ar.js +0 -1
- package/src/mcp/resources/project_resource.ts +0 -184
- package/src/service/resolve_project.ts +0 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
BuildGraph,
|
|
3
|
-
Connection as MalloyConnection,
|
|
4
3
|
MalloyConfig,
|
|
4
|
+
Connection as MalloyConnection,
|
|
5
5
|
PersistSource,
|
|
6
6
|
} from "@malloydata/malloy";
|
|
7
7
|
import { Manifest } from "@malloydata/malloy";
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
ResourceRepository,
|
|
20
20
|
} from "../storage/DatabaseInterface";
|
|
21
21
|
import { DuplicateActiveMaterializationError } from "../storage/duckdb/MaterializationRepository";
|
|
22
|
+
import { EnvironmentStore } from "./environment_store";
|
|
22
23
|
import { ManifestService } from "./manifest_service";
|
|
23
24
|
import {
|
|
24
25
|
dropManifestEntries,
|
|
@@ -26,9 +27,8 @@ import {
|
|
|
26
27
|
liveTableKey,
|
|
27
28
|
} from "./materialized_table_gc";
|
|
28
29
|
import { Model } from "./model";
|
|
29
|
-
import { ProjectStore } from "./project_store";
|
|
30
30
|
import { quoteTablePath, splitTablePath } from "./quoting";
|
|
31
|
-
import {
|
|
31
|
+
import { resolveEnvironmentId } from "./resolve_environment";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Length of the BuildID prefix used when synthesizing staging table names.
|
|
@@ -128,7 +128,7 @@ const VALID_TRANSITIONS: Record<
|
|
|
128
128
|
* The manifest is optionally activated after a successful build so
|
|
129
129
|
* subsequent queries resolve persist references to materialized tables.
|
|
130
130
|
*
|
|
131
|
-
* Enforces at-most-one concurrent build per (
|
|
131
|
+
* Enforces at-most-one concurrent build per (environment, package) via a
|
|
132
132
|
* DB-level unique index on `materializations.active_key` (see
|
|
133
133
|
* `MaterializationRepository`), and supports cooperative cancellation
|
|
134
134
|
* through `AbortController`.
|
|
@@ -149,12 +149,12 @@ export class MaterializationService {
|
|
|
149
149
|
private runningAbortControllers = new Map<string, AbortController>();
|
|
150
150
|
|
|
151
151
|
constructor(
|
|
152
|
-
private
|
|
152
|
+
private environmentStore: EnvironmentStore,
|
|
153
153
|
private manifestService: ManifestService,
|
|
154
154
|
) {}
|
|
155
155
|
|
|
156
156
|
private get repository(): ResourceRepository {
|
|
157
|
-
return this.
|
|
157
|
+
return this.environmentStore.storageManager.getRepository();
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
// ==================== STATE MACHINE ====================
|
|
@@ -198,28 +198,28 @@ export class MaterializationService {
|
|
|
198
198
|
// ==================== BUILD QUERIES ====================
|
|
199
199
|
|
|
200
200
|
async listMaterializations(
|
|
201
|
-
|
|
201
|
+
environmentName: string,
|
|
202
202
|
packageName: string,
|
|
203
203
|
options?: { limit?: number; offset?: number },
|
|
204
204
|
): Promise<Materialization[]> {
|
|
205
|
-
const
|
|
205
|
+
const environmentId = await this.resolveEnvironmentId(environmentName);
|
|
206
206
|
return this.repository.listMaterializations(
|
|
207
|
-
|
|
207
|
+
environmentId,
|
|
208
208
|
packageName,
|
|
209
209
|
options,
|
|
210
210
|
);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
async getMaterialization(
|
|
214
|
-
|
|
214
|
+
environmentName: string,
|
|
215
215
|
packageName: string,
|
|
216
216
|
buildId: string,
|
|
217
217
|
): Promise<Materialization> {
|
|
218
|
-
const
|
|
218
|
+
const environmentId = await this.resolveEnvironmentId(environmentName);
|
|
219
219
|
const execution = await this.repository.getMaterializationById(buildId);
|
|
220
220
|
if (
|
|
221
221
|
!execution ||
|
|
222
|
-
execution.
|
|
222
|
+
execution.environmentId !== environmentId ||
|
|
223
223
|
execution.packageName !== packageName
|
|
224
224
|
) {
|
|
225
225
|
throw new MaterializationNotFoundError(
|
|
@@ -236,21 +236,24 @@ export class MaterializationService {
|
|
|
236
236
|
* metadata so `startMaterialization` can read them back.
|
|
237
237
|
*/
|
|
238
238
|
async createMaterialization(
|
|
239
|
-
|
|
239
|
+
environmentName: string,
|
|
240
240
|
packageName: string,
|
|
241
241
|
options: { forceRefresh?: boolean; autoLoadManifest?: boolean } = {},
|
|
242
242
|
): Promise<Materialization> {
|
|
243
|
-
const
|
|
243
|
+
const environmentId = await this.resolveEnvironmentId(environmentName);
|
|
244
244
|
|
|
245
245
|
// Verify the package exists.
|
|
246
|
-
const
|
|
247
|
-
|
|
246
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
247
|
+
environmentName,
|
|
248
|
+
false,
|
|
249
|
+
);
|
|
250
|
+
await environment.getPackage(packageName, false);
|
|
248
251
|
|
|
249
252
|
// A non-atomic probe for a helpful error message. The DB-level unique
|
|
250
253
|
// index on active_key is the actual race-free guard — see the catch
|
|
251
254
|
// block below.
|
|
252
255
|
const active = await this.repository.getActiveMaterialization(
|
|
253
|
-
|
|
256
|
+
environmentId,
|
|
254
257
|
packageName,
|
|
255
258
|
);
|
|
256
259
|
if (active) {
|
|
@@ -266,7 +269,7 @@ export class MaterializationService {
|
|
|
266
269
|
|
|
267
270
|
try {
|
|
268
271
|
return await this.repository.createMaterialization(
|
|
269
|
-
|
|
272
|
+
environmentId,
|
|
270
273
|
packageName,
|
|
271
274
|
"PENDING",
|
|
272
275
|
metadata,
|
|
@@ -276,7 +279,7 @@ export class MaterializationService {
|
|
|
276
279
|
// Lost the race with a concurrent create. Re-read to report the
|
|
277
280
|
// winner's id for parity with the non-racy error above.
|
|
278
281
|
const winner = await this.repository.getActiveMaterialization(
|
|
279
|
-
|
|
282
|
+
environmentId,
|
|
280
283
|
packageName,
|
|
281
284
|
);
|
|
282
285
|
throw new MaterializationConflictError(
|
|
@@ -294,13 +297,13 @@ export class MaterializationService {
|
|
|
294
297
|
* background. Returns the RUNNING execution immediately.
|
|
295
298
|
*/
|
|
296
299
|
async startMaterialization(
|
|
297
|
-
|
|
300
|
+
environmentName: string,
|
|
298
301
|
packageName: string,
|
|
299
302
|
buildId: string,
|
|
300
303
|
): Promise<Materialization> {
|
|
301
|
-
const
|
|
304
|
+
const environmentId = await this.resolveEnvironmentId(environmentName);
|
|
302
305
|
const execution = await this.getMaterialization(
|
|
303
|
-
|
|
306
|
+
environmentName,
|
|
304
307
|
packageName,
|
|
305
308
|
buildId,
|
|
306
309
|
);
|
|
@@ -313,7 +316,7 @@ export class MaterializationService {
|
|
|
313
316
|
|
|
314
317
|
// Check for a *different* active materialization on this package.
|
|
315
318
|
const active = await this.repository.getActiveMaterialization(
|
|
316
|
-
|
|
319
|
+
environmentId,
|
|
317
320
|
packageName,
|
|
318
321
|
);
|
|
319
322
|
if (active && active.id !== execution.id) {
|
|
@@ -331,8 +334,8 @@ export class MaterializationService {
|
|
|
331
334
|
// Fire-and-forget: run the build in the background.
|
|
332
335
|
this.runMaterialization(
|
|
333
336
|
execution.id,
|
|
334
|
-
|
|
335
|
-
|
|
337
|
+
environmentName,
|
|
338
|
+
environmentId,
|
|
336
339
|
packageName,
|
|
337
340
|
metadata,
|
|
338
341
|
).catch((err) => {
|
|
@@ -347,8 +350,8 @@ export class MaterializationService {
|
|
|
347
350
|
|
|
348
351
|
private async runMaterialization(
|
|
349
352
|
executionId: string,
|
|
350
|
-
|
|
351
|
-
|
|
353
|
+
environmentName: string,
|
|
354
|
+
environmentId: string,
|
|
352
355
|
packageName: string,
|
|
353
356
|
metadata: Record<string, unknown>,
|
|
354
357
|
): Promise<void> {
|
|
@@ -357,8 +360,8 @@ export class MaterializationService {
|
|
|
357
360
|
|
|
358
361
|
try {
|
|
359
362
|
const buildMetadata = await this.executeBuild(
|
|
360
|
-
|
|
361
|
-
|
|
363
|
+
environmentName,
|
|
364
|
+
environmentId,
|
|
362
365
|
packageName,
|
|
363
366
|
!!metadata.forceRefresh,
|
|
364
367
|
abortController.signal,
|
|
@@ -366,14 +369,14 @@ export class MaterializationService {
|
|
|
366
369
|
|
|
367
370
|
if (metadata.autoLoadManifest) {
|
|
368
371
|
const updatedManifest = await this.manifestService.getManifest(
|
|
369
|
-
|
|
372
|
+
environmentId,
|
|
370
373
|
packageName,
|
|
371
374
|
);
|
|
372
|
-
const
|
|
373
|
-
|
|
375
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
376
|
+
environmentName,
|
|
374
377
|
false,
|
|
375
378
|
);
|
|
376
|
-
const pkg = await
|
|
379
|
+
const pkg = await environment.getPackage(packageName, false);
|
|
377
380
|
await pkg.reloadAllModels(updatedManifest.entries);
|
|
378
381
|
}
|
|
379
382
|
|
|
@@ -415,12 +418,12 @@ export class MaterializationService {
|
|
|
415
418
|
* Cancels a running build. Takes a specific buildId.
|
|
416
419
|
*/
|
|
417
420
|
async stopMaterialization(
|
|
418
|
-
|
|
421
|
+
environmentName: string,
|
|
419
422
|
packageName: string,
|
|
420
423
|
buildId: string,
|
|
421
424
|
): Promise<Materialization> {
|
|
422
425
|
const execution = await this.getMaterialization(
|
|
423
|
-
|
|
426
|
+
environmentName,
|
|
424
427
|
packageName,
|
|
425
428
|
buildId,
|
|
426
429
|
);
|
|
@@ -455,12 +458,12 @@ export class MaterializationService {
|
|
|
455
458
|
* (SUCCESS, FAILED, CANCELLED) can be deleted.
|
|
456
459
|
*/
|
|
457
460
|
async deleteMaterialization(
|
|
458
|
-
|
|
461
|
+
environmentName: string,
|
|
459
462
|
packageName: string,
|
|
460
463
|
materializationId: string,
|
|
461
464
|
): Promise<void> {
|
|
462
465
|
const execution = await this.getMaterialization(
|
|
463
|
-
|
|
466
|
+
environmentName,
|
|
464
467
|
packageName,
|
|
465
468
|
materializationId,
|
|
466
469
|
);
|
|
@@ -481,7 +484,7 @@ export class MaterializationService {
|
|
|
481
484
|
*
|
|
482
485
|
* This is the only out-of-band teardown surface exposed by the
|
|
483
486
|
* publisher and is intended for a single caller: the controlplane,
|
|
484
|
-
* invoking it on the truly destructive path before the package/
|
|
487
|
+
* invoking it on the truly destructive path before the package/environment
|
|
485
488
|
* is torn down. The publisher's `DELETE` endpoints are *not* wired into
|
|
486
489
|
* teardown because the controlplane invokes them for non-destructive
|
|
487
490
|
* unload too (down-replicate, drain, archive) where the entity still
|
|
@@ -505,14 +508,14 @@ export class MaterializationService {
|
|
|
505
508
|
* deleting manifest rows.
|
|
506
509
|
*/
|
|
507
510
|
async teardownPackage(
|
|
508
|
-
|
|
511
|
+
environmentName: string,
|
|
509
512
|
packageName: string,
|
|
510
513
|
options: { dryRun?: boolean } = {},
|
|
511
514
|
): Promise<GcResult> {
|
|
512
|
-
const
|
|
515
|
+
const environmentId = await this.resolveEnvironmentId(environmentName);
|
|
513
516
|
|
|
514
517
|
const active = await this.repository.getActiveMaterialization(
|
|
515
|
-
|
|
518
|
+
environmentId,
|
|
516
519
|
packageName,
|
|
517
520
|
);
|
|
518
521
|
if (active) {
|
|
@@ -521,11 +524,14 @@ export class MaterializationService {
|
|
|
521
524
|
);
|
|
522
525
|
}
|
|
523
526
|
|
|
524
|
-
const
|
|
525
|
-
|
|
527
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
528
|
+
environmentName,
|
|
529
|
+
false,
|
|
530
|
+
);
|
|
531
|
+
const pkg = await environment.getPackage(packageName, false);
|
|
526
532
|
|
|
527
533
|
const entries = await this.manifestService.listEntries(
|
|
528
|
-
|
|
534
|
+
environmentId,
|
|
529
535
|
packageName,
|
|
530
536
|
);
|
|
531
537
|
|
|
@@ -541,7 +547,7 @@ export class MaterializationService {
|
|
|
541
547
|
return dropManifestEntries(entries, {
|
|
542
548
|
connections,
|
|
543
549
|
manifestService: this.manifestService,
|
|
544
|
-
|
|
550
|
+
environmentId,
|
|
545
551
|
dryRun: options.dryRun,
|
|
546
552
|
forceDeleteRowOnMissingConnection: true,
|
|
547
553
|
});
|
|
@@ -560,30 +566,33 @@ export class MaterializationService {
|
|
|
560
566
|
* `gcErrors` metadata so the controller/UI can show them.
|
|
561
567
|
*/
|
|
562
568
|
private async executeBuild(
|
|
563
|
-
|
|
564
|
-
|
|
569
|
+
environmentName: string,
|
|
570
|
+
environmentId: string,
|
|
565
571
|
packageName: string,
|
|
566
572
|
forceRefresh: boolean,
|
|
567
573
|
signal: AbortSignal,
|
|
568
574
|
): Promise<Record<string, unknown>> {
|
|
569
575
|
logger.info("Starting materialization build", {
|
|
570
|
-
|
|
576
|
+
environmentName,
|
|
571
577
|
packageName,
|
|
572
578
|
});
|
|
573
579
|
|
|
574
|
-
const
|
|
575
|
-
|
|
580
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
581
|
+
environmentName,
|
|
582
|
+
false,
|
|
583
|
+
);
|
|
584
|
+
const pkg = await environment.getPackage(packageName, false);
|
|
576
585
|
|
|
577
586
|
// ── STEP 1: LOAD ───────────────────────────────────────────────
|
|
578
587
|
const manifest = new Manifest();
|
|
579
588
|
const existingManifest = await this.manifestService.getManifest(
|
|
580
|
-
|
|
589
|
+
environmentId,
|
|
581
590
|
packageName,
|
|
582
591
|
);
|
|
583
592
|
manifest.loadText(JSON.stringify(existingManifest));
|
|
584
593
|
|
|
585
594
|
const existingEntries = await this.manifestService.listEntries(
|
|
586
|
-
|
|
595
|
+
environmentId,
|
|
587
596
|
packageName,
|
|
588
597
|
);
|
|
589
598
|
const knownMaterializedTables = new Set(
|
|
@@ -594,7 +603,7 @@ export class MaterializationService {
|
|
|
594
603
|
|
|
595
604
|
// ── STEP 2: COMPILE & PLAN ─────────────────────────────────────
|
|
596
605
|
// `connections` is built lazily from the connection names the plan
|
|
597
|
-
// actually targets — no upfront ATTACH on every
|
|
606
|
+
// actually targets — no upfront ATTACH on every environment connection.
|
|
598
607
|
const { graphs, sources, connectionDigests, connections } =
|
|
599
608
|
await this.compilePackageBuildPlan(pkg, signal);
|
|
600
609
|
|
|
@@ -634,7 +643,7 @@ export class MaterializationService {
|
|
|
634
643
|
connection,
|
|
635
644
|
connectionDigests,
|
|
636
645
|
forceRefresh,
|
|
637
|
-
|
|
646
|
+
environmentId,
|
|
638
647
|
packageName,
|
|
639
648
|
knownMaterializedTables,
|
|
640
649
|
);
|
|
@@ -649,7 +658,7 @@ export class MaterializationService {
|
|
|
649
658
|
// ── STEP 4: GC ─────────────────────────────────────────────────
|
|
650
659
|
const gcResult = await this.runPostBuildGc(
|
|
651
660
|
manifest,
|
|
652
|
-
|
|
661
|
+
environmentId,
|
|
653
662
|
packageName,
|
|
654
663
|
connections,
|
|
655
664
|
);
|
|
@@ -800,7 +809,7 @@ export class MaterializationService {
|
|
|
800
809
|
connection: MalloyConnection,
|
|
801
810
|
connectionDigests: Record<string, string>,
|
|
802
811
|
forceRefresh: boolean,
|
|
803
|
-
|
|
812
|
+
environmentId: string,
|
|
804
813
|
packageName: string,
|
|
805
814
|
knownMaterializedTables: Set<string>,
|
|
806
815
|
): Promise<Record<string, unknown>> {
|
|
@@ -899,7 +908,7 @@ export class MaterializationService {
|
|
|
899
908
|
manifest.update(buildId, { tableName });
|
|
900
909
|
|
|
901
910
|
await this.manifestService.writeEntry(
|
|
902
|
-
|
|
911
|
+
environmentId,
|
|
903
912
|
packageName,
|
|
904
913
|
buildId,
|
|
905
914
|
tableName,
|
|
@@ -930,13 +939,13 @@ export class MaterializationService {
|
|
|
930
939
|
*/
|
|
931
940
|
private async runPostBuildGc(
|
|
932
941
|
manifest: Manifest,
|
|
933
|
-
|
|
942
|
+
environmentId: string,
|
|
934
943
|
packageName: string,
|
|
935
944
|
connections: Map<string, MalloyConnection>,
|
|
936
945
|
): Promise<GcResult> {
|
|
937
946
|
const activeManifest = manifest.activeEntries;
|
|
938
947
|
const allDbEntries = await this.manifestService.listEntries(
|
|
939
|
-
|
|
948
|
+
environmentId,
|
|
940
949
|
packageName,
|
|
941
950
|
);
|
|
942
951
|
|
|
@@ -954,7 +963,7 @@ export class MaterializationService {
|
|
|
954
963
|
const gcResult = await dropManifestEntries(staleEntries, {
|
|
955
964
|
connections,
|
|
956
965
|
manifestService: this.manifestService,
|
|
957
|
-
|
|
966
|
+
environmentId,
|
|
958
967
|
liveTables,
|
|
959
968
|
});
|
|
960
969
|
|
|
@@ -970,7 +979,7 @@ export class MaterializationService {
|
|
|
970
979
|
|
|
971
980
|
// ==================== HELPERS ====================
|
|
972
981
|
|
|
973
|
-
private
|
|
974
|
-
return
|
|
982
|
+
private resolveEnvironmentId(environmentName: string): Promise<string> {
|
|
983
|
+
return resolveEnvironmentId(this.repository, environmentName);
|
|
975
984
|
}
|
|
976
985
|
}
|
|
@@ -9,7 +9,7 @@ import { dropManifestEntries, liveTableKey } from "./materialized_table_gc";
|
|
|
9
9
|
function makeEntry(overrides: Partial<ManifestEntry> = {}): ManifestEntry {
|
|
10
10
|
return {
|
|
11
11
|
id: "entry-1",
|
|
12
|
-
|
|
12
|
+
environmentId: "proj-1",
|
|
13
13
|
packageName: "pkg",
|
|
14
14
|
buildId: "abcdef1234567890abcdef1234567890",
|
|
15
15
|
tableName: "my_table",
|
|
@@ -67,7 +67,7 @@ describe("dropManifestEntries", () => {
|
|
|
67
67
|
const result = await dropManifestEntries([entry], {
|
|
68
68
|
connections: ctx.connections,
|
|
69
69
|
manifestService: ctx.manifestService,
|
|
70
|
-
|
|
70
|
+
environmentId: "proj-1",
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
expect(result.dropped).toHaveLength(1);
|
|
@@ -102,7 +102,7 @@ describe("dropManifestEntries", () => {
|
|
|
102
102
|
const result = await dropManifestEntries([entry], {
|
|
103
103
|
connections: ctx.connections,
|
|
104
104
|
manifestService: ctx.manifestService,
|
|
105
|
-
|
|
105
|
+
environmentId: "proj-1",
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
expect(result.dropped).toHaveLength(0);
|
|
@@ -122,7 +122,7 @@ describe("dropManifestEntries", () => {
|
|
|
122
122
|
const result = await dropManifestEntries([entry], {
|
|
123
123
|
connections: ctx.connections,
|
|
124
124
|
manifestService: ctx.manifestService,
|
|
125
|
-
|
|
125
|
+
environmentId: "proj-1",
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
// Manifest row is gone → entry is authoritatively dropped. The
|
|
@@ -146,7 +146,7 @@ describe("dropManifestEntries", () => {
|
|
|
146
146
|
const result = await dropManifestEntries([entry], {
|
|
147
147
|
connections: ctx.connections,
|
|
148
148
|
manifestService: ctx.manifestService,
|
|
149
|
-
|
|
149
|
+
environmentId: "proj-1",
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
expect(result.dropped).toHaveLength(1);
|
|
@@ -162,7 +162,7 @@ describe("dropManifestEntries", () => {
|
|
|
162
162
|
const result = await dropManifestEntries([entry], {
|
|
163
163
|
connections: ctx.connections,
|
|
164
164
|
manifestService: ctx.manifestService,
|
|
165
|
-
|
|
165
|
+
environmentId: "proj-1",
|
|
166
166
|
});
|
|
167
167
|
|
|
168
168
|
expect(result.dropped).toHaveLength(0);
|
|
@@ -181,7 +181,7 @@ describe("dropManifestEntries", () => {
|
|
|
181
181
|
const result = await dropManifestEntries([entry], {
|
|
182
182
|
connections: ctx2.connections,
|
|
183
183
|
manifestService: ctx2.manifestService,
|
|
184
|
-
|
|
184
|
+
environmentId: "proj-1",
|
|
185
185
|
});
|
|
186
186
|
|
|
187
187
|
expect(result.dropped).toHaveLength(0);
|
|
@@ -199,7 +199,7 @@ describe("dropManifestEntries", () => {
|
|
|
199
199
|
const result = await dropManifestEntries(entries, {
|
|
200
200
|
connections: ctx.connections,
|
|
201
201
|
manifestService: ctx.manifestService,
|
|
202
|
-
|
|
202
|
+
environmentId: "proj-1",
|
|
203
203
|
dryRun: true,
|
|
204
204
|
});
|
|
205
205
|
|
|
@@ -222,7 +222,7 @@ describe("dropManifestEntries", () => {
|
|
|
222
222
|
const result = await dropManifestEntries([bad, good], {
|
|
223
223
|
connections: ctx.connections,
|
|
224
224
|
manifestService: ctx.manifestService,
|
|
225
|
-
|
|
225
|
+
environmentId: "proj-1",
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
expect(result.dropped).toHaveLength(1);
|
|
@@ -250,7 +250,7 @@ describe("dropManifestEntries", () => {
|
|
|
250
250
|
const result = await dropManifestEntries([staleEntry], {
|
|
251
251
|
connections: ctx.connections,
|
|
252
252
|
manifestService: ctx.manifestService,
|
|
253
|
-
|
|
253
|
+
environmentId: "proj-1",
|
|
254
254
|
liveTables: live,
|
|
255
255
|
});
|
|
256
256
|
|
|
@@ -280,7 +280,7 @@ describe("dropManifestEntries", () => {
|
|
|
280
280
|
const result = await dropManifestEntries([staleEntry], {
|
|
281
281
|
connections: ctx.connections,
|
|
282
282
|
manifestService: ctx.manifestService,
|
|
283
|
-
|
|
283
|
+
environmentId: "proj-1",
|
|
284
284
|
liveTables: live,
|
|
285
285
|
});
|
|
286
286
|
|
|
@@ -296,7 +296,7 @@ describe("dropManifestEntries", () => {
|
|
|
296
296
|
const result = await dropManifestEntries([staleEntry], {
|
|
297
297
|
connections: ctx.connections,
|
|
298
298
|
manifestService: ctx.manifestService,
|
|
299
|
-
|
|
299
|
+
environmentId: "proj-1",
|
|
300
300
|
dryRun: true,
|
|
301
301
|
liveTables: live,
|
|
302
302
|
});
|
|
@@ -317,7 +317,7 @@ describe("dropManifestEntries", () => {
|
|
|
317
317
|
const result = await dropManifestEntries([entry], {
|
|
318
318
|
connections: ctx.connections,
|
|
319
319
|
manifestService: ctx.manifestService,
|
|
320
|
-
|
|
320
|
+
environmentId: "proj-1",
|
|
321
321
|
forceDeleteRowOnMissingConnection: true,
|
|
322
322
|
});
|
|
323
323
|
|
|
@@ -339,7 +339,7 @@ describe("dropManifestEntries", () => {
|
|
|
339
339
|
const result = await dropManifestEntries([entry], {
|
|
340
340
|
connections: ctx.connections,
|
|
341
341
|
manifestService: ctx.manifestService,
|
|
342
|
-
|
|
342
|
+
environmentId: "proj-1",
|
|
343
343
|
forceDeleteRowOnMissingConnection: true,
|
|
344
344
|
});
|
|
345
345
|
|
|
@@ -354,7 +354,7 @@ describe("dropManifestEntries", () => {
|
|
|
354
354
|
const result = await dropManifestEntries([entry], {
|
|
355
355
|
connections: ctx.connections,
|
|
356
356
|
manifestService: ctx.manifestService,
|
|
357
|
-
|
|
357
|
+
environmentId: "proj-1",
|
|
358
358
|
forceDeleteRowOnMissingConnection: true,
|
|
359
359
|
dryRun: true,
|
|
360
360
|
});
|
|
@@ -72,7 +72,7 @@ export interface GcResult {
|
|
|
72
72
|
export interface GcContext {
|
|
73
73
|
connections: Map<string, Connection>;
|
|
74
74
|
manifestService: ManifestService;
|
|
75
|
-
|
|
75
|
+
environmentId: string;
|
|
76
76
|
dryRun?: boolean;
|
|
77
77
|
/**
|
|
78
78
|
* Set of `liveTableKey(connectionName, tableName)` tuples that some
|
|
@@ -115,7 +115,7 @@ async function processOneEntry(
|
|
|
115
115
|
if (!connection) {
|
|
116
116
|
if (ctx.forceDeleteRowOnMissingConnection && !ctx.dryRun) {
|
|
117
117
|
try {
|
|
118
|
-
await ctx.manifestService.deleteEntry(ctx.
|
|
118
|
+
await ctx.manifestService.deleteEntry(ctx.environmentId, entry.id);
|
|
119
119
|
logger.warn(
|
|
120
120
|
"GC: deleted manifest row whose connection is gone; physical table (if any) is orphaned",
|
|
121
121
|
{
|
|
@@ -184,7 +184,7 @@ async function processOneEntry(
|
|
|
184
184
|
const quoted = (p: string) => quoteTablePath(p, dialect);
|
|
185
185
|
|
|
186
186
|
try {
|
|
187
|
-
await ctx.manifestService.deleteEntry(ctx.
|
|
187
|
+
await ctx.manifestService.deleteEntry(ctx.environmentId, entry.id);
|
|
188
188
|
} catch (err) {
|
|
189
189
|
const error = err instanceof Error ? err.message : String(err);
|
|
190
190
|
logger.warn("GC: failed to delete manifest row; skipping physical drop", {
|
package/src/service/model.ts
CHANGED
|
@@ -426,7 +426,7 @@ export class Model {
|
|
|
426
426
|
logger.error("Query parsing error", {
|
|
427
427
|
error,
|
|
428
428
|
errorMessage,
|
|
429
|
-
|
|
429
|
+
environmentName: this.packageName,
|
|
430
430
|
modelPath: this.modelPath,
|
|
431
431
|
query,
|
|
432
432
|
queryName,
|
|
@@ -466,7 +466,7 @@ export class Model {
|
|
|
466
466
|
logger.error("Query execution error", {
|
|
467
467
|
error,
|
|
468
468
|
errorMessage,
|
|
469
|
-
|
|
469
|
+
environmentName: this.packageName,
|
|
470
470
|
modelPath: this.modelPath,
|
|
471
471
|
query,
|
|
472
472
|
queryName,
|
|
@@ -316,7 +316,7 @@ describe("service/package", () => {
|
|
|
316
316
|
expect(models).toEqual([
|
|
317
317
|
{
|
|
318
318
|
// @ts-expect-error TODO: Fix missing projectName type in API
|
|
319
|
-
|
|
319
|
+
environmentName: "testProject",
|
|
320
320
|
packageName: "testPackage",
|
|
321
321
|
path: "model1.malloy",
|
|
322
322
|
error: undefined,
|
|
@@ -327,7 +327,7 @@ describe("service/package", () => {
|
|
|
327
327
|
expect(notebooks).toEqual([
|
|
328
328
|
{
|
|
329
329
|
// @ts-expect-error TODO: Fix missing projectName type in API
|
|
330
|
-
|
|
330
|
+
environmentName: "testProject",
|
|
331
331
|
packageName: "testPackage",
|
|
332
332
|
path: "model2.malloynb",
|
|
333
333
|
error: "This is the error",
|