@gscdump/engine 1.4.8 → 1.4.11
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/entities.d.mts +12 -0
- package/dist/entities.mjs +46 -0
- package/dist/rollups.mjs +1 -1
- package/package.json +4 -4
package/dist/entities.d.mts
CHANGED
|
@@ -4,6 +4,7 @@ import { SitemapGenerationKey, emptyTypesKey, hashSortedUrlList, hashUrl, hashUr
|
|
|
4
4
|
import { QueryDimDeps, QueryDimMeta, QueryDimRecord, QueryDimStore, buildQueryDimRecords, createQueryDimStore } from "./query-dim.mjs";
|
|
5
5
|
import { SITEMAP_PROJECTION_GRACE_MS, SitemapProjectionFeed, SitemapProjectionFiles, SitemapProjectionManifest, decodeSitemapProjectionManifest, emptySitemapProjectionManifest, parseSitemapProjectionManifest, selectSitemapProjectionFiles, withSitemapProjectionFeed } from "./sitemap-projection.mjs";
|
|
6
6
|
import { TenantCtx } from "@gscdump/contracts";
|
|
7
|
+
import { CanonicalDifferenceKind } from "gscdump";
|
|
7
8
|
/**
|
|
8
9
|
* GSC URL inspection result fields we persist. Mirrors the
|
|
9
10
|
* `searchconsole_v1.Schema$UrlInspectionResult` shape but as plain JSON
|
|
@@ -106,6 +107,8 @@ interface InspectionParquetRow {
|
|
|
106
107
|
* newest-by-`inspectedAt` event.
|
|
107
108
|
*/
|
|
108
109
|
interface InspectionEventRow extends InspectionParquetRow {
|
|
110
|
+
/** Declared-vs-selected canonical classification, computed at inspection ingest. */
|
|
111
|
+
canonicalMismatchKind: CanonicalDifferenceKind;
|
|
109
112
|
crawlingUserAgent: string | null;
|
|
110
113
|
/** JSON-encoded `RichResultsItem[]`. */
|
|
111
114
|
richResultsItems: string | null;
|
|
@@ -212,6 +215,15 @@ interface InspectionStore {
|
|
|
212
215
|
eventFilesDeleted: number;
|
|
213
216
|
transitionsWritten: number;
|
|
214
217
|
}>;
|
|
218
|
+
/**
|
|
219
|
+
* Rewrite a legacy latest-only base with the canonical kind derived from the
|
|
220
|
+
* canonical pair it already retains. Outstanding events must be compacted first.
|
|
221
|
+
*/
|
|
222
|
+
backfillCanonicalMismatchKinds: (ctx: TenantCtx) => Promise<{
|
|
223
|
+
baseRowCount: number;
|
|
224
|
+
rowsBackfilled: number;
|
|
225
|
+
rewritten: boolean;
|
|
226
|
+
}>;
|
|
215
227
|
/**
|
|
216
228
|
* DuckDB-resolvable URI for the materialised parquet sidecar, or
|
|
217
229
|
* `undefined` if the underlying `DataSource` has no native URI shape
|
package/dist/entities.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { SITEMAP_PROJECTION_GRACE_MS, decodeSitemapProjectionManifest, emptySite
|
|
|
5
5
|
import { buildQueryDimRecords, createQueryDimStore } from "./query-dim.mjs";
|
|
6
6
|
import { encodeJsonBigintSafe } from "@gscdump/lakehouse/bigint";
|
|
7
7
|
import { GSCDUMP_INDEXING_TRANSITION_FIELDS } from "@gscdump/contracts";
|
|
8
|
+
import { classifyCanonicalDifference } from "gscdump";
|
|
8
9
|
const YEAR_MONTH_RE = /^(\d{4})-(\d{2})-/;
|
|
9
10
|
const ENTITY_IO_CONCURRENCY = 8;
|
|
10
11
|
async function mapEntityIo(items, fn) {
|
|
@@ -107,6 +108,11 @@ const INSPECTION_PARQUET_COLUMNS = [
|
|
|
107
108
|
];
|
|
108
109
|
const INSPECTION_EVENT_COLUMNS = [
|
|
109
110
|
...INSPECTION_PARQUET_COLUMNS,
|
|
111
|
+
{
|
|
112
|
+
name: "canonicalMismatchKind",
|
|
113
|
+
type: "VARCHAR",
|
|
114
|
+
nullable: false
|
|
115
|
+
},
|
|
110
116
|
{
|
|
111
117
|
name: "crawlingUserAgent",
|
|
112
118
|
type: "VARCHAR",
|
|
@@ -158,6 +164,19 @@ const INSPECTION_EVENT_COLUMNS = [
|
|
|
158
164
|
nullable: true
|
|
159
165
|
}
|
|
160
166
|
];
|
|
167
|
+
const CANONICAL_DIFFERENCE_KINDS = /* @__PURE__ */ new Set([
|
|
168
|
+
"none",
|
|
169
|
+
"formatting",
|
|
170
|
+
"path",
|
|
171
|
+
"cross_domain"
|
|
172
|
+
]);
|
|
173
|
+
function populateCanonicalMismatchKind(row) {
|
|
174
|
+
const current = row.canonicalMismatchKind;
|
|
175
|
+
const expected = classifyCanonicalDifference(typeof row.userCanonical === "string" ? row.userCanonical : null, typeof row.googleCanonical === "string" ? row.googleCanonical : null);
|
|
176
|
+
const missingOrInvalid = typeof current !== "string" || !CANONICAL_DIFFERENCE_KINDS.has(current);
|
|
177
|
+
row.canonicalMismatchKind = expected;
|
|
178
|
+
return missingOrInvalid || current !== expected;
|
|
179
|
+
}
|
|
161
180
|
const INSPECTION_TRANSITION_COLUMNS = [
|
|
162
181
|
{
|
|
163
182
|
name: "urlHash",
|
|
@@ -389,6 +408,7 @@ function createInspectionStore(opts) {
|
|
|
389
408
|
for (const [h, row] of latest) {
|
|
390
409
|
const fc = earliestChecked.get(h);
|
|
391
410
|
if (fc !== void 0) row.firstCheckedAt = fc;
|
|
411
|
+
populateCanonicalMismatchKind(row);
|
|
392
412
|
merged.push(row);
|
|
393
413
|
}
|
|
394
414
|
const bytes = encodeRowsToParquetFlex(merged, {
|
|
@@ -405,6 +425,32 @@ function createInspectionStore(opts) {
|
|
|
405
425
|
transitionsWritten
|
|
406
426
|
};
|
|
407
427
|
},
|
|
428
|
+
async backfillCanonicalMismatchKinds(ctx) {
|
|
429
|
+
const baseKey = inspectionBaseKey(ctx);
|
|
430
|
+
const baseBytes = await readOptional(ds, baseKey);
|
|
431
|
+
if (!baseBytes) return {
|
|
432
|
+
baseRowCount: 0,
|
|
433
|
+
rowsBackfilled: 0,
|
|
434
|
+
rewritten: false
|
|
435
|
+
};
|
|
436
|
+
const rows = await decodeParquetToRows(baseBytes);
|
|
437
|
+
let rowsBackfilled = 0;
|
|
438
|
+
for (const row of rows) if (populateCanonicalMismatchKind(row)) rowsBackfilled++;
|
|
439
|
+
if (rowsBackfilled === 0) return {
|
|
440
|
+
baseRowCount: rows.length,
|
|
441
|
+
rowsBackfilled: 0,
|
|
442
|
+
rewritten: false
|
|
443
|
+
};
|
|
444
|
+
await ds.write(baseKey, encodeRowsToParquetFlex(rows, {
|
|
445
|
+
columns: INSPECTION_EVENT_COLUMNS,
|
|
446
|
+
sortKey: ["urlHash"]
|
|
447
|
+
}));
|
|
448
|
+
return {
|
|
449
|
+
baseRowCount: rows.length,
|
|
450
|
+
rowsBackfilled,
|
|
451
|
+
rewritten: true
|
|
452
|
+
};
|
|
453
|
+
},
|
|
408
454
|
parquetUri(ctx) {
|
|
409
455
|
return ds.uri?.(inspectionParquetKey(ctx));
|
|
410
456
|
}
|
package/dist/rollups.mjs
CHANGED
|
@@ -978,7 +978,7 @@ const indexingHealthRollup = {
|
|
|
978
978
|
SUM(CASE WHEN CAST(pageFetchState AS VARCHAR) = 'NOT_FOUND' THEN 1 ELSE 0 END)::BIGINT AS not_found,
|
|
979
979
|
SUM(CASE WHEN CAST(mobileUsabilityVerdict AS VARCHAR) = 'PASS' THEN 1 ELSE 0 END)::BIGINT AS mobile_passes,
|
|
980
980
|
SUM(CASE WHEN CAST(richResultsVerdict AS VARCHAR) = 'PASS' THEN 1 ELSE 0 END)::BIGINT AS rich_results_passes,
|
|
981
|
-
SUM(CASE WHEN
|
|
981
|
+
SUM(CASE WHEN canonicalMismatchKind IN ('path', 'cross_domain') THEN 1 ELSE 0 END)::BIGINT AS canonical_mismatches
|
|
982
982
|
FROM read_parquet({{INSPECTIONS}}, union_by_name = true)
|
|
983
983
|
WHERE substr(CAST(inspectedAt AS VARCHAR), 1, 10) >= '${utcDateMinusDays(windowAnchorMs, 90)}'
|
|
984
984
|
GROUP BY 1
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/engine",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.11",
|
|
5
5
|
"description": "Append-only Parquet/DuckDB storage engine + planner + adapters for the gscdump pipeline. Node + edge runtimes; opt-in heavy peers.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -181,9 +181,9 @@
|
|
|
181
181
|
"dependencies": {
|
|
182
182
|
"drizzle-orm": "1.0.0-rc.3",
|
|
183
183
|
"proper-lockfile": "^4.1.2",
|
|
184
|
-
"@gscdump/contracts": "^1.4.
|
|
185
|
-
"@gscdump/lakehouse": "^1.4.
|
|
186
|
-
"gscdump": "^1.4.
|
|
184
|
+
"@gscdump/contracts": "^1.4.11",
|
|
185
|
+
"@gscdump/lakehouse": "^1.4.11",
|
|
186
|
+
"gscdump": "^1.4.11"
|
|
187
187
|
},
|
|
188
188
|
"devDependencies": {
|
|
189
189
|
"@duckdb/duckdb-wasm": "1.33.1-dev57.0",
|