bulltrackers-module 1.0.611 → 1.0.612
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.
|
@@ -15,6 +15,7 @@ const ContractValidator = require('./ContractValidator');
|
|
|
15
15
|
const validationOverrides = require('../config/validation_overrides');
|
|
16
16
|
const pLimit = require('p-limit');
|
|
17
17
|
const zlib = require('zlib');
|
|
18
|
+
const { commitBatchInChunks, generateDataHash, FieldValue } = require('../utils/utils');
|
|
18
19
|
|
|
19
20
|
const NON_RETRYABLE_ERRORS = [ 'PERMISSION_DENIED', 'DATA_LOSS', 'FAILED_PRECONDITION' ];
|
|
20
21
|
const SIMHASH_REGISTRY_COLLECTION = 'system_simhash_registry';
|
|
@@ -137,6 +138,8 @@ async function commitResults(stateObj, dStr, passName, config, deps, skipStatusW
|
|
|
137
138
|
continue;
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
// [NEW] Page Computation Logic (Fan-Out) with TTL
|
|
142
|
+
// Bypasses standard compression/sharding to write per-user documents
|
|
140
143
|
// [NEW] Page Computation Logic (Fan-Out) with TTL
|
|
141
144
|
// Bypasses standard compression/sharding to write per-user documents
|
|
142
145
|
if (isPageComputation && !isEmpty) {
|
|
@@ -145,26 +148,27 @@ async function commitResults(stateObj, dStr, passName, config, deps, skipStatusW
|
|
|
145
148
|
.collection(config.computationsSubcollection).doc(name);
|
|
146
149
|
|
|
147
150
|
// --- CLEANUP START: Remove old storage formats (Sharded/Compressed) ---
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
151
|
+
// Optimization: Only attempt cleanup on the initial write to save reads
|
|
152
|
+
if (isInitialWrite) {
|
|
153
|
+
try {
|
|
154
|
+
const docSnap = await mainDocRef.get();
|
|
155
|
+
if (docSnap.exists) {
|
|
156
|
+
const dData = docSnap.data();
|
|
157
|
+
if (dData._sharded) {
|
|
158
|
+
const shardCol = mainDocRef.collection('_shards');
|
|
159
|
+
const shardDocs = await withRetry(() => shardCol.listDocuments());
|
|
160
|
+
|
|
161
|
+
if (shardDocs.length > 0) {
|
|
162
|
+
const cleanupOps = shardDocs.map(d => ({ type: 'DELETE', ref: d }));
|
|
163
|
+
await commitBatchInChunks(config, deps, cleanupOps, `${name}::PageModeCleanup`);
|
|
164
|
+
runMetrics.io.deletes += cleanupOps.length;
|
|
165
|
+
logger.log('INFO', `[PageMode] ${name}: Cleaned up ${cleanupOps.length} old shard documents.`);
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
}
|
|
169
|
+
} catch (cleanupErr) {
|
|
170
|
+
logger.log('WARN', `[PageMode] ${name}: Cleanup warning: ${cleanupErr.message}`);
|
|
165
171
|
}
|
|
166
|
-
} catch (cleanupErr) {
|
|
167
|
-
logger.log('WARN', `[PageMode] ${name}: Cleanup warning: ${cleanupErr.message}`);
|
|
168
172
|
}
|
|
169
173
|
// --- CLEANUP END ---
|
|
170
174
|
|
|
@@ -198,31 +202,47 @@ async function commitResults(stateObj, dStr, passName, config, deps, skipStatusW
|
|
|
198
202
|
logger.log('INFO', `[PageMode] ${name}: Wrote ${pageWrites.length} user pages. TTL: ${ttlDays}d.`);
|
|
199
203
|
}
|
|
200
204
|
|
|
201
|
-
// 3. Write the "Header" document
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
205
|
+
// 3. Write or Update the "Header" document
|
|
206
|
+
// FIXED: Now runs on every batch to ensure counts are accumulated correctly.
|
|
207
|
+
|
|
208
|
+
const isFinalFlush = (flushMode !== 'INTERMEDIATE');
|
|
209
|
+
|
|
210
|
+
// Determine Page Count Value: Raw number for initial, Increment for updates
|
|
211
|
+
let pageCountValue = pageWrites.length;
|
|
212
|
+
if (!isInitialWrite) {
|
|
213
|
+
pageCountValue = FieldValue.increment(pageWrites.length);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const headerData = {
|
|
217
|
+
_isPageMode: true, // Flag for readers to know where to look
|
|
218
|
+
_pageCount: pageCountValue,
|
|
219
|
+
_lastUpdated: new Date().toISOString(),
|
|
220
|
+
_expireAt: expireAt // Ensure the header also gets deleted
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// Handle Completion Status
|
|
224
|
+
if (isFinalFlush) {
|
|
225
|
+
headerData._completed = true;
|
|
226
|
+
} else if (isInitialWrite) {
|
|
227
|
+
headerData._completed = false; // Initialize as incomplete
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Write Strategy:
|
|
231
|
+
// isInitialWrite = TRUE -> merge: false (Wipes old Standard Mode data/schema)
|
|
232
|
+
// isInitialWrite = FALSE -> merge: true (Updates count and status, preserves data)
|
|
233
|
+
await mainDocRef.set(headerData, { merge: !isInitialWrite });
|
|
234
|
+
|
|
235
|
+
runMetrics.io.writes += 1;
|
|
236
|
+
|
|
237
|
+
if (isFinalFlush && calc.manifest.hash) {
|
|
238
|
+
successUpdates[name] = {
|
|
239
|
+
hash: calc.manifest.hash,
|
|
240
|
+
simHash: simHash,
|
|
241
|
+
resultHash: resultHash,
|
|
242
|
+
category: calc.manifest.category,
|
|
243
|
+
composition: calc.manifest.composition,
|
|
244
|
+
metrics: runMetrics
|
|
245
|
+
};
|
|
226
246
|
}
|
|
227
247
|
|
|
228
248
|
continue; // Skip the standard writeSingleResult logic
|