@tiangong-lca/cli 0.0.24 → 0.0.26
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/README.md +66 -5
- package/dist/src/cli.js +484 -5
- package/dist/src/cli.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-alias-request.js +99 -0
- package/dist/src/lib/dataset-maintenance-alias-request.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-apply.js +12 -367
- package/dist/src/lib/dataset-maintenance-apply.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-protected-artifacts.js +100 -0
- package/dist/src/lib/dataset-maintenance-protected-artifacts.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-before.js +284 -0
- package/dist/src/lib/dataset-maintenance-protected-before.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-contract.js +918 -0
- package/dist/src/lib/dataset-maintenance-protected-contract.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-freeze.js +230 -0
- package/dist/src/lib/dataset-maintenance-protected-freeze.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-preparation.js +524 -0
- package/dist/src/lib/dataset-maintenance-protected-preparation.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-run.js +667 -0
- package/dist/src/lib/dataset-maintenance-protected-run.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-seal.js +160 -0
- package/dist/src/lib/dataset-maintenance-protected-seal.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-toolchain.js +86 -0
- package/dist/src/lib/dataset-maintenance-protected-toolchain.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-verify.js +435 -0
- package/dist/src/lib/dataset-maintenance-protected-verify.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-remote.js +116 -2
- package/dist/src/lib/dataset-maintenance-remote.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { CliError } from './errors.js';
|
|
2
|
+
import { isJsonObject, readJsonFile, resolveMaintenancePlanArtifactPath, sha256Json, } from './dataset-maintenance-contract.js';
|
|
3
|
+
export function loadMaintenanceDesiredPayload(planDir, action) {
|
|
4
|
+
if (!action.desired_payload) {
|
|
5
|
+
throw new CliError(`Maintenance action lacks desired payload: ${action.action_id}`, {
|
|
6
|
+
code: 'DATASET_MAINTENANCE_PLAN_INVALID',
|
|
7
|
+
exitCode: 2,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
const payloadPath = resolveMaintenancePlanArtifactPath(planDir, action.desired_payload.path, 'Maintenance desired payload path');
|
|
11
|
+
const payload = readJsonFile(payloadPath, 'Maintenance desired payload');
|
|
12
|
+
if (!isJsonObject(payload) || sha256Json(payload) !== action.desired_payload.sha256) {
|
|
13
|
+
throw new CliError(`Desired payload hash mismatch for action ${action.action_id}.`, {
|
|
14
|
+
code: 'DATASET_MAINTENANCE_DESIRED_PAYLOAD_HASH_MISMATCH',
|
|
15
|
+
exitCode: 1,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return payload;
|
|
19
|
+
}
|
|
20
|
+
export function orderedAliasBatches(plan) {
|
|
21
|
+
const time = plan.alias_batches?.find((batch) => batch.dimension === 'time');
|
|
22
|
+
const lengthTime = plan.alias_batches?.find((batch) => batch.dimension === 'length_time');
|
|
23
|
+
return [time, lengthTime].filter((batch) => batch !== undefined);
|
|
24
|
+
}
|
|
25
|
+
export function buildAliasBatchRequest(options) {
|
|
26
|
+
if (options.plan.target_mode !== 'owner_draft') {
|
|
27
|
+
throw new CliError('Alias batch request requires target_mode=owner_draft.', {
|
|
28
|
+
code: 'DATASET_MAINTENANCE_TARGET_MODE_INVALID',
|
|
29
|
+
exitCode: 2,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const targetSnapshot = (snapshot) => ({
|
|
33
|
+
id: snapshot.id,
|
|
34
|
+
version: snapshot.version,
|
|
35
|
+
expected_modified_at: snapshot.modified_at,
|
|
36
|
+
expected_json_ordered: snapshot.json_ordered,
|
|
37
|
+
});
|
|
38
|
+
const actions = options.batch.action_ids.map((actionId) => {
|
|
39
|
+
const action = options.plan.actions.find((entry) => entry.action_id === actionId);
|
|
40
|
+
if (!action?.before || !action.alias_mutation) {
|
|
41
|
+
throw new CliError(`Alias action is incomplete: ${actionId}`, {
|
|
42
|
+
code: 'DATASET_MAINTENANCE_ALIAS_PLAN_INVALID',
|
|
43
|
+
exitCode: 2,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
action_id: action.action_id,
|
|
48
|
+
action: 'update_json_ordered',
|
|
49
|
+
table: action.table,
|
|
50
|
+
id: action.id,
|
|
51
|
+
version: action.version,
|
|
52
|
+
expected_state_code: 0,
|
|
53
|
+
expected_modified_at: action.before.modified_at,
|
|
54
|
+
expected_json_ordered: action.before.json_ordered,
|
|
55
|
+
desired_json_ordered: loadMaintenanceDesiredPayload(options.planDir, action),
|
|
56
|
+
mutation: action.alias_mutation,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
schema_version: 'dataset-alias-batch.v1',
|
|
61
|
+
target_visibility: 'owner_draft',
|
|
62
|
+
plan_sha256: options.plan.plan_sha256,
|
|
63
|
+
operation_id: options.plan.operation_id,
|
|
64
|
+
batch_id: options.batch.batch_id,
|
|
65
|
+
dimension: options.batch.dimension,
|
|
66
|
+
factor: options.batch.factor,
|
|
67
|
+
target: {
|
|
68
|
+
flowproperty: targetSnapshot(options.batch.target_snapshots.flowproperty),
|
|
69
|
+
unitgroup: targetSnapshot(options.batch.target_snapshots.unitgroup),
|
|
70
|
+
source_unitgroup: targetSnapshot(options.batch.target_snapshots.source_unitgroup),
|
|
71
|
+
},
|
|
72
|
+
actions,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function buildAliasPlanRequest(options) {
|
|
76
|
+
if (options.plan.target_mode !== 'owner_draft') {
|
|
77
|
+
throw new CliError('Alias plan request requires target_mode=owner_draft.', {
|
|
78
|
+
code: 'DATASET_MAINTENANCE_TARGET_MODE_INVALID',
|
|
79
|
+
exitCode: 2,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const batches = orderedAliasBatches(options.plan);
|
|
83
|
+
if (batches.length !== 2 ||
|
|
84
|
+
batches[0]?.dimension !== 'time' ||
|
|
85
|
+
batches[1]?.dimension !== 'length_time') {
|
|
86
|
+
throw new CliError('Alias plan request requires time followed by length_time exactly once.', {
|
|
87
|
+
code: 'DATASET_MAINTENANCE_ALIAS_PLAN_INVALID',
|
|
88
|
+
exitCode: 2,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
schema_version: 'dataset-alias-plan.v1',
|
|
93
|
+
plan_sha256: options.plan.plan_sha256,
|
|
94
|
+
operation_id: options.plan.operation_id,
|
|
95
|
+
target_visibility: 'owner_draft',
|
|
96
|
+
batches: batches.map((batch) => buildAliasBatchRequest({ plan: options.plan, batch, planDir: options.planDir })),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=dataset-maintenance-alias-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-maintenance-alias-request.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-alias-request.ts"],"names":[],"mappings":"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","sourcesContent":["import { CliError } from './errors.js';\nimport {\n isJsonObject,\n readJsonFile,\n resolveMaintenancePlanArtifactPath,\n sha256Json,\n type DatasetMaintenanceAliasBatchPlan,\n type DatasetMaintenancePlan,\n type DatasetMaintenancePlanAction,\n type JsonObject,\n} from './dataset-maintenance-contract.js';\n\nexport function loadMaintenanceDesiredPayload(\n planDir: string,\n action: DatasetMaintenancePlanAction,\n): JsonObject {\n if (!action.desired_payload) {\n throw new CliError(`Maintenance action lacks desired payload: ${action.action_id}`, {\n code: 'DATASET_MAINTENANCE_PLAN_INVALID',\n exitCode: 2,\n });\n }\n const payloadPath = resolveMaintenancePlanArtifactPath(\n planDir,\n action.desired_payload.path,\n 'Maintenance desired payload path',\n );\n const payload = readJsonFile(payloadPath, 'Maintenance desired payload');\n if (!isJsonObject(payload) || sha256Json(payload) !== action.desired_payload.sha256) {\n throw new CliError(`Desired payload hash mismatch for action ${action.action_id}.`, {\n code: 'DATASET_MAINTENANCE_DESIRED_PAYLOAD_HASH_MISMATCH',\n exitCode: 1,\n });\n }\n return payload;\n}\n\nexport function orderedAliasBatches(\n plan: DatasetMaintenancePlan,\n): DatasetMaintenanceAliasBatchPlan[] {\n const time = plan.alias_batches?.find((batch) => batch.dimension === 'time');\n const lengthTime = plan.alias_batches?.find((batch) => batch.dimension === 'length_time');\n return [time, lengthTime].filter(\n (batch): batch is DatasetMaintenanceAliasBatchPlan => batch !== undefined,\n );\n}\n\nexport function buildAliasBatchRequest(options: {\n plan: DatasetMaintenancePlan;\n batch: DatasetMaintenanceAliasBatchPlan;\n planDir: string;\n}): JsonObject {\n if (options.plan.target_mode !== 'owner_draft') {\n throw new CliError('Alias batch request requires target_mode=owner_draft.', {\n code: 'DATASET_MAINTENANCE_TARGET_MODE_INVALID',\n exitCode: 2,\n });\n }\n const targetSnapshot = (\n snapshot: NonNullable<DatasetMaintenanceAliasBatchPlan['target_snapshots']['unitgroup']>,\n ): JsonObject => ({\n id: snapshot.id,\n version: snapshot.version,\n expected_modified_at: snapshot.modified_at!,\n expected_json_ordered: snapshot.json_ordered!,\n });\n const actions = options.batch.action_ids.map((actionId) => {\n const action = options.plan.actions.find((entry) => entry.action_id === actionId);\n if (!action?.before || !action.alias_mutation) {\n throw new CliError(`Alias action is incomplete: ${actionId}`, {\n code: 'DATASET_MAINTENANCE_ALIAS_PLAN_INVALID',\n exitCode: 2,\n });\n }\n return {\n action_id: action.action_id,\n action: 'update_json_ordered',\n table: action.table,\n id: action.id,\n version: action.version,\n expected_state_code: 0,\n expected_modified_at: action.before.modified_at!,\n expected_json_ordered: action.before.json_ordered!,\n desired_json_ordered: loadMaintenanceDesiredPayload(options.planDir, action),\n mutation: action.alias_mutation,\n };\n });\n return {\n schema_version: 'dataset-alias-batch.v1',\n target_visibility: 'owner_draft',\n plan_sha256: options.plan.plan_sha256,\n operation_id: options.plan.operation_id,\n batch_id: options.batch.batch_id,\n dimension: options.batch.dimension,\n factor: options.batch.factor,\n target: {\n flowproperty: targetSnapshot(options.batch.target_snapshots.flowproperty!),\n unitgroup: targetSnapshot(options.batch.target_snapshots.unitgroup!),\n source_unitgroup: targetSnapshot(options.batch.target_snapshots.source_unitgroup!),\n },\n actions,\n };\n}\n\nexport function buildAliasPlanRequest(options: {\n plan: DatasetMaintenancePlan;\n planDir: string;\n}): JsonObject {\n if (options.plan.target_mode !== 'owner_draft') {\n throw new CliError('Alias plan request requires target_mode=owner_draft.', {\n code: 'DATASET_MAINTENANCE_TARGET_MODE_INVALID',\n exitCode: 2,\n });\n }\n const batches = orderedAliasBatches(options.plan);\n if (\n batches.length !== 2 ||\n batches[0]?.dimension !== 'time' ||\n batches[1]?.dimension !== 'length_time'\n ) {\n throw new CliError('Alias plan request requires time followed by length_time exactly once.', {\n code: 'DATASET_MAINTENANCE_ALIAS_PLAN_INVALID',\n exitCode: 2,\n });\n }\n return {\n schema_version: 'dataset-alias-plan.v1',\n plan_sha256: options.plan.plan_sha256,\n operation_id: options.plan.operation_id,\n target_visibility: 'owner_draft',\n batches: batches.map((batch) =>\n buildAliasBatchRequest({ plan: options.plan, batch, planDir: options.planDir }),\n ),\n };\n}\n"]}
|
|
@@ -3,7 +3,8 @@ import path from 'node:path';
|
|
|
3
3
|
import { writeJsonArtifact } from './artifacts.js';
|
|
4
4
|
import { CliError } from './errors.js';
|
|
5
5
|
import { withStateFileLock } from './state-lock.js';
|
|
6
|
-
import {
|
|
6
|
+
import { buildAliasBatchRequest, buildAliasPlanRequest, loadMaintenanceDesiredPayload, orderedAliasBatches, } from './dataset-maintenance-alias-request.js';
|
|
7
|
+
import { MAINTENANCE_SCAN_TABLES, appendStableJsonLine, isJsonObject, maintenanceRowKey, parseMaintenancePlan, readJsonFile, readJsonLinesIfPresent, sha256Json, snapshotRemoteRow, writeImmutableJson, } from './dataset-maintenance-contract.js';
|
|
7
8
|
import { buildDerivativePlanRequest, derivativePlanAction, parseDerivativeSnapshotResponse, parseDerivativeSubmitResponse, } from './dataset-maintenance-derivatives.js';
|
|
8
9
|
import { maintenanceProjectedReferenceFingerprint } from './dataset-maintenance-plan.js';
|
|
9
10
|
import { isSnapshotCompletenessCompatible } from './dataset-maintenance-pagination.js';
|
|
@@ -16,21 +17,7 @@ function errorMessage(error) {
|
|
|
16
17
|
return error instanceof Error ? error.message : String(error);
|
|
17
18
|
}
|
|
18
19
|
function loadDesiredPayload(planDir, action) {
|
|
19
|
-
|
|
20
|
-
throw new CliError(`save_draft action lacks desired payload: ${action.action_id}`, {
|
|
21
|
-
code: 'DATASET_MAINTENANCE_PLAN_INVALID',
|
|
22
|
-
exitCode: 2,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
const payloadPath = resolveMaintenancePlanArtifactPath(planDir, action.desired_payload.path, 'Maintenance desired payload path');
|
|
26
|
-
const payload = readJsonFile(payloadPath, 'Maintenance desired payload');
|
|
27
|
-
if (!isJsonObject(payload) || sha256Json(payload) !== action.desired_payload.sha256) {
|
|
28
|
-
throw new CliError(`Desired payload hash mismatch for action ${action.action_id}.`, {
|
|
29
|
-
code: 'DATASET_MAINTENANCE_DESIRED_PAYLOAD_HASH_MISMATCH',
|
|
30
|
-
exitCode: 1,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
return payload;
|
|
20
|
+
return loadMaintenanceDesiredPayload(planDir, action);
|
|
34
21
|
}
|
|
35
22
|
function parseProgress(plan, progressPath) {
|
|
36
23
|
const rawEntries = readJsonLinesIfPresent(progressPath);
|
|
@@ -526,81 +513,6 @@ async function assertAliasSupportSnapshots(options) {
|
|
|
526
513
|
}
|
|
527
514
|
}
|
|
528
515
|
}
|
|
529
|
-
function buildAliasBatchRequest(options) {
|
|
530
|
-
if (options.plan.target_mode !== 'owner_draft') {
|
|
531
|
-
throw new CliError('Alias batch request requires target_mode=owner_draft.', {
|
|
532
|
-
code: 'DATASET_MAINTENANCE_TARGET_MODE_INVALID',
|
|
533
|
-
exitCode: 2,
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
const targetSnapshot = (snapshot) => {
|
|
537
|
-
return {
|
|
538
|
-
id: snapshot.id,
|
|
539
|
-
version: snapshot.version,
|
|
540
|
-
expected_modified_at: snapshot.modified_at,
|
|
541
|
-
expected_json_ordered: snapshot.json_ordered,
|
|
542
|
-
};
|
|
543
|
-
};
|
|
544
|
-
const actions = options.batch.action_ids.map((actionId) => {
|
|
545
|
-
const action = options.plan.actions.find((entry) => entry.action_id === actionId);
|
|
546
|
-
return {
|
|
547
|
-
action_id: action.action_id,
|
|
548
|
-
action: 'update_json_ordered',
|
|
549
|
-
table: action.table,
|
|
550
|
-
id: action.id,
|
|
551
|
-
version: action.version,
|
|
552
|
-
expected_state_code: 0,
|
|
553
|
-
expected_modified_at: action.before.modified_at,
|
|
554
|
-
expected_json_ordered: action.before.json_ordered,
|
|
555
|
-
desired_json_ordered: loadDesiredPayload(options.planDir, action),
|
|
556
|
-
mutation: action.alias_mutation,
|
|
557
|
-
};
|
|
558
|
-
});
|
|
559
|
-
return {
|
|
560
|
-
schema_version: 'dataset-alias-batch.v1',
|
|
561
|
-
target_visibility: 'owner_draft',
|
|
562
|
-
plan_sha256: options.plan.plan_sha256,
|
|
563
|
-
operation_id: options.plan.operation_id,
|
|
564
|
-
batch_id: options.batch.batch_id,
|
|
565
|
-
dimension: options.batch.dimension,
|
|
566
|
-
factor: options.batch.factor,
|
|
567
|
-
target: {
|
|
568
|
-
flowproperty: targetSnapshot(options.batch.target_snapshots.flowproperty),
|
|
569
|
-
unitgroup: targetSnapshot(options.batch.target_snapshots.unitgroup),
|
|
570
|
-
source_unitgroup: targetSnapshot(options.batch.target_snapshots.source_unitgroup),
|
|
571
|
-
},
|
|
572
|
-
actions,
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
function orderedAliasBatches(plan) {
|
|
576
|
-
const time = plan.alias_batches.find((batch) => batch.dimension === 'time');
|
|
577
|
-
const lengthTime = plan.alias_batches.find((batch) => batch.dimension === 'length_time');
|
|
578
|
-
return [time, lengthTime].filter((batch) => batch !== undefined);
|
|
579
|
-
}
|
|
580
|
-
function buildAliasPlanRequest(options) {
|
|
581
|
-
if (options.plan.target_mode !== 'owner_draft') {
|
|
582
|
-
throw new CliError('Alias plan request requires target_mode=owner_draft.', {
|
|
583
|
-
code: 'DATASET_MAINTENANCE_TARGET_MODE_INVALID',
|
|
584
|
-
exitCode: 2,
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
const batches = orderedAliasBatches(options.plan);
|
|
588
|
-
if (batches.length !== 2 ||
|
|
589
|
-
batches[0]?.dimension !== 'time' ||
|
|
590
|
-
batches[1]?.dimension !== 'length_time') {
|
|
591
|
-
throw new CliError('Alias plan request requires time followed by length_time exactly once.', {
|
|
592
|
-
code: 'DATASET_MAINTENANCE_ALIAS_PLAN_INVALID',
|
|
593
|
-
exitCode: 2,
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
return {
|
|
597
|
-
schema_version: 'dataset-alias-plan.v1',
|
|
598
|
-
plan_sha256: options.plan.plan_sha256,
|
|
599
|
-
operation_id: options.plan.operation_id,
|
|
600
|
-
target_visibility: 'owner_draft',
|
|
601
|
-
batches: batches.map((batch) => buildAliasBatchRequest({ plan: options.plan, batch, planDir: options.planDir })),
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
516
|
function validateAliasRpcResult(value, batch, plan) {
|
|
605
517
|
const audit = Array.isArray(value.audit) ? value.audit : [];
|
|
606
518
|
const proofs = audit.filter(isJsonObject).map((entry) => ({
|
|
@@ -751,106 +663,6 @@ async function executeAliasPlan(options) {
|
|
|
751
663
|
function aliasExchangeProgressKey(value) {
|
|
752
664
|
return `${value.batch_id}\u0000${value.action_id}\u0000${value.exchange_index}\u0000${value.data_set_internal_id}`;
|
|
753
665
|
}
|
|
754
|
-
function aliasBatchDerivedLogsComplete(options) {
|
|
755
|
-
const planBatchProof = options.planSuccess.batches.find((proof) => proof.batch_id === options.batch.batch_id);
|
|
756
|
-
if (!planBatchProof ||
|
|
757
|
-
planBatchProof.dimension !== options.batch.dimension ||
|
|
758
|
-
planBatchProof.batch_request_sha256 !== options.batchSuccess.batch_request_sha256 ||
|
|
759
|
-
planBatchProof.summary_audit_id !== options.batchSuccess.summary_audit_id ||
|
|
760
|
-
options.batchSuccess.plan_request_sha256 !== options.planSuccess.plan_request_sha256 ||
|
|
761
|
-
options.batchSuccess.plan_summary_audit_id !== options.planSuccess.summary_audit_id ||
|
|
762
|
-
!options.batch.action_ids.every((actionId) => options.progress.successes.get(actionId)?.batch_request_sha256 ===
|
|
763
|
-
options.batchSuccess.batch_request_sha256 &&
|
|
764
|
-
options.progress.successes.get(actionId)?.summary_audit_id ===
|
|
765
|
-
options.batchSuccess.summary_audit_id &&
|
|
766
|
-
options.progress.successes.get(actionId)?.plan_request_sha256 ===
|
|
767
|
-
options.planSuccess.plan_request_sha256 &&
|
|
768
|
-
options.progress.successes.get(actionId)?.plan_summary_audit_id ===
|
|
769
|
-
options.planSuccess.summary_audit_id)) {
|
|
770
|
-
return false;
|
|
771
|
-
}
|
|
772
|
-
const expected = new Map(options.batch.exchange_rewrites.map((rewrite) => [
|
|
773
|
-
aliasExchangeProgressKey({ batch_id: options.batch.batch_id, ...rewrite }),
|
|
774
|
-
rewrite,
|
|
775
|
-
]));
|
|
776
|
-
const exchangeKeys = new Set();
|
|
777
|
-
for (const value of readJsonLinesIfPresent(options.exchangeProgressPath)) {
|
|
778
|
-
if (!isJsonObject(value) || value.batch_id !== options.batch.batch_id)
|
|
779
|
-
continue;
|
|
780
|
-
const key = typeof value.action_id === 'string' &&
|
|
781
|
-
typeof value.exchange_index === 'number' &&
|
|
782
|
-
typeof value.data_set_internal_id === 'string'
|
|
783
|
-
? aliasExchangeProgressKey({
|
|
784
|
-
batch_id: options.batch.batch_id,
|
|
785
|
-
action_id: value.action_id,
|
|
786
|
-
exchange_index: value.exchange_index,
|
|
787
|
-
data_set_internal_id: value.data_set_internal_id,
|
|
788
|
-
})
|
|
789
|
-
: '';
|
|
790
|
-
const rewrite = expected.get(key);
|
|
791
|
-
const rowProof = rewrite ? options.progress.successes.get(rewrite.action_id) : null;
|
|
792
|
-
if (!rewrite ||
|
|
793
|
-
!rowProof ||
|
|
794
|
-
value.schema_version !== 1 ||
|
|
795
|
-
value.plan_sha256 !== options.plan.plan_sha256 ||
|
|
796
|
-
value.operation_id !== options.plan.operation_id ||
|
|
797
|
-
value.target_mode !== 'owner_draft' ||
|
|
798
|
-
value.batch_request_sha256 !== options.batchSuccess.batch_request_sha256 ||
|
|
799
|
-
value.batch_request_sha256 !== rowProof.batch_request_sha256 ||
|
|
800
|
-
value.summary_audit_id !== options.batchSuccess.summary_audit_id ||
|
|
801
|
-
value.summary_audit_id !== rowProof.summary_audit_id ||
|
|
802
|
-
value.plan_request_sha256 !== options.planSuccess.plan_request_sha256 ||
|
|
803
|
-
value.plan_request_sha256 !== rowProof.plan_request_sha256 ||
|
|
804
|
-
value.plan_summary_audit_id !== options.planSuccess.summary_audit_id ||
|
|
805
|
-
value.plan_summary_audit_id !== rowProof.plan_summary_audit_id ||
|
|
806
|
-
value.factor !== options.batch.factor ||
|
|
807
|
-
value.result !== 'success' ||
|
|
808
|
-
!isJsonObject(value.actor) ||
|
|
809
|
-
value.actor.user_id !== options.plan.account.user_id ||
|
|
810
|
-
value.actor.email !== options.plan.account.email ||
|
|
811
|
-
typeof value.logged_at_utc !== 'string' ||
|
|
812
|
-
typeof value.database_audit_id !== 'string' ||
|
|
813
|
-
!POSITIVE_INTEGER_TEXT.test(value.database_audit_id) ||
|
|
814
|
-
value.database_audit_id !== rowProof.database_audit_id ||
|
|
815
|
-
typeof value.summary_audit_id !== 'string' ||
|
|
816
|
-
!POSITIVE_INTEGER_TEXT.test(value.summary_audit_id) ||
|
|
817
|
-
sha256Json({
|
|
818
|
-
action_id: value.action_id,
|
|
819
|
-
process_id: value.process_id,
|
|
820
|
-
process_version: value.process_version,
|
|
821
|
-
exchange_index: value.exchange_index,
|
|
822
|
-
data_set_internal_id: value.data_set_internal_id,
|
|
823
|
-
flow_id: value.flow_id,
|
|
824
|
-
flow_version: value.flow_version,
|
|
825
|
-
direction: value.direction,
|
|
826
|
-
before_exchange_sha256: value.before_exchange_sha256,
|
|
827
|
-
before_mean_amount: value.before_mean_amount,
|
|
828
|
-
before_resulting_amount: value.before_resulting_amount,
|
|
829
|
-
after_mean_amount: value.after_mean_amount,
|
|
830
|
-
after_resulting_amount: value.after_resulting_amount,
|
|
831
|
-
after_exchange_sha256: value.after_exchange_sha256,
|
|
832
|
-
}) !== sha256Json(rewrite) ||
|
|
833
|
-
exchangeKeys.has(key)) {
|
|
834
|
-
return false;
|
|
835
|
-
}
|
|
836
|
-
exchangeKeys.add(key);
|
|
837
|
-
}
|
|
838
|
-
return options.batch.exchange_rewrites.every((rewrite) => exchangeKeys.has(aliasExchangeProgressKey({ batch_id: options.batch.batch_id, ...rewrite })));
|
|
839
|
-
}
|
|
840
|
-
function aliasPlanDerivedLogsComplete(options) {
|
|
841
|
-
return orderedAliasBatches(options.plan).every((batch) => {
|
|
842
|
-
const batchSuccess = options.batchProgress.successes.get(batch.batch_id);
|
|
843
|
-
return Boolean(batchSuccess &&
|
|
844
|
-
aliasBatchDerivedLogsComplete({
|
|
845
|
-
plan: options.plan,
|
|
846
|
-
batch,
|
|
847
|
-
planSuccess: options.planSuccess,
|
|
848
|
-
batchSuccess,
|
|
849
|
-
progress: options.progress,
|
|
850
|
-
exchangeProgressPath: options.exchangeProgressPath,
|
|
851
|
-
}));
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
666
|
function appendAliasSuccessLogs(options) {
|
|
855
667
|
const batchRpc = options.execution.rpc.batches.get(options.batch.dimension);
|
|
856
668
|
for (const actionId of options.batch.action_ids) {
|
|
@@ -1105,32 +917,6 @@ function appendAliasProofProgress(options) {
|
|
|
1105
917
|
options.planProgress.latestFailure = null;
|
|
1106
918
|
return entry;
|
|
1107
919
|
}
|
|
1108
|
-
function appendAliasPlanFailure(options) {
|
|
1109
|
-
const entry = {
|
|
1110
|
-
schema_version: 1,
|
|
1111
|
-
plan_sha256: options.plan.plan_sha256,
|
|
1112
|
-
operation_id: options.plan.operation_id,
|
|
1113
|
-
target_mode: 'owner_draft',
|
|
1114
|
-
actor: { user_id: options.context.account.user_id, email: options.context.account.email },
|
|
1115
|
-
started_at_utc: options.startedAt,
|
|
1116
|
-
ended_at_utc: options.endedAt,
|
|
1117
|
-
plan_request_sha256: null,
|
|
1118
|
-
idempotent_replay: null,
|
|
1119
|
-
batch_count: 2,
|
|
1120
|
-
row_count: 52,
|
|
1121
|
-
exchange_count: 59,
|
|
1122
|
-
summary_audit_id: null,
|
|
1123
|
-
batches: [],
|
|
1124
|
-
result: 'failed',
|
|
1125
|
-
error: errorMessage(options.error),
|
|
1126
|
-
};
|
|
1127
|
-
appendStableJsonLine(options.progressPath, entry);
|
|
1128
|
-
options.planProgress.entries.push(entry);
|
|
1129
|
-
if (!options.planProgress.success) {
|
|
1130
|
-
options.planProgress.latestFailure = entry;
|
|
1131
|
-
}
|
|
1132
|
-
return entry;
|
|
1133
|
-
}
|
|
1134
920
|
async function executeAction(options) {
|
|
1135
921
|
if (options.action.action === 'rebuild_derivatives') {
|
|
1136
922
|
throw new CliError('Derivative rebuild actions may only execute through the guarded whole-plan RPC.', {
|
|
@@ -1324,6 +1110,12 @@ export async function runDatasetMaintenanceApply(options) {
|
|
|
1324
1110
|
details: plan.blockers,
|
|
1325
1111
|
});
|
|
1326
1112
|
}
|
|
1113
|
+
if (plan.operation === 'merge-support-aliases') {
|
|
1114
|
+
throw new CliError('merge-support-aliases is sealed for dataset maintenance run-protected and cannot use ordinary apply.', {
|
|
1115
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_RUN_REQUIRED',
|
|
1116
|
+
exitCode: 1,
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1327
1119
|
if (plan.operation === 'redo-import' &&
|
|
1328
1120
|
!plan.source_import_run_id &&
|
|
1329
1121
|
plan.source_lineage === null) {
|
|
@@ -1335,9 +1127,6 @@ export async function runDatasetMaintenanceApply(options) {
|
|
|
1335
1127
|
const progressPath = path.join(planDir, plan.operation === 'rebuild-derivatives'
|
|
1336
1128
|
? 'derivative-submit-progress.jsonl'
|
|
1337
1129
|
: 'apply-progress.jsonl');
|
|
1338
|
-
const aliasPlanProgressPath = path.join(planDir, 'alias-plan-progress.jsonl');
|
|
1339
|
-
const aliasBatchProgressPath = path.join(planDir, 'alias-batch-progress.jsonl');
|
|
1340
|
-
const aliasExchangeProgressPath = path.join(planDir, 'alias-exchange-progress.jsonl');
|
|
1341
1130
|
return withStateFileLock(progressPath, { reason: `dataset_maintenance_apply_${plan.operation_id}` }, async () => {
|
|
1342
1131
|
const context = await resolveMaintenanceRemoteContext({
|
|
1343
1132
|
env: options.env,
|
|
@@ -1364,13 +1153,7 @@ export async function runDatasetMaintenanceApply(options) {
|
|
|
1364
1153
|
const progress = plan.operation === 'rebuild-derivatives'
|
|
1365
1154
|
? { entries: [], successes: new Map(), latestFailures: new Map() }
|
|
1366
1155
|
: parseProgress(plan, progressPath);
|
|
1367
|
-
|
|
1368
|
-
const aliasPlanProgress = plan.operation === 'merge-support-aliases'
|
|
1369
|
-
? parseAliasPlanProgress(plan, aliasPlanProgressPath)
|
|
1370
|
-
: { entries: [], success: null, latestFailure: null };
|
|
1371
|
-
const aliasBatchProgress = plan.operation === 'merge-support-aliases'
|
|
1372
|
-
? parseAliasBatchProgress(plan, aliasBatchProgressPath)
|
|
1373
|
-
: { entries: [], successes: new Map() };
|
|
1156
|
+
const resumedSuccesses = progress.successes.size;
|
|
1374
1157
|
const current = await fetchMaintenanceAccountRows({
|
|
1375
1158
|
context,
|
|
1376
1159
|
userId: plan.account.user_id,
|
|
@@ -1380,11 +1163,8 @@ export async function runDatasetMaintenanceApply(options) {
|
|
|
1380
1163
|
planDir,
|
|
1381
1164
|
currentRows: current.rows,
|
|
1382
1165
|
progress,
|
|
1383
|
-
aliasPlanProgress,
|
|
1166
|
+
aliasPlanProgress: { entries: [], success: null, latestFailure: null },
|
|
1384
1167
|
});
|
|
1385
|
-
if (plan.operation === 'merge-support-aliases') {
|
|
1386
|
-
await assertAliasSupportSnapshots({ plan, context });
|
|
1387
|
-
}
|
|
1388
1168
|
const approvalPath = path.join(planDir, 'approval-record.json');
|
|
1389
1169
|
const approvalAlreadyExisted = existsSync(approvalPath);
|
|
1390
1170
|
validateApprovalRecord({ path: approvalPath, plan, context });
|
|
@@ -1504,140 +1284,6 @@ export async function runDatasetMaintenanceApply(options) {
|
|
|
1504
1284
|
writeJsonArtifact(report.artifacts.commit_report, report);
|
|
1505
1285
|
return report;
|
|
1506
1286
|
}
|
|
1507
|
-
if (plan.operation === 'merge-support-aliases') {
|
|
1508
|
-
const alreadyComplete = Boolean(aliasPlanProgress.success &&
|
|
1509
|
-
aliasPlanDerivedLogsComplete({
|
|
1510
|
-
plan,
|
|
1511
|
-
planSuccess: aliasPlanProgress.success,
|
|
1512
|
-
batchProgress: aliasBatchProgress,
|
|
1513
|
-
progress,
|
|
1514
|
-
exchangeProgressPath: aliasExchangeProgressPath,
|
|
1515
|
-
}));
|
|
1516
|
-
resumedSuccesses = alreadyComplete ? plan.actions.length : 0;
|
|
1517
|
-
let planSuccess = alreadyComplete ? aliasPlanProgress.success : null;
|
|
1518
|
-
let planFailure = null;
|
|
1519
|
-
if (!alreadyComplete) {
|
|
1520
|
-
const startedAt = clock(options);
|
|
1521
|
-
try {
|
|
1522
|
-
const execution = await executeAliasPlan({ plan, planDir, context });
|
|
1523
|
-
const endedAt = clock(options);
|
|
1524
|
-
for (const batch of orderedAliasBatches(plan)) {
|
|
1525
|
-
appendAliasSuccessLogs({
|
|
1526
|
-
plan,
|
|
1527
|
-
batch,
|
|
1528
|
-
execution,
|
|
1529
|
-
progress,
|
|
1530
|
-
progressPath,
|
|
1531
|
-
exchangeProgressPath: aliasExchangeProgressPath,
|
|
1532
|
-
context,
|
|
1533
|
-
startedAt,
|
|
1534
|
-
endedAt,
|
|
1535
|
-
});
|
|
1536
|
-
}
|
|
1537
|
-
planSuccess = appendAliasProofProgress({
|
|
1538
|
-
plan,
|
|
1539
|
-
execution,
|
|
1540
|
-
planProgress: aliasPlanProgress,
|
|
1541
|
-
batchProgress: aliasBatchProgress,
|
|
1542
|
-
planProgressPath: aliasPlanProgressPath,
|
|
1543
|
-
batchProgressPath: aliasBatchProgressPath,
|
|
1544
|
-
context,
|
|
1545
|
-
startedAt,
|
|
1546
|
-
endedAt,
|
|
1547
|
-
});
|
|
1548
|
-
}
|
|
1549
|
-
catch (error) {
|
|
1550
|
-
planFailure = appendAliasPlanFailure({
|
|
1551
|
-
plan,
|
|
1552
|
-
planProgress: aliasPlanProgress,
|
|
1553
|
-
progressPath: aliasPlanProgressPath,
|
|
1554
|
-
context,
|
|
1555
|
-
startedAt,
|
|
1556
|
-
endedAt: clock(options),
|
|
1557
|
-
error,
|
|
1558
|
-
});
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
const fullyProven = Boolean(planSuccess &&
|
|
1562
|
-
aliasPlanDerivedLogsComplete({
|
|
1563
|
-
plan,
|
|
1564
|
-
planSuccess,
|
|
1565
|
-
batchProgress: aliasBatchProgress,
|
|
1566
|
-
progress,
|
|
1567
|
-
exchangeProgressPath: aliasExchangeProgressPath,
|
|
1568
|
-
}));
|
|
1569
|
-
const failureError = planFailure?.error ?? 'Whole-plan proof is incomplete.';
|
|
1570
|
-
const actions = plan.actions.map((action) => {
|
|
1571
|
-
return {
|
|
1572
|
-
action_id: action.action_id,
|
|
1573
|
-
action: action.action,
|
|
1574
|
-
table: action.table,
|
|
1575
|
-
id: action.id,
|
|
1576
|
-
version: action.version,
|
|
1577
|
-
status: fullyProven ? 'success' : 'failed',
|
|
1578
|
-
error: fullyProven ? null : failureError,
|
|
1579
|
-
};
|
|
1580
|
-
});
|
|
1581
|
-
const successCount = fullyProven ? actions.length : 0;
|
|
1582
|
-
const failureCount = fullyProven ? 0 : actions.length;
|
|
1583
|
-
const attemptPath = nextAttemptPath(planDir);
|
|
1584
|
-
const report = {
|
|
1585
|
-
schema_version: 1,
|
|
1586
|
-
generated_at_utc: clock(options),
|
|
1587
|
-
status: successCount === actions.length ? 'completed' : 'completed_with_failures',
|
|
1588
|
-
task_id: plan.task_id,
|
|
1589
|
-
operation: plan.operation,
|
|
1590
|
-
operation_id: plan.operation_id,
|
|
1591
|
-
target_mode: plan.target_mode,
|
|
1592
|
-
plan_sha256: plan.plan_sha256,
|
|
1593
|
-
actor: { user_id: context.account.user_id, email: context.account.email },
|
|
1594
|
-
summary: {
|
|
1595
|
-
actions: actions.length,
|
|
1596
|
-
success: successCount,
|
|
1597
|
-
failed: failureCount,
|
|
1598
|
-
pending: actions.length - successCount - failureCount,
|
|
1599
|
-
resumed_successes: resumedSuccesses,
|
|
1600
|
-
},
|
|
1601
|
-
actions,
|
|
1602
|
-
artifacts: {
|
|
1603
|
-
approval_record: approvalPath,
|
|
1604
|
-
apply_progress: progressPath,
|
|
1605
|
-
commit_report: path.join(planDir, 'commit-report.json'),
|
|
1606
|
-
attempt_report: attemptPath,
|
|
1607
|
-
alias_plan_progress: aliasPlanProgressPath,
|
|
1608
|
-
alias_batch_progress: aliasBatchProgressPath,
|
|
1609
|
-
alias_exchange_progress: aliasExchangeProgressPath,
|
|
1610
|
-
},
|
|
1611
|
-
database_audit: {
|
|
1612
|
-
rpc_transaction_log: 'public.command_audit_log',
|
|
1613
|
-
source: 'tiangong-lca dataset maintenance apply',
|
|
1614
|
-
correlation_fields: [
|
|
1615
|
-
'plan_sha256',
|
|
1616
|
-
'operation_id',
|
|
1617
|
-
'target_visibility',
|
|
1618
|
-
'plan_request_sha256',
|
|
1619
|
-
'batch_id',
|
|
1620
|
-
'action_id',
|
|
1621
|
-
'batch_request_sha256',
|
|
1622
|
-
],
|
|
1623
|
-
},
|
|
1624
|
-
...(fullyProven && planSuccess
|
|
1625
|
-
? {
|
|
1626
|
-
alias_plan_proof: {
|
|
1627
|
-
plan_request_sha256: planSuccess.plan_request_sha256,
|
|
1628
|
-
summary_audit_id: planSuccess.summary_audit_id,
|
|
1629
|
-
batch_count: 2,
|
|
1630
|
-
row_count: 52,
|
|
1631
|
-
exchange_count: 59,
|
|
1632
|
-
idempotent_replay: planSuccess.idempotent_replay,
|
|
1633
|
-
},
|
|
1634
|
-
}
|
|
1635
|
-
: {}),
|
|
1636
|
-
};
|
|
1637
|
-
writeImmutableJson(attemptPath, report);
|
|
1638
|
-
writeJsonArtifact(report.artifacts.commit_report, report);
|
|
1639
|
-
return report;
|
|
1640
|
-
}
|
|
1641
1287
|
const ordered = [...plan.actions].sort((left, right) => {
|
|
1642
1288
|
const rank = {
|
|
1643
1289
|
save_draft: 0,
|
|
@@ -1777,10 +1423,9 @@ export async function runDatasetMaintenanceApply(options) {
|
|
|
1777
1423
|
});
|
|
1778
1424
|
}
|
|
1779
1425
|
export const __testInternals = {
|
|
1780
|
-
aliasBatchDerivedLogsComplete,
|
|
1781
|
-
aliasPlanDerivedLogsComplete,
|
|
1782
1426
|
aliasExchangeProgressKey,
|
|
1783
1427
|
appendAliasSuccessLogs,
|
|
1428
|
+
appendAliasProofProgress,
|
|
1784
1429
|
assertApplyPreconditions,
|
|
1785
1430
|
assertAliasSupportSnapshots,
|
|
1786
1431
|
buildAliasBatchRequest,
|