@gscdump/lakehouse 3.4.1 → 3.4.2

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/catalog.mjs CHANGED
@@ -5,6 +5,7 @@ import { icebergManifests } from "./_virtual/node_modules/.pnpm/icebird@0.8.27_p
5
5
  import { s3SignedResolver } from "./_virtual/node_modules/.pnpm/icebird@0.8.27_patch_hash=651b5cc1b513184638c98e21a0852c4559044ae60f8449fbe9d81a894ea5b4d7/node_modules/icebird/src/s3.mjs";
6
6
  import { cacheGet, cachePut, reportCatalogCacheError } from "./catalog-cache.mjs";
7
7
  import { toIcebergDayCount } from "./date.mjs";
8
+ import { wrapManifestCacheResolver } from "./manifest-cache-resolver.mjs";
8
9
  import { buildManifestPartitionFilter } from "./partition-prune.mjs";
9
10
  let icebirdWriteModule;
10
11
  function useIcebirdWriteModule() {
@@ -46,18 +47,21 @@ async function connectIcebergCatalog(config, opts = {}) {
46
47
  await cachePut(opts.cache, catalogConfigKey(config), toCache, CATALOG_CONFIG_TTL_MS, now);
47
48
  }
48
49
  }
49
- const resolver = withVerifiedWriterByteLengths(cachingResolver(s3SignedResolver({
50
+ const cacheScope = catalogCacheScope(config);
51
+ const s3Resolver = s3SignedResolver({
50
52
  accessKeyId: config.s3.accessKeyId,
51
53
  secretAccessKey: config.s3.secretAccessKey,
52
54
  region: config.s3.region ?? "auto",
53
55
  endpoint: config.s3.endpoint,
54
56
  pathStyle: true
55
- })));
57
+ });
58
+ const baseResolver = opts.cache ? wrapManifestCacheResolver(s3Resolver, opts.cache, cacheScope, opts.clock) : s3Resolver;
59
+ const resolver = withVerifiedWriterByteLengths(cachingResolver(baseResolver));
56
60
  return {
57
61
  catalog,
58
62
  resolver,
59
63
  namespace: config.namespace,
60
- cacheScope: catalogCacheScope(config)
64
+ cacheScope
61
65
  };
62
66
  }
63
67
  function withVerifiedWriterByteLengths(resolver) {
@@ -0,0 +1,50 @@
1
+ import { cacheGet, cachePut } from "./catalog-cache.mjs";
2
+ const MANIFEST_AVRO_PATH = /\/metadata\/[^/]+\.avro$/;
3
+ const MANIFEST_CACHE_TTL_MS = 6048e5;
4
+ const MAX_CACHED_MANIFEST_BYTES = 1048576;
5
+ const BASE64_CHUNK_BYTES = 32768;
6
+ function isManifestObjectPath(path) {
7
+ return MANIFEST_AVRO_PATH.test(path);
8
+ }
9
+ function manifestCacheKey(scope, path) {
10
+ return `lh-manifest\0${scope}\0${path}`;
11
+ }
12
+ function bytesToBase64(bytes) {
13
+ let binary = "";
14
+ for (let offset = 0; offset < bytes.length; offset += BASE64_CHUNK_BYTES) {
15
+ const chunk = bytes.subarray(offset, offset + BASE64_CHUNK_BYTES);
16
+ binary += String.fromCharCode(...chunk);
17
+ }
18
+ return btoa(binary);
19
+ }
20
+ function base64ToBytes(b64) {
21
+ const binary = atob(b64);
22
+ const bytes = new Uint8Array(binary.length);
23
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
24
+ return bytes;
25
+ }
26
+ function bufferedAsyncBuffer(bytes) {
27
+ return {
28
+ byteLength: bytes.byteLength,
29
+ slice(start = 0, end = bytes.byteLength) {
30
+ return bytes.buffer.slice(bytes.byteOffset + start, bytes.byteOffset + end);
31
+ }
32
+ };
33
+ }
34
+ function wrapManifestCacheResolver(base, cache, scope, clock = Date.now) {
35
+ return {
36
+ ...base,
37
+ async reader(path, byteLength) {
38
+ if (!isManifestObjectPath(path)) return base.reader(path, byteLength);
39
+ const now = clock();
40
+ const key = manifestCacheKey(scope, path);
41
+ const cached = await cacheGet(cache, key, now);
42
+ if (cached) return bufferedAsyncBuffer(base64ToBytes(cached.b64));
43
+ const ab = await base.reader(path, byteLength);
44
+ const bytes = new Uint8Array(await ab.slice(0, ab.byteLength));
45
+ if (bytes.byteLength <= MAX_CACHED_MANIFEST_BYTES) await cachePut(cache, key, { b64: bytesToBase64(bytes) }, MANIFEST_CACHE_TTL_MS, now);
46
+ return bufferedAsyncBuffer(bytes);
47
+ }
48
+ };
49
+ }
50
+ export { wrapManifestCacheResolver };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/lakehouse",
3
3
  "type": "module",
4
- "version": "3.4.1",
4
+ "version": "3.4.2",
5
5
  "description": "Dataset-agnostic Iceberg lakehouse layer + dataset registry for R2 Data Catalog producers (ADR-0021).",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",