bulltrackers-module 1.0.647 → 1.0.648
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.
|
@@ -274,15 +274,9 @@ async function fetchSingleResult(db, config, dateStr, name, category) {
|
|
|
274
274
|
|
|
275
275
|
let data = snap.data();
|
|
276
276
|
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
config.logger.log('ERROR', `[DependencyFetcher] ❌ Document exists but is empty at: ${path} (only contains metadata fields)`);
|
|
281
|
-
} else {
|
|
282
|
-
console.error(`[DependencyFetcher] ❌ Document exists but is empty at: ${path} (only contains metadata fields)`);
|
|
283
|
-
}
|
|
284
|
-
return null; // Return null so it gets caught as missing
|
|
285
|
-
}
|
|
277
|
+
// CRITICAL: Don't check if empty yet - we need to load shards/compressed data first
|
|
278
|
+
// A sharded document will only have metadata in the pointer doc, but the actual data is in shards
|
|
279
|
+
// A compressed document will only have metadata + payload, but the actual data is in the payload
|
|
286
280
|
|
|
287
281
|
// 1. Handle Compression
|
|
288
282
|
if (data._compressed && data.payload) {
|
|
@@ -305,7 +299,7 @@ async function fetchSingleResult(db, config, dateStr, name, category) {
|
|
|
305
299
|
}
|
|
306
300
|
}
|
|
307
301
|
|
|
308
|
-
// 2. Handle Sharding
|
|
302
|
+
// 2. Handle Sharding (MUST happen before empty check)
|
|
309
303
|
if (data._sharded) {
|
|
310
304
|
const shardPath = `${path}/_shards`;
|
|
311
305
|
if (config.logger) {
|
|
@@ -330,11 +324,36 @@ async function fetchSingleResult(db, config, dateStr, name, category) {
|
|
|
330
324
|
// Merge shard contents
|
|
331
325
|
let hasData = false;
|
|
332
326
|
shardSnaps.forEach(shard => {
|
|
333
|
-
|
|
327
|
+
let shardData = shard.data();
|
|
334
328
|
const shardId = shard.id;
|
|
335
329
|
if (config.logger) {
|
|
336
330
|
config.logger.log('TRACE', `[DependencyFetcher] 📂 Loading Shard '${shardId}' for '${name}' from: ${shardPath}/${shardId}`);
|
|
337
331
|
}
|
|
332
|
+
|
|
333
|
+
// CRITICAL: Shards themselves can be compressed (common in big data)
|
|
334
|
+
// Decompress the shard if needed before merging
|
|
335
|
+
if (shardData._compressed && shardData.payload) {
|
|
336
|
+
try {
|
|
337
|
+
const buffer = (shardData.payload instanceof Buffer) ? shardData.payload :
|
|
338
|
+
(shardData.payload._byteString ? Buffer.from(shardData.payload._byteString, 'base64') :
|
|
339
|
+
Buffer.from(shardData.payload));
|
|
340
|
+
const decompressed = zlib.gunzipSync(buffer);
|
|
341
|
+
const jsonStr = decompressed.toString('utf8');
|
|
342
|
+
const realData = JSON.parse(jsonStr);
|
|
343
|
+
// If it's double-encoded, parse again
|
|
344
|
+
const parsedData = (typeof realData === 'string') ? JSON.parse(realData) : realData;
|
|
345
|
+
shardData = { ...shardData, ...parsedData };
|
|
346
|
+
delete shardData.payload;
|
|
347
|
+
} catch (e) {
|
|
348
|
+
if (config.logger) {
|
|
349
|
+
config.logger.log('ERROR', `[DependencyFetcher] ❌ Failed to decompress shard '${shardId}' for '${name}': ${e.message}`);
|
|
350
|
+
} else {
|
|
351
|
+
console.error(`[DependencyFetcher] ❌ Failed to decompress shard '${shardId}' for '${name}': ${e.message}`);
|
|
352
|
+
}
|
|
353
|
+
// Continue with uncompressed data if decompression fails
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
338
357
|
// Merge shard contents, ignoring internal metadata if it clashes
|
|
339
358
|
Object.entries(shardData).forEach(([k, v]) => {
|
|
340
359
|
if (!k.startsWith('_')) {
|
|
@@ -353,9 +372,27 @@ async function fetchSingleResult(db, config, dateStr, name, category) {
|
|
|
353
372
|
}
|
|
354
373
|
return null;
|
|
355
374
|
}
|
|
375
|
+
|
|
376
|
+
// After loading shards, remove shard metadata from data object for cleaner output
|
|
377
|
+
// Keep only the actual data fields
|
|
378
|
+
const cleanedData = {};
|
|
379
|
+
const dataKeys = [];
|
|
380
|
+
Object.entries(data).forEach(([k, v]) => {
|
|
381
|
+
if (!k.startsWith('_')) {
|
|
382
|
+
cleanedData[k] = v;
|
|
383
|
+
dataKeys.push(k);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
data = cleanedData;
|
|
387
|
+
|
|
388
|
+
// Log what we loaded for debugging
|
|
389
|
+
if (config.logger) {
|
|
390
|
+
config.logger.log('INFO', `[DependencyFetcher] ✅ Loaded ${shardSnaps.size} shard(s) for '${name}'. Data fields: ${dataKeys.length > 0 ? dataKeys.slice(0, 10).join(', ') + (dataKeys.length > 10 ? `... (+${dataKeys.length - 10} more)` : '') : 'none'}`);
|
|
391
|
+
}
|
|
356
392
|
}
|
|
357
393
|
|
|
358
|
-
// Final validation: ensure we have usable data after all processing
|
|
394
|
+
// Final validation: ensure we have usable data after all processing (decompression + sharding)
|
|
395
|
+
// Only check if we haven't already determined it's empty
|
|
359
396
|
if (isDataEmpty(data)) {
|
|
360
397
|
if (config.logger) {
|
|
361
398
|
config.logger.log('ERROR', `[DependencyFetcher] ❌ Dependency '${name}' loaded but is empty (no usable data) at: ${path}`);
|