@proofhound/core 0.1.12 → 0.1.14
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/server/channels/mcp/dataset-import.tools.d.ts.map +1 -1
- package/dist/server/channels/mcp/dataset-import.tools.js +33 -0
- package/dist/server/channels/mcp/dataset-import.tools.js.map +1 -1
- package/dist/server/common/contracts/object-storage.provider.d.ts +2 -0
- package/dist/server/common/contracts/object-storage.provider.d.ts.map +1 -1
- package/dist/server/common/contracts/object-storage.provider.js +4 -0
- package/dist/server/common/contracts/object-storage.provider.js.map +1 -1
- package/dist/server/common/contracts/quota-policy.hook.d.ts +1 -1
- package/dist/server/common/contracts/quota-policy.hook.d.ts.map +1 -1
- package/dist/server/common/contracts/quota-policy.hook.js.map +1 -1
- package/dist/server/modules/annotation/annotation.controller.d.ts +3 -3
- package/dist/server/modules/annotation/annotation.module.d.ts.map +1 -1
- package/dist/server/modules/annotation/annotation.module.js +2 -1
- package/dist/server/modules/annotation/annotation.module.js.map +1 -1
- package/dist/server/modules/annotation/annotation.repository.d.ts +4 -1
- package/dist/server/modules/annotation/annotation.repository.d.ts.map +1 -1
- package/dist/server/modules/annotation/annotation.repository.js +31 -6
- package/dist/server/modules/annotation/annotation.repository.js.map +1 -1
- package/dist/server/modules/canary-release/canary-release.module.d.ts.map +1 -1
- package/dist/server/modules/canary-release/canary-release.module.js +2 -1
- package/dist/server/modules/canary-release/canary-release.module.js.map +1 -1
- package/dist/server/modules/canary-release/canary-release.repository.d.ts +4 -1
- package/dist/server/modules/canary-release/canary-release.repository.d.ts.map +1 -1
- package/dist/server/modules/canary-release/canary-release.repository.js +29 -4
- package/dist/server/modules/canary-release/canary-release.repository.js.map +1 -1
- package/dist/server/modules/dataset/dataset-import-raw-parser.d.ts +7 -0
- package/dist/server/modules/dataset/dataset-import-raw-parser.d.ts.map +1 -0
- package/dist/server/modules/dataset/dataset-import-raw-parser.js +104 -0
- package/dist/server/modules/dataset/dataset-import-raw-parser.js.map +1 -0
- package/dist/server/modules/dataset/dataset-import.controller.d.ts +31 -0
- package/dist/server/modules/dataset/dataset-import.controller.d.ts.map +1 -1
- package/dist/server/modules/dataset/dataset-import.controller.js +27 -0
- package/dist/server/modules/dataset/dataset-import.controller.js.map +1 -1
- package/dist/server/modules/dataset/dataset-import.repository.d.ts +15 -2
- package/dist/server/modules/dataset/dataset-import.repository.d.ts.map +1 -1
- package/dist/server/modules/dataset/dataset-import.repository.js +59 -12
- package/dist/server/modules/dataset/dataset-import.repository.js.map +1 -1
- package/dist/server/modules/dataset/dataset-import.service.d.ts +15 -2
- package/dist/server/modules/dataset/dataset-import.service.d.ts.map +1 -1
- package/dist/server/modules/dataset/dataset-import.service.js +196 -9
- package/dist/server/modules/dataset/dataset-import.service.js.map +1 -1
- package/dist/server/modules/dataset/dataset-sample-offload.d.ts +36 -0
- package/dist/server/modules/dataset/dataset-sample-offload.d.ts.map +1 -0
- package/dist/server/modules/dataset/dataset-sample-offload.js +41 -0
- package/dist/server/modules/dataset/dataset-sample-offload.js.map +1 -0
- package/dist/server/modules/dataset/dataset-sample-payload.d.ts +21 -0
- package/dist/server/modules/dataset/dataset-sample-payload.d.ts.map +1 -0
- package/dist/server/modules/dataset/dataset-sample-payload.js +72 -0
- package/dist/server/modules/dataset/dataset-sample-payload.js.map +1 -0
- package/dist/server/modules/dataset/dataset-sample-projection.d.ts +11 -0
- package/dist/server/modules/dataset/dataset-sample-projection.d.ts.map +1 -0
- package/dist/server/modules/dataset/dataset-sample-projection.js +49 -0
- package/dist/server/modules/dataset/dataset-sample-projection.js.map +1 -0
- package/dist/server/modules/dataset/dataset.module.d.ts.map +1 -1
- package/dist/server/modules/dataset/dataset.module.js +2 -0
- package/dist/server/modules/dataset/dataset.module.js.map +1 -1
- package/dist/server/modules/dataset/dataset.repository.d.ts +6 -1
- package/dist/server/modules/dataset/dataset.repository.d.ts.map +1 -1
- package/dist/server/modules/dataset/dataset.repository.js +59 -12
- package/dist/server/modules/dataset/dataset.repository.js.map +1 -1
- package/dist/server/modules/dataset/dataset.service.d.ts +2 -0
- package/dist/server/modules/dataset/dataset.service.d.ts.map +1 -1
- package/dist/server/modules/dataset/dataset.service.js +12 -0
- package/dist/server/modules/dataset/dataset.service.js.map +1 -1
- package/dist/server/modules/experiment/experiment.module.d.ts.map +1 -1
- package/dist/server/modules/experiment/experiment.module.js +2 -0
- package/dist/server/modules/experiment/experiment.module.js.map +1 -1
- package/dist/server/modules/experiment/experiment.workflow.d.ts +7 -1
- package/dist/server/modules/experiment/experiment.workflow.d.ts.map +1 -1
- package/dist/server/modules/experiment/experiment.workflow.js +33 -4
- package/dist/server/modules/experiment/experiment.workflow.js.map +1 -1
- package/dist/server/modules/optimization/optimization.module.d.ts.map +1 -1
- package/dist/server/modules/optimization/optimization.module.js +2 -0
- package/dist/server/modules/optimization/optimization.module.js.map +1 -1
- package/dist/server/modules/optimization/optimization.repository.d.ts +5 -1
- package/dist/server/modules/optimization/optimization.repository.d.ts.map +1 -1
- package/dist/server/modules/optimization/optimization.repository.js +30 -8
- package/dist/server/modules/optimization/optimization.repository.js.map +1 -1
- package/dist/server/modules/run-result/run-result-compaction-sweeper.d.ts +15 -0
- package/dist/server/modules/run-result/run-result-compaction-sweeper.d.ts.map +1 -0
- package/dist/server/modules/run-result/run-result-compaction-sweeper.js +74 -0
- package/dist/server/modules/run-result/run-result-compaction-sweeper.js.map +1 -0
- package/dist/server/modules/run-result/run-result-compaction.d.ts +38 -0
- package/dist/server/modules/run-result/run-result-compaction.d.ts.map +1 -0
- package/dist/server/modules/run-result/run-result-compaction.js +74 -0
- package/dist/server/modules/run-result/run-result-compaction.js.map +1 -0
- package/dist/server/modules/run-result/run-result-compactor.d.ts +58 -0
- package/dist/server/modules/run-result/run-result-compactor.d.ts.map +1 -0
- package/dist/server/modules/run-result/run-result-compactor.js +188 -0
- package/dist/server/modules/run-result/run-result-compactor.js.map +1 -0
- package/dist/server/modules/run-result/run-result-payload.d.ts +30 -0
- package/dist/server/modules/run-result/run-result-payload.d.ts.map +1 -0
- package/dist/server/modules/run-result/run-result-payload.js +82 -0
- package/dist/server/modules/run-result/run-result-payload.js.map +1 -0
- package/dist/server/modules/run-result/run-result-payload.reader.d.ts +20 -0
- package/dist/server/modules/run-result/run-result-payload.reader.d.ts.map +1 -0
- package/dist/server/modules/run-result/run-result-payload.reader.js +99 -0
- package/dist/server/modules/run-result/run-result-payload.reader.js.map +1 -0
- package/dist/server/modules/run-result/run-result.controller.d.ts +4 -0
- package/dist/server/modules/run-result/run-result.controller.d.ts.map +1 -1
- package/dist/server/modules/run-result/run-result.module.d.ts.map +1 -1
- package/dist/server/modules/run-result/run-result.module.js +14 -2
- package/dist/server/modules/run-result/run-result.module.js.map +1 -1
- package/dist/server/modules/run-result/run-result.repository.d.ts +3 -1
- package/dist/server/modules/run-result/run-result.repository.d.ts.map +1 -1
- package/dist/server/modules/run-result/run-result.repository.js +63 -4
- package/dist/server/modules/run-result/run-result.repository.js.map +1 -1
- package/package.json +14 -12
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RunResultCompactionSweeper = void 0;
|
|
13
|
+
// RunResultCompactionSweeper — periodic compaction for run-result sources with no finalize step.
|
|
14
|
+
//
|
|
15
|
+
// experiment / optimization compact at their workflow finalize. The remaining sources have no batch
|
|
16
|
+
// boundary, so a timer-driven sweep offloads their still-inline rows (SPEC 30 §9.3): `online`
|
|
17
|
+
// (production traffic) plus `canary` / `release` (their lane-scoped reads — canary annotations,
|
|
18
|
+
// release lists, details — all route through the reader seam, so offloading them is safe). A no-op
|
|
19
|
+
// when object storage is disabled, so an OSS deployment without storage keeps everything inline.
|
|
20
|
+
const common_1 = require("@nestjs/common");
|
|
21
|
+
const logger_1 = require("@proofhound/logger");
|
|
22
|
+
const run_result_compactor_1 = require("./run-result-compactor");
|
|
23
|
+
// optimization_analysis / optimization_generate offload only rendered_prompt + input_variables
|
|
24
|
+
// (their parsed_output / raw_response stay inline for reconstruct/reuse, SPEC 30 §9.4). Those two
|
|
25
|
+
// fields are read only by the detail view (seam-hydrated), so they are safe to sweep.
|
|
26
|
+
const SWEEP_SOURCES = ['online', 'canary', 'release', 'optimization_analysis', 'optimization_generate'];
|
|
27
|
+
const DEFAULT_SWEEP_MS = 300_000; // 5 minutes
|
|
28
|
+
const MIN_SWEEP_MS = 60_000;
|
|
29
|
+
let RunResultCompactionSweeper = class RunResultCompactionSweeper {
|
|
30
|
+
constructor(compactor) {
|
|
31
|
+
this.compactor = compactor;
|
|
32
|
+
this.logger = (0, logger_1.createLogger)('run-result.compaction-sweeper', { service: 'server' });
|
|
33
|
+
this.timer = null;
|
|
34
|
+
this.running = false;
|
|
35
|
+
}
|
|
36
|
+
onModuleInit() {
|
|
37
|
+
this.timer = setInterval(() => void this.sweep(), this.intervalMs());
|
|
38
|
+
this.timer.unref?.();
|
|
39
|
+
}
|
|
40
|
+
onModuleDestroy() {
|
|
41
|
+
if (this.timer) {
|
|
42
|
+
clearInterval(this.timer);
|
|
43
|
+
this.timer = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** One sweep pass. Guarded so a slow pass never overlaps the next tick. */
|
|
47
|
+
async sweep() {
|
|
48
|
+
if (this.running)
|
|
49
|
+
return;
|
|
50
|
+
this.running = true;
|
|
51
|
+
try {
|
|
52
|
+
const result = await this.compactor.compactPending(SWEEP_SOURCES);
|
|
53
|
+
if (result.compactedRows > 0) {
|
|
54
|
+
this.logger.info(result, 'run_result_compaction_sweep_done');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
this.logger.error({ error: error.message }, 'run_result_compaction_sweep_failed');
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
this.running = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
intervalMs() {
|
|
65
|
+
const raw = Number(process.env['RUN_RESULT_COMPACTION_SWEEP_MS']);
|
|
66
|
+
return Number.isFinite(raw) && raw >= MIN_SWEEP_MS ? raw : DEFAULT_SWEEP_MS;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
exports.RunResultCompactionSweeper = RunResultCompactionSweeper;
|
|
70
|
+
exports.RunResultCompactionSweeper = RunResultCompactionSweeper = __decorate([
|
|
71
|
+
(0, common_1.Injectable)(),
|
|
72
|
+
__metadata("design:paramtypes", [run_result_compactor_1.RunResultCompactor])
|
|
73
|
+
], RunResultCompactionSweeper);
|
|
74
|
+
//# sourceMappingURL=run-result-compaction-sweeper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-compaction-sweeper.js","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-compaction-sweeper.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iGAAiG;AACjG,EAAE;AACF,oGAAoG;AACpG,8FAA8F;AAC9F,gGAAgG;AAChG,mGAAmG;AACnG,iGAAiG;AACjG,2CAAqF;AACrF,+CAAkD;AAClD,iEAA4D;AAE5D,+FAA+F;AAC/F,kGAAkG;AAClG,sFAAsF;AACtF,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,uBAAuB,EAAE,uBAAuB,CAAC,CAAC;AACxG,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,YAAY;AAC9C,MAAM,YAAY,GAAG,MAAM,CAAC;AAGrB,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IAKrC,YAA6B,SAA6B;QAA7B,cAAS,GAAT,SAAS,CAAoB;QAJzC,WAAM,GAAG,IAAA,qBAAY,EAAC,+BAA+B,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvF,UAAK,GAA0B,IAAI,CAAC;QACpC,YAAO,GAAG,KAAK,CAAC;IAEqC,CAAC;IAE9D,YAAY;QACV,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;YAClE,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,kCAAkC,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,EAAE,oCAAoC,CAAC,CAAC;QAC/F,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAEO,UAAU;QAChB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAClE,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAC9E,CAAC;CACF,CAAA;AAvCY,gEAA0B;qCAA1B,0BAA0B;IADtC,IAAA,mBAAU,GAAE;qCAM6B,yCAAkB;GAL/C,0BAA0B,CAuCtC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type RunResultPayloadFields, type RunResultShardLine } from './run-result-payload';
|
|
2
|
+
export type PayloadField = keyof RunResultPayloadFields;
|
|
3
|
+
/** Which large fields tier out for a given run-result source (SPEC 30 §9.4). */
|
|
4
|
+
export declare function offloadFieldsForSource(source: string): PayloadField[];
|
|
5
|
+
/** A terminal row to compact: its offloadable fields + identity (composite PK) + the decision preview. */
|
|
6
|
+
export interface CompactionRow extends RunResultPayloadFields {
|
|
7
|
+
id: string;
|
|
8
|
+
createdAt: Date | string;
|
|
9
|
+
decisionOutput: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface ShardPlan {
|
|
12
|
+
seq: number;
|
|
13
|
+
lines: RunResultShardLine[];
|
|
14
|
+
}
|
|
15
|
+
export interface RowAssignment {
|
|
16
|
+
id: string;
|
|
17
|
+
createdAt: Date | string;
|
|
18
|
+
shardSeq: number;
|
|
19
|
+
rowIndex: number;
|
|
20
|
+
inputPreview: string | null;
|
|
21
|
+
outputPreview: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface CompactionPlan {
|
|
24
|
+
shards: ShardPlan[];
|
|
25
|
+
assignments: RowAssignment[];
|
|
26
|
+
/** The fields cleared inline for every row in this plan (uniform per source). */
|
|
27
|
+
clearedFields: PayloadField[];
|
|
28
|
+
}
|
|
29
|
+
/** Input list preview: a truncated serialization of input_variables. */
|
|
30
|
+
export declare function computeInputPreview(inputVariables: unknown): string | null;
|
|
31
|
+
/** Output list preview: decision_output already serves it when present, else preview parsed_output. */
|
|
32
|
+
export declare function computeOutputPreview(parsedOutput: unknown, decisionOutput: string | null): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Pack rows into shards of at most `maxRowsPerShard` rows, in input order, and record each row's
|
|
35
|
+
* shard + line index + previews. Row order is preserved: row i lands in shard floor(i/N) at line i%N.
|
|
36
|
+
*/
|
|
37
|
+
export declare function planCompaction(rows: CompactionRow[], offload: PayloadField[], maxRowsPerShard: number): CompactionPlan;
|
|
38
|
+
//# sourceMappingURL=run-result-compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-compaction.d.ts","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-compaction.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EAGxB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,YAAY,GAAG,MAAM,sBAAsB,CAAC;AAQxD,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAIrE;AAED,0GAA0G;AAC1G,MAAM,WAAW,aAAc,SAAQ,sBAAsB;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,iFAAiF;IACjF,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAWD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE1E;AAED,uGAAuG;AACvG,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAKxG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,aAAa,EAAE,EACrB,OAAO,EAAE,YAAY,EAAE,EACvB,eAAe,EAAE,MAAM,GACtB,cAAc,CAyBhB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.offloadFieldsForSource = offloadFieldsForSource;
|
|
4
|
+
exports.computeInputPreview = computeInputPreview;
|
|
5
|
+
exports.computeOutputPreview = computeOutputPreview;
|
|
6
|
+
exports.planCompaction = planCompaction;
|
|
7
|
+
// Run-result compaction — pure planning logic (SPEC 30 §9.3 / §9.4).
|
|
8
|
+
//
|
|
9
|
+
// Given a run's terminal rows, decide which fields to offload (per source), pack them into
|
|
10
|
+
// generation-keyed shards, and produce per-row assignments (shard + rowIndex + previews + the
|
|
11
|
+
// fields to clear inline). No DB or object storage here — the orchestrator (run-result-compactor.ts)
|
|
12
|
+
// turns this plan into shard writes + a single-transaction commit.
|
|
13
|
+
const run_result_payload_1 = require("./run-result-payload");
|
|
14
|
+
// rendered_prompt + input_variables are UI-read only → offloaded for every source.
|
|
15
|
+
const UI_ONLY_FIELDS = ['renderedPrompt', 'inputVariables'];
|
|
16
|
+
// raw_response + parsed_output are read by background business logic for optimization/release/canary,
|
|
17
|
+
// so they stay inline there; only the high-volume experiment/online sources offload them.
|
|
18
|
+
const PARSED_RAW_FIELDS = ['rawResponse', 'parsedOutput'];
|
|
19
|
+
/** Which large fields tier out for a given run-result source (SPEC 30 §9.4). */
|
|
20
|
+
function offloadFieldsForSource(source) {
|
|
21
|
+
return source === 'experiment' || source === 'online'
|
|
22
|
+
? [...UI_ONLY_FIELDS, ...PARSED_RAW_FIELDS]
|
|
23
|
+
: [...UI_ONLY_FIELDS];
|
|
24
|
+
}
|
|
25
|
+
const PREVIEW_MAX = 1000;
|
|
26
|
+
function previewOf(value) {
|
|
27
|
+
if (value == null)
|
|
28
|
+
return null;
|
|
29
|
+
const text = typeof value === 'string' ? value : JSON.stringify(value);
|
|
30
|
+
if (text.length === 0)
|
|
31
|
+
return null;
|
|
32
|
+
return text.length > PREVIEW_MAX ? text.slice(0, PREVIEW_MAX) : text;
|
|
33
|
+
}
|
|
34
|
+
/** Input list preview: a truncated serialization of input_variables. */
|
|
35
|
+
function computeInputPreview(inputVariables) {
|
|
36
|
+
return previewOf(inputVariables);
|
|
37
|
+
}
|
|
38
|
+
/** Output list preview: decision_output already serves it when present, else preview parsed_output. */
|
|
39
|
+
function computeOutputPreview(parsedOutput, decisionOutput) {
|
|
40
|
+
if (decisionOutput != null && decisionOutput.length > 0) {
|
|
41
|
+
return decisionOutput.length > PREVIEW_MAX ? decisionOutput.slice(0, PREVIEW_MAX) : decisionOutput;
|
|
42
|
+
}
|
|
43
|
+
return previewOf(parsedOutput);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Pack rows into shards of at most `maxRowsPerShard` rows, in input order, and record each row's
|
|
47
|
+
* shard + line index + previews. Row order is preserved: row i lands in shard floor(i/N) at line i%N.
|
|
48
|
+
*/
|
|
49
|
+
function planCompaction(rows, offload, maxRowsPerShard) {
|
|
50
|
+
if (maxRowsPerShard < 1)
|
|
51
|
+
throw new Error('maxRowsPerShard must be >= 1');
|
|
52
|
+
const shards = [];
|
|
53
|
+
const assignments = [];
|
|
54
|
+
rows.forEach((row, i) => {
|
|
55
|
+
const shardSeq = Math.floor(i / maxRowsPerShard);
|
|
56
|
+
const rowIndex = i % maxRowsPerShard;
|
|
57
|
+
let shard = shards[shardSeq];
|
|
58
|
+
if (!shard) {
|
|
59
|
+
shard = { seq: shardSeq, lines: [] };
|
|
60
|
+
shards[shardSeq] = shard;
|
|
61
|
+
}
|
|
62
|
+
shard.lines.push((0, run_result_payload_1.shardLineForFields)((0, run_result_payload_1.pickPayloadFields)(row), offload));
|
|
63
|
+
assignments.push({
|
|
64
|
+
id: row.id,
|
|
65
|
+
createdAt: row.createdAt,
|
|
66
|
+
shardSeq,
|
|
67
|
+
rowIndex,
|
|
68
|
+
inputPreview: computeInputPreview(row.inputVariables),
|
|
69
|
+
outputPreview: computeOutputPreview(row.parsedOutput, row.decisionOutput),
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
return { shards, assignments, clearedFields: offload };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=run-result-compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-compaction.js","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-compaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { DbClient } from '@proofhound/db';
|
|
2
|
+
import { ObjectStorageProvider, type StoredObjectRef } from '../../common/contracts/object-storage.provider';
|
|
3
|
+
import { type CompactionRow, type PayloadField, type RowAssignment } from './run-result-compaction';
|
|
4
|
+
export interface CompactionTarget {
|
|
5
|
+
projectId: string;
|
|
6
|
+
source: string;
|
|
7
|
+
sourceId: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CompactionResult {
|
|
10
|
+
compactedRows: number;
|
|
11
|
+
shards: number;
|
|
12
|
+
generation: number | null;
|
|
13
|
+
}
|
|
14
|
+
export interface CommitCompactionInput {
|
|
15
|
+
assignments: RowAssignment[];
|
|
16
|
+
shardRefs: StoredObjectRef[];
|
|
17
|
+
generation: number;
|
|
18
|
+
clearedFields: PayloadField[];
|
|
19
|
+
}
|
|
20
|
+
/** A (project, source, sourceId) group with rows still awaiting compaction. */
|
|
21
|
+
export interface PendingCompactionGroup {
|
|
22
|
+
projectId: string;
|
|
23
|
+
source: string;
|
|
24
|
+
sourceId: string;
|
|
25
|
+
}
|
|
26
|
+
/** DB side of compaction, behind an interface so the orchestrator unit-tests with a fake. */
|
|
27
|
+
export interface RunResultCompactionStore {
|
|
28
|
+
nextGeneration(sourceId: string): Promise<number>;
|
|
29
|
+
loadUncompacted(target: CompactionTarget): Promise<CompactionRow[]>;
|
|
30
|
+
commit(input: CommitCompactionInput): Promise<void>;
|
|
31
|
+
findPendingGroups(sources: string[], limit: number): Promise<PendingCompactionGroup[]>;
|
|
32
|
+
}
|
|
33
|
+
export declare const RUN_RESULT_COMPACTION_STORE: unique symbol;
|
|
34
|
+
export declare class RunResultCompactor {
|
|
35
|
+
private readonly store;
|
|
36
|
+
private readonly storage;
|
|
37
|
+
private readonly maxRowsPerShard;
|
|
38
|
+
constructor(store: RunResultCompactionStore, storage: ObjectStorageProvider);
|
|
39
|
+
compact(target: CompactionTarget): Promise<CompactionResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Periodic compaction for sources with no finalize step (e.g. `online`): finds (project, source,
|
|
42
|
+
* sourceId) groups with rows still inline and compacts each. SPEC 30 §9.3. A no-op when storage is
|
|
43
|
+
* disabled. Callers schedule this; it compacts at most `maxGroups` groups per run so a sweep is bounded.
|
|
44
|
+
*/
|
|
45
|
+
compactPending(sources: string[], maxGroups?: number): Promise<{
|
|
46
|
+
groups: number;
|
|
47
|
+
compactedRows: number;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
export declare class DrizzleRunResultCompactionStore implements RunResultCompactionStore {
|
|
51
|
+
private readonly db;
|
|
52
|
+
constructor(db: DbClient);
|
|
53
|
+
nextGeneration(sourceId: string): Promise<number>;
|
|
54
|
+
findPendingGroups(sources: string[], limit: number): Promise<PendingCompactionGroup[]>;
|
|
55
|
+
loadUncompacted(target: CompactionTarget): Promise<CompactionRow[]>;
|
|
56
|
+
commit({ assignments, shardRefs, generation, clearedFields }: CommitCompactionInput): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=run-result-compactor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-compactor.d.ts","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-compactor.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAC7G,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,aAAa,EAGnB,MAAM,yBAAyB,CAAC;AAOjC,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,6FAA6F;AAC7F,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC;CACxF;AAED,eAAO,MAAM,2BAA2B,eAAwC,CAAC;AAEjF,qBACa,kBAAkB;IAIU,OAAO,CAAC,QAAQ,CAAC,KAAK;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA8B;gBAGN,KAAK,EAAE,wBAAwB,EACpE,OAAO,EAAE,qBAAqB;IAG3C,OAAO,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmClE;;;;OAIG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,SAAK,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CAU5G;AAuBD,qBACa,+BAAgC,YAAW,wBAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAE5D,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUjD,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC;IAoBtF,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAqBnE,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAqB1G"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.DrizzleRunResultCompactionStore = exports.RunResultCompactor = exports.RUN_RESULT_COMPACTION_STORE = void 0;
|
|
16
|
+
// RunResultCompactor — tiers a finished run's large fields into object-storage shards (SPEC 30 §9.3).
|
|
17
|
+
//
|
|
18
|
+
// Protocol (object stores have no atomic rename, so payload_ref is committed only after the shard is
|
|
19
|
+
// confirmed written; there is no post-commit promote):
|
|
20
|
+
// 1. load the run's not-yet-compacted terminal rows
|
|
21
|
+
// 2. write each shard to a generation-exclusive key …/run_result_shard/{sourceId}/gen{G}/shard-{seq}
|
|
22
|
+
// 3. single-transaction UPDATE: set payload_ref + compaction_generation + previews, clear inline
|
|
23
|
+
// A re-run rewrites the not-yet-referenced gen{G} key region; it never overwrites a committed
|
|
24
|
+
// generation. When object storage is disabled this is a no-op, so OSS behaviour is unchanged.
|
|
25
|
+
const common_1 = require("@nestjs/common");
|
|
26
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
27
|
+
const database_constants_1 = require("../../../shared/database/database.constants");
|
|
28
|
+
const object_storage_provider_1 = require("../../common/contracts/object-storage.provider");
|
|
29
|
+
const run_result_compaction_1 = require("./run-result-compaction");
|
|
30
|
+
const run_result_payload_1 = require("./run-result-payload");
|
|
31
|
+
const CODEC = 'gzip';
|
|
32
|
+
const SHARD_EXT = '.jsonl.gz';
|
|
33
|
+
const DEFAULT_MAX_ROWS_PER_SHARD = 2000;
|
|
34
|
+
exports.RUN_RESULT_COMPACTION_STORE = Symbol('RUN_RESULT_COMPACTION_STORE');
|
|
35
|
+
let RunResultCompactor = class RunResultCompactor {
|
|
36
|
+
constructor(store, storage) {
|
|
37
|
+
this.store = store;
|
|
38
|
+
this.storage = storage;
|
|
39
|
+
this.maxRowsPerShard = DEFAULT_MAX_ROWS_PER_SHARD;
|
|
40
|
+
}
|
|
41
|
+
async compact(target) {
|
|
42
|
+
if (!this.storage.isEnabled())
|
|
43
|
+
return { compactedRows: 0, shards: 0, generation: null };
|
|
44
|
+
const rows = await this.store.loadUncompacted(target);
|
|
45
|
+
if (rows.length === 0)
|
|
46
|
+
return { compactedRows: 0, shards: 0, generation: null };
|
|
47
|
+
const generation = await this.store.nextGeneration(target.sourceId);
|
|
48
|
+
const plan = (0, run_result_compaction_1.planCompaction)(rows, (0, run_result_compaction_1.offloadFieldsForSource)(target.source), this.maxRowsPerShard);
|
|
49
|
+
const shardRefs = [];
|
|
50
|
+
for (const shard of plan.shards) {
|
|
51
|
+
const body = await (0, run_result_payload_1.encodeShard)(shard.lines, CODEC);
|
|
52
|
+
const ref = await this.storage.putObject({
|
|
53
|
+
project: { projectId: target.projectId, source: 'local' },
|
|
54
|
+
resourceType: 'run_result_shard',
|
|
55
|
+
resourceId: target.sourceId,
|
|
56
|
+
name: shardName(generation, shard.seq),
|
|
57
|
+
}, body, { codec: CODEC });
|
|
58
|
+
shardRefs[shard.seq] = { ...ref, version: generation };
|
|
59
|
+
}
|
|
60
|
+
await this.store.commit({
|
|
61
|
+
assignments: plan.assignments,
|
|
62
|
+
shardRefs,
|
|
63
|
+
generation,
|
|
64
|
+
clearedFields: plan.clearedFields,
|
|
65
|
+
});
|
|
66
|
+
return { compactedRows: plan.assignments.length, shards: plan.shards.length, generation };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Periodic compaction for sources with no finalize step (e.g. `online`): finds (project, source,
|
|
70
|
+
* sourceId) groups with rows still inline and compacts each. SPEC 30 §9.3. A no-op when storage is
|
|
71
|
+
* disabled. Callers schedule this; it compacts at most `maxGroups` groups per run so a sweep is bounded.
|
|
72
|
+
*/
|
|
73
|
+
async compactPending(sources, maxGroups = 50) {
|
|
74
|
+
if (!this.storage.isEnabled() || sources.length === 0)
|
|
75
|
+
return { groups: 0, compactedRows: 0 };
|
|
76
|
+
const groups = await this.store.findPendingGroups(sources, maxGroups);
|
|
77
|
+
let compactedRows = 0;
|
|
78
|
+
for (const group of groups) {
|
|
79
|
+
const result = await this.compact(group);
|
|
80
|
+
compactedRows += result.compactedRows;
|
|
81
|
+
}
|
|
82
|
+
return { groups: groups.length, compactedRows };
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
exports.RunResultCompactor = RunResultCompactor;
|
|
86
|
+
exports.RunResultCompactor = RunResultCompactor = __decorate([
|
|
87
|
+
(0, common_1.Injectable)(),
|
|
88
|
+
__param(0, (0, common_1.Inject)(exports.RUN_RESULT_COMPACTION_STORE)),
|
|
89
|
+
__metadata("design:paramtypes", [Object, object_storage_provider_1.ObjectStorageProvider])
|
|
90
|
+
], RunResultCompactor);
|
|
91
|
+
function shardName(generation, seq) {
|
|
92
|
+
return `gen${generation}/shard-${String(seq).padStart(5, '0')}${SHARD_EXT}`;
|
|
93
|
+
}
|
|
94
|
+
const CLEAR_COLUMN_SQL = {
|
|
95
|
+
renderedPrompt: (0, drizzle_orm_1.sql) `rendered_prompt = NULL`,
|
|
96
|
+
inputVariables: (0, drizzle_orm_1.sql) `input_variables = NULL`,
|
|
97
|
+
rawResponse: (0, drizzle_orm_1.sql) `raw_response = NULL`,
|
|
98
|
+
parsedOutput: (0, drizzle_orm_1.sql) `parsed_output = NULL`,
|
|
99
|
+
};
|
|
100
|
+
let DrizzleRunResultCompactionStore = class DrizzleRunResultCompactionStore {
|
|
101
|
+
constructor(db) {
|
|
102
|
+
this.db = db;
|
|
103
|
+
}
|
|
104
|
+
async nextGeneration(sourceId) {
|
|
105
|
+
const result = await this.db.execute((0, drizzle_orm_1.sql) `
|
|
106
|
+
SELECT COALESCE(MAX(compaction_generation), 0) + 1 AS next
|
|
107
|
+
FROM ph_runs.run_results
|
|
108
|
+
WHERE source_id = ${sourceId}::uuid
|
|
109
|
+
`);
|
|
110
|
+
const next = unwrapRows(result)[0]?.next;
|
|
111
|
+
return next == null ? 1 : Number(next);
|
|
112
|
+
}
|
|
113
|
+
async findPendingGroups(sources, limit) {
|
|
114
|
+
if (sources.length === 0)
|
|
115
|
+
return [];
|
|
116
|
+
const result = await this.db.execute((0, drizzle_orm_1.sql) `
|
|
117
|
+
SELECT DISTINCT project_id, source, source_id
|
|
118
|
+
FROM ph_runs.run_results
|
|
119
|
+
WHERE source IN (${drizzle_orm_1.sql.join(sources.map((s) => (0, drizzle_orm_1.sql) `${s}`), (0, drizzle_orm_1.sql) `, `)})
|
|
120
|
+
AND payload_ref IS NULL
|
|
121
|
+
AND status IN ('success', 'failed')
|
|
122
|
+
LIMIT ${limit}
|
|
123
|
+
`);
|
|
124
|
+
return unwrapRows(result).map((r) => ({
|
|
125
|
+
projectId: r.project_id,
|
|
126
|
+
source: r.source,
|
|
127
|
+
sourceId: r.source_id,
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
async loadUncompacted(target) {
|
|
131
|
+
const result = await this.db.execute((0, drizzle_orm_1.sql) `
|
|
132
|
+
SELECT id, created_at, rendered_prompt, input_variables, raw_response, parsed_output, decision_output
|
|
133
|
+
FROM ph_runs.run_results
|
|
134
|
+
WHERE source = ${target.source}
|
|
135
|
+
AND source_id = ${target.sourceId}::uuid
|
|
136
|
+
AND payload_ref IS NULL
|
|
137
|
+
AND status IN ('success', 'failed')
|
|
138
|
+
ORDER BY created_at ASC, id ASC
|
|
139
|
+
`);
|
|
140
|
+
return unwrapRows(result).map((r) => ({
|
|
141
|
+
id: r.id,
|
|
142
|
+
createdAt: r.created_at,
|
|
143
|
+
renderedPrompt: r.rendered_prompt,
|
|
144
|
+
inputVariables: r.input_variables,
|
|
145
|
+
rawResponse: r.raw_response,
|
|
146
|
+
parsedOutput: r.parsed_output,
|
|
147
|
+
decisionOutput: r.decision_output,
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
async commit({ assignments, shardRefs, generation, clearedFields }) {
|
|
151
|
+
if (assignments.length === 0)
|
|
152
|
+
return;
|
|
153
|
+
const valueRows = assignments.map((a) => {
|
|
154
|
+
const payloadRef = JSON.stringify({ shard: shardRefs[a.shardSeq], rowIndex: a.rowIndex });
|
|
155
|
+
return (0, drizzle_orm_1.sql) `(${a.id}::uuid, ${toIso(a.createdAt)}::timestamptz, ${payloadRef}::jsonb, ${a.inputPreview}::text, ${a.outputPreview}::text)`;
|
|
156
|
+
});
|
|
157
|
+
const clears = clearedFields.map((f) => CLEAR_COLUMN_SQL[f]);
|
|
158
|
+
const clearClause = clears.length > 0 ? (0, drizzle_orm_1.sql) `, ${drizzle_orm_1.sql.join(clears, (0, drizzle_orm_1.sql) `, `)}` : (0, drizzle_orm_1.sql) ``;
|
|
159
|
+
// Single statement = atomic: at commit, every payload_ref points at an already-written shard.
|
|
160
|
+
await this.db.execute((0, drizzle_orm_1.sql) `
|
|
161
|
+
UPDATE ph_runs.run_results AS rr
|
|
162
|
+
SET payload_ref = v.payload_ref,
|
|
163
|
+
compaction_generation = ${generation},
|
|
164
|
+
input_preview = v.input_preview,
|
|
165
|
+
output_preview = v.output_preview${clearClause}
|
|
166
|
+
FROM (VALUES ${drizzle_orm_1.sql.join(valueRows, (0, drizzle_orm_1.sql) `, `)}) AS v(id, created_at, payload_ref, input_preview, output_preview)
|
|
167
|
+
WHERE rr.id = v.id AND rr.created_at = v.created_at
|
|
168
|
+
`);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
exports.DrizzleRunResultCompactionStore = DrizzleRunResultCompactionStore;
|
|
172
|
+
exports.DrizzleRunResultCompactionStore = DrizzleRunResultCompactionStore = __decorate([
|
|
173
|
+
(0, common_1.Injectable)(),
|
|
174
|
+
__param(0, (0, common_1.Inject)(database_constants_1.DATABASE_CLIENT)),
|
|
175
|
+
__metadata("design:paramtypes", [Object])
|
|
176
|
+
], DrizzleRunResultCompactionStore);
|
|
177
|
+
function toIso(value) {
|
|
178
|
+
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
179
|
+
}
|
|
180
|
+
function unwrapRows(result) {
|
|
181
|
+
if (Array.isArray(result))
|
|
182
|
+
return result;
|
|
183
|
+
if (result && typeof result === 'object' && 'rows' in result) {
|
|
184
|
+
return result.rows ?? [];
|
|
185
|
+
}
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=run-result-compactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-compactor.js","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-compactor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,sGAAsG;AACtG,EAAE;AACF,qGAAqG;AACrG,uDAAuD;AACvD,sDAAsD;AACtD,uGAAuG;AACvG,mGAAmG;AACnG,8FAA8F;AAC9F,8FAA8F;AAC9F,2CAAoD;AACpD,6CAA4C;AAE5C,oFAA8E;AAC9E,4FAA6G;AAC7G,mEAMiC;AACjC,6DAAmD;AAEnD,MAAM,KAAK,GAAG,MAAe,CAAC;AAC9B,MAAM,SAAS,GAAG,WAAW,CAAC;AAC9B,MAAM,0BAA0B,GAAG,IAAI,CAAC;AAoC3B,QAAA,2BAA2B,GAAG,MAAM,CAAC,6BAA6B,CAAC,CAAC;AAG1E,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAG7B,YACuC,KAAgD,EACpE,OAA8B;QADO,UAAK,GAAL,KAAK,CAA0B;QACpE,YAAO,GAAP,OAAO,CAAuB;QAJhC,oBAAe,GAAG,0BAA0B,CAAC;IAK3D,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,MAAwB;QACpC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;YAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAExF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAEhF,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,IAAA,sCAAc,EAAC,IAAI,EAAE,IAAA,8CAAsB,EAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAE/F,MAAM,SAAS,GAAsB,EAAE,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,IAAA,gCAAW,EAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACnD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CACtC;gBACE,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;gBACzD,YAAY,EAAE,kBAAkB;gBAChC,UAAU,EAAE,MAAM,CAAC,QAAQ;gBAC3B,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC;aACvC,EACD,IAAI,EACJ,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;YACF,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YACtB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS;YACT,UAAU;YACV,aAAa,EAAE,IAAI,CAAC,aAAa;SAClC,CAAC,CAAC;QAEH,OAAO,EAAE,aAAa,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;IAC5F,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,OAAiB,EAAE,SAAS,GAAG,EAAE;QACpD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;QAC9F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACtE,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACzC,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC;QACxC,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC;IAClD,CAAC;CACF,CAAA;AA1DY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,eAAM,EAAC,mCAA2B,CAAC,CAAA;6CACV,+CAAqB;GALtC,kBAAkB,CA0D9B;AAED,SAAS,SAAS,CAAC,UAAkB,EAAE,GAAW;IAChD,OAAO,MAAM,UAAU,UAAU,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,gBAAgB,GAA8B;IAClD,cAAc,EAAE,IAAA,iBAAG,EAAA,wBAAwB;IAC3C,cAAc,EAAE,IAAA,iBAAG,EAAA,wBAAwB;IAC3C,WAAW,EAAE,IAAA,iBAAG,EAAA,qBAAqB;IACrC,YAAY,EAAE,IAAA,iBAAG,EAAA,sBAAsB;CACxC,CAAC;AAaK,IAAM,+BAA+B,GAArC,MAAM,+BAA+B;IAC1C,YAAsD,EAAY;QAAZ,OAAE,GAAF,EAAE,CAAU;IAAG,CAAC;IAEtE,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAA4B,IAAA,iBAAG,EAAA;;;0BAG7C,QAAQ;KAC7B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,CAA4B,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACpE,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,OAAiB,EAAE,KAAa;QACtD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAA4D,IAAA,iBAAG,EAAA;;;yBAG9E,iBAAG,CAAC,IAAI,CACzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,iBAAG,EAAA,GAAG,CAAC,EAAE,CAAC,EAC7B,IAAA,iBAAG,EAAA,IAAI,CACR;;;cAGO,KAAK;KACd,CAAC,CAAC;QACH,OAAO,UAAU,CAA4D,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/F,SAAS,EAAE,CAAC,CAAC,UAAU;YACvB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,QAAQ,EAAE,CAAC,CAAC,SAAS;SACtB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAwB;QAC5C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAAiB,IAAA,iBAAG,EAAA;;;uBAGrC,MAAM,CAAC,MAAM;0BACV,MAAM,CAAC,QAAQ;;;;KAIpC,CAAC,CAAC;QACH,OAAO,UAAU,CAAiB,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpD,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,SAAS,EAAE,CAAC,CAAC,UAAU;YACvB,cAAc,EAAE,CAAC,CAAC,eAAe;YACjC,cAAc,EAAE,CAAC,CAAC,eAAe;YACjC,WAAW,EAAE,CAAC,CAAC,YAAY;YAC3B,YAAY,EAAE,CAAC,CAAC,aAAa;YAC7B,cAAc,EAAE,CAAC,CAAC,eAAe;SAClC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAyB;QACvF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAErC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACtC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC1F,OAAO,IAAA,iBAAG,EAAA,IAAI,CAAC,CAAC,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,UAAU,YAAY,CAAC,CAAC,YAAY,WAAW,CAAC,CAAC,aAAa,SAAS,CAAC;QAC3I,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAA,iBAAG,EAAA,KAAK,iBAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAA,iBAAG,EAAA,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,iBAAG,EAAA,EAAE,CAAC;QAEpF,8FAA8F;QAC9F,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAA,iBAAG,EAAA;;;oCAGO,UAAU;;6CAED,WAAW;qBACnC,iBAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAA,iBAAG,EAAA,IAAI,CAAC;;KAE5C,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AA3EY,0EAA+B;0CAA/B,+BAA+B;IAD3C,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,oCAAe,CAAC,CAAA;;GADzB,+BAA+B,CA2E3C;AAED,SAAS,KAAK,CAAC,KAAoB;IACjC,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AACrF,CAAC;AAED,SAAS,UAAU,CAAc,MAAe;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAa,CAAC;IAChD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,IAAK,MAAkC,EAAE,CAAC;QAC1F,OAAQ,MAAyB,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
import type { ObjectCodec, StoredObjectRef } from '../../common/contracts/object-storage.provider';
|
|
3
|
+
/** The four large fields that tier out of `run_results`. `null` = absent / genuinely empty. */
|
|
4
|
+
export interface RunResultPayloadFields {
|
|
5
|
+
renderedPrompt: unknown;
|
|
6
|
+
inputVariables: unknown;
|
|
7
|
+
rawResponse: string | null;
|
|
8
|
+
parsedOutput: unknown;
|
|
9
|
+
}
|
|
10
|
+
/** One JSONL line in a shard. A source only offloads some fields (SPEC 30 §9.4), so all optional. */
|
|
11
|
+
export type RunResultShardLine = Partial<RunResultPayloadFields>;
|
|
12
|
+
/** Stored in `run_results.payload_ref`: the shard holding this row + which line it is. */
|
|
13
|
+
export interface RunResultPayloadRef {
|
|
14
|
+
shard: StoredObjectRef;
|
|
15
|
+
rowIndex: number;
|
|
16
|
+
}
|
|
17
|
+
/** Minimal row shape the reader consumes: the inline (possibly-null) fields + the pointer. */
|
|
18
|
+
export interface RunResultPayloadRow extends RunResultPayloadFields {
|
|
19
|
+
payloadRef: RunResultPayloadRef | null;
|
|
20
|
+
}
|
|
21
|
+
/** Pick only the offloadable fields off a wider row, defaulting missing ones to null. */
|
|
22
|
+
export declare function pickPayloadFields(row: Partial<RunResultPayloadFields>): RunResultPayloadFields;
|
|
23
|
+
/** Keep only the fields a source actually offloads; drops the rest so they are not double-stored. */
|
|
24
|
+
export declare function shardLineForFields(fields: RunResultPayloadFields, offload: ReadonlyArray<keyof RunResultPayloadFields>): RunResultShardLine;
|
|
25
|
+
/** Encode shard lines into compressed JSONL bytes (the object body a compactor writes). Generic so
|
|
26
|
+
* dataset-sample shards (one data object per line) reuse the same codec as run-result shards. */
|
|
27
|
+
export declare function encodeShard<T>(lines: T[], codec: ObjectCodec): Promise<Buffer>;
|
|
28
|
+
/** Decode a shard body back into its lines (used by the readers). */
|
|
29
|
+
export declare function decodeShard<T = RunResultShardLine>(body: Buffer, codec: ObjectCodec | undefined): Promise<T[]>;
|
|
30
|
+
//# sourceMappingURL=run-result-payload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-payload.d.ts","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-payload.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAOnG,+FAA+F;AAC/F,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,qGAAqG;AACrG,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAEjE,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8FAA8F;AAC9F,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACxC;AASD,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAO9F;AAED,qGAAqG;AACrG,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,aAAa,CAAC,MAAM,sBAAsB,CAAC,GACnD,kBAAkB,CAQpB;AA4BD;kGACkG;AAClG,wBAAsB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpF;AAED,qEAAqE;AACrE,wBAAsB,WAAW,CAAC,CAAC,GAAG,kBAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAIpH"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pickPayloadFields = pickPayloadFields;
|
|
4
|
+
exports.shardLineForFields = shardLineForFields;
|
|
5
|
+
exports.encodeShard = encodeShard;
|
|
6
|
+
exports.decodeShard = decodeShard;
|
|
7
|
+
// Run-result large-payload tiering — shared shard format + codec (SPEC 30 §9).
|
|
8
|
+
//
|
|
9
|
+
// When object storage is configured, a run's four large fields are compacted into a compressed
|
|
10
|
+
// JSONL shard: one line per row, each line the offloaded fields of that row. The row keeps a
|
|
11
|
+
// `payload_ref` ({ shard, rowIndex }) so any reader can resolve a field back. The reader
|
|
12
|
+
// (run-result-payload.reader.ts) and the compactor (run-result-compactor.ts) both speak this format.
|
|
13
|
+
const node_buffer_1 = require("node:buffer");
|
|
14
|
+
const node_util_1 = require("node:util");
|
|
15
|
+
const node_zlib_1 = require("node:zlib");
|
|
16
|
+
const gzipAsync = (0, node_util_1.promisify)(node_zlib_1.gzip);
|
|
17
|
+
const gunzipAsync = (0, node_util_1.promisify)(node_zlib_1.gunzip);
|
|
18
|
+
const brotliCompressAsync = (0, node_util_1.promisify)(node_zlib_1.brotliCompress);
|
|
19
|
+
const brotliDecompressAsync = (0, node_util_1.promisify)(node_zlib_1.brotliDecompress);
|
|
20
|
+
const PAYLOAD_FIELDS = [
|
|
21
|
+
'renderedPrompt',
|
|
22
|
+
'inputVariables',
|
|
23
|
+
'rawResponse',
|
|
24
|
+
'parsedOutput',
|
|
25
|
+
];
|
|
26
|
+
/** Pick only the offloadable fields off a wider row, defaulting missing ones to null. */
|
|
27
|
+
function pickPayloadFields(row) {
|
|
28
|
+
return {
|
|
29
|
+
renderedPrompt: row.renderedPrompt ?? null,
|
|
30
|
+
inputVariables: row.inputVariables ?? null,
|
|
31
|
+
rawResponse: row.rawResponse ?? null,
|
|
32
|
+
parsedOutput: row.parsedOutput ?? null,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Keep only the fields a source actually offloads; drops the rest so they are not double-stored. */
|
|
36
|
+
function shardLineForFields(fields, offload) {
|
|
37
|
+
const line = {};
|
|
38
|
+
for (const key of PAYLOAD_FIELDS) {
|
|
39
|
+
if (offload.includes(key)) {
|
|
40
|
+
line[key] = fields[key] ?? null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return line;
|
|
44
|
+
}
|
|
45
|
+
async function compress(buf, codec) {
|
|
46
|
+
switch (codec) {
|
|
47
|
+
case 'gzip':
|
|
48
|
+
return gzipAsync(buf);
|
|
49
|
+
case 'br':
|
|
50
|
+
return brotliCompressAsync(buf);
|
|
51
|
+
case 'identity':
|
|
52
|
+
return buf;
|
|
53
|
+
default:
|
|
54
|
+
throw new Error(`unsupported shard codec for write: ${codec}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function decompress(buf, codec) {
|
|
58
|
+
switch (codec ?? 'identity') {
|
|
59
|
+
case 'gzip':
|
|
60
|
+
return gunzipAsync(buf);
|
|
61
|
+
case 'br':
|
|
62
|
+
return brotliDecompressAsync(buf);
|
|
63
|
+
case 'identity':
|
|
64
|
+
return buf;
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`unsupported shard codec for read: ${codec}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Encode shard lines into compressed JSONL bytes (the object body a compactor writes). Generic so
|
|
70
|
+
* dataset-sample shards (one data object per line) reuse the same codec as run-result shards. */
|
|
71
|
+
async function encodeShard(lines, codec) {
|
|
72
|
+
const jsonl = lines.map((line) => JSON.stringify(line)).join('\n');
|
|
73
|
+
return compress(node_buffer_1.Buffer.from(jsonl, 'utf8'), codec);
|
|
74
|
+
}
|
|
75
|
+
/** Decode a shard body back into its lines (used by the readers). */
|
|
76
|
+
async function decodeShard(body, codec) {
|
|
77
|
+
const text = (await decompress(body, codec)).toString('utf8');
|
|
78
|
+
if (text.length === 0)
|
|
79
|
+
return [];
|
|
80
|
+
return text.split('\n').map((line) => (line.length === 0 ? {} : JSON.parse(line)));
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=run-result-payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-payload.js","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-payload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ObjectStorageProvider } from '../../common/contracts/object-storage.provider';
|
|
2
|
+
import { type RunResultPayloadFields, type RunResultPayloadRow } from './run-result-payload';
|
|
3
|
+
export declare class RunResultPayloadReader {
|
|
4
|
+
private readonly storage;
|
|
5
|
+
constructor(storage: ObjectStorageProvider);
|
|
6
|
+
/** Resolve all four fields for one row, fetching its shard at most once. */
|
|
7
|
+
hydrate(row: RunResultPayloadRow): Promise<RunResultPayloadFields>;
|
|
8
|
+
/**
|
|
9
|
+
* Batch variant: groups rows by shard object so each shard is fetched exactly once. The dominant
|
|
10
|
+
* pattern (a page / batch of rows from one run) shares a shard, so this is one GET, not one per row.
|
|
11
|
+
*/
|
|
12
|
+
hydrateMany(rows: RunResultPayloadRow[]): Promise<RunResultPayloadFields[]>;
|
|
13
|
+
readRenderedPrompt(row: RunResultPayloadRow): Promise<unknown>;
|
|
14
|
+
readInputVariables(row: RunResultPayloadRow): Promise<unknown>;
|
|
15
|
+
readRawResponse(row: RunResultPayloadRow): Promise<string | null>;
|
|
16
|
+
readParsedOutput(row: RunResultPayloadRow): Promise<unknown>;
|
|
17
|
+
private needsShard;
|
|
18
|
+
private loadShardLine;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=run-result-payload.reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-result-payload.reader.d.ts","sourceRoot":"","sources":["../../../../src/server/modules/run-result/run-result-payload.reader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,qBAAqB,EAAwB,MAAM,gDAAgD,CAAC;AAC7G,OAAO,EACL,KAAK,sBAAsB,EAE3B,KAAK,mBAAmB,EAIzB,MAAM,sBAAsB,CAAC;AAE9B,qBACa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,qBAAqB;IAE3D,4EAA4E;IACtE,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAMxE;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC;IAwB3E,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9D,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9D,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIjE,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,OAAO,CAAC,UAAU;YAIJ,aAAa;CAI5B"}
|