bulltrackers-module 1.0.469 → 1.0.471
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.
|
@@ -235,12 +235,38 @@ exports.runRootDataIndexer = async (config, dependencies) => {
|
|
|
235
235
|
// Path: {verifications} (Limit 1) - Checks if collection is non-empty generally
|
|
236
236
|
const verificationsRef = db.collection(collections.verifications || 'user_verifications');
|
|
237
237
|
|
|
238
|
-
// 4.
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
238
|
+
// 4. Social Data Checks - Use date tracking documents
|
|
239
|
+
// Single tracking documents at root level:
|
|
240
|
+
// - pi_social_posts/_dates -> fetchedDates.{date}
|
|
241
|
+
// - signed_in_users_social/_dates -> fetchedDates.{date}
|
|
242
|
+
// For generic social (daily_social_insights), check the collection directly
|
|
243
|
+
const [piSocialTrackingDoc, signedInSocialTrackingDoc, genericSocialSnap] = await Promise.all([
|
|
244
|
+
db.collection(PI_SOCIAL_COLL_NAME).doc('_dates').get(),
|
|
245
|
+
db.collection(SIGNED_IN_SOCIAL_COLL_NAME).doc('_dates').get(),
|
|
246
|
+
db.collectionGroup('posts')
|
|
247
|
+
.where('fetchedAt', '>=', dayStart)
|
|
248
|
+
.where('fetchedAt', '<=', dayEnd)
|
|
249
|
+
.limit(1)
|
|
250
|
+
.get()
|
|
251
|
+
]);
|
|
252
|
+
|
|
253
|
+
// Check if date exists in tracking documents
|
|
254
|
+
let foundPISocial = false;
|
|
255
|
+
let foundSignedInSocial = false;
|
|
256
|
+
|
|
257
|
+
if (piSocialTrackingDoc.exists) {
|
|
258
|
+
const data = piSocialTrackingDoc.data();
|
|
259
|
+
if (data.fetchedDates && data.fetchedDates[dateStr] === true) {
|
|
260
|
+
foundPISocial = true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (signedInSocialTrackingDoc.exists) {
|
|
265
|
+
const data = signedInSocialTrackingDoc.data();
|
|
266
|
+
if (data.fetchedDates && data.fetchedDates[dateStr] === true) {
|
|
267
|
+
foundSignedInSocial = true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
244
270
|
|
|
245
271
|
// --- Execute Checks ---
|
|
246
272
|
const [
|
|
@@ -252,8 +278,7 @@ exports.runRootDataIndexer = async (config, dependencies) => {
|
|
|
252
278
|
piDeepExists,
|
|
253
279
|
piHistExists,
|
|
254
280
|
signedInPortExists, signedInHistExists,
|
|
255
|
-
verificationsQuery
|
|
256
|
-
universalSocialSnap
|
|
281
|
+
verificationsQuery
|
|
257
282
|
] = await Promise.all([
|
|
258
283
|
checkAnyPartExists(normPortPartsRef),
|
|
259
284
|
checkAnyPartExists(specPortPartsRef),
|
|
@@ -267,43 +292,12 @@ exports.runRootDataIndexer = async (config, dependencies) => {
|
|
|
267
292
|
checkAnyPartExists(piHistoryPartsRef),
|
|
268
293
|
checkAnyPartExists(signedInPortPartsRef),
|
|
269
294
|
checkAnyPartExists(signedInHistPartsRef),
|
|
270
|
-
verificationsRef.limit(1).get()
|
|
271
|
-
universalSocialQuery.get()
|
|
295
|
+
verificationsRef.limit(1).get()
|
|
272
296
|
]);
|
|
273
297
|
|
|
274
|
-
//
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (!universalSocialSnap.empty) {
|
|
279
|
-
logger.log('DEBUG', `[RootDataIndexer/${dateStr}] Found ${universalSocialSnap.docs.length} social posts in query`);
|
|
280
|
-
universalSocialSnap.docs.forEach(doc => {
|
|
281
|
-
const path = doc.ref.path;
|
|
282
|
-
const data = doc.data();
|
|
283
|
-
const fetchedAt = data.fetchedAt;
|
|
284
|
-
|
|
285
|
-
// Use includes() to match collection name anywhere in path (more robust)
|
|
286
|
-
// Path format: {collectionName}/{userId}/posts/{postId}
|
|
287
|
-
// Firestore paths don't have leading slash, so check both with and without
|
|
288
|
-
const piMatchPattern = `${PI_SOCIAL_COLL_NAME}/`;
|
|
289
|
-
const signedInMatchPattern = `${SIGNED_IN_SOCIAL_COLL_NAME}/`;
|
|
290
|
-
|
|
291
|
-
if (path.includes(piMatchPattern) || path.startsWith(piMatchPattern)) {
|
|
292
|
-
foundPISocial = true;
|
|
293
|
-
logger.log('DEBUG', `[RootDataIndexer/${dateStr}] ✓ Found PI social: ${path}`);
|
|
294
|
-
}
|
|
295
|
-
if (path.includes(signedInMatchPattern) || path.startsWith(signedInMatchPattern)) {
|
|
296
|
-
foundSignedInSocial = true;
|
|
297
|
-
const fetchedAtStr = fetchedAt ? (fetchedAt.toDate ? fetchedAt.toDate().toISOString() : String(fetchedAt)) : 'missing';
|
|
298
|
-
logger.log('DEBUG', `[RootDataIndexer/${dateStr}] ✓ Found signed-in social: ${path}, fetchedAt: ${fetchedAtStr}`);
|
|
299
|
-
} else if (!path.includes(piMatchPattern)) {
|
|
300
|
-
// Log paths that don't match either pattern to help debug
|
|
301
|
-
logger.log('DEBUG', `[RootDataIndexer/${dateStr}] ✗ Path doesn't match: ${path} (looking for: "${signedInMatchPattern}" or "${piMatchPattern}")`);
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
} else {
|
|
305
|
-
logger.log('DEBUG', `[RootDataIndexer/${dateStr}] No social posts found in query (dayStart: ${dayStart.toISOString()}, dayEnd: ${dayEnd.toISOString()})`);
|
|
306
|
-
}
|
|
298
|
+
// Social data checks are done above using tracking documents
|
|
299
|
+
// foundPISocial and foundSignedInSocial are already set from the tracking document checks
|
|
300
|
+
logger.log('INFO', `[RootDataIndexer/${dateStr}] Social check results - PI: ${foundPISocial}, Signed-in: ${foundSignedInSocial}`);
|
|
307
301
|
|
|
308
302
|
// --- Assign to Availability ---
|
|
309
303
|
availability.details.normalPortfolio = normPortExists;
|
|
@@ -351,6 +351,30 @@ exports.handleSocialTask = async (message, context, config, dependencies) => {
|
|
|
351
351
|
offset += take;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
+
// Write date tracking document after successful fetch
|
|
355
|
+
// Single document at root level: /signed_in_users_social/_dates and /pi_social_posts/_dates
|
|
356
|
+
// Contains a map of all dates that have been fetched
|
|
357
|
+
if (totalSaved > 0 && (type === 'SIGNED_IN_USER' || type === 'POPULAR_INVESTOR')) {
|
|
358
|
+
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
|
|
359
|
+
let trackingCollectionPath;
|
|
360
|
+
|
|
361
|
+
if (type === 'SIGNED_IN_USER') {
|
|
362
|
+
trackingCollectionPath = config.signedInUserSocialCollection || 'signed_in_users_social';
|
|
363
|
+
} else {
|
|
364
|
+
trackingCollectionPath = config.piSocialCollectionName || 'pi_social_posts';
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Write to a single tracking document at the root of the collection
|
|
368
|
+
const trackingDocRef = db.collection(trackingCollectionPath).doc('_dates');
|
|
369
|
+
const trackingData = {
|
|
370
|
+
[`fetchedDates.${today}`]: true,
|
|
371
|
+
lastUpdated: FieldValue.serverTimestamp()
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
await trackingDocRef.set(trackingData, { merge: true });
|
|
375
|
+
logger.log('INFO', `[SocialTask/${taskId}] Updated date tracking for ${type}: ${today}`);
|
|
376
|
+
}
|
|
377
|
+
|
|
354
378
|
logger.log('SUCCESS', `[SocialTask/${taskId}] Process complete for ${cid}. Total stored: ${totalSaved}/${MAX_POSTS_TO_STORE}`);
|
|
355
379
|
|
|
356
380
|
} catch (error) {
|