bulltrackers-module 1.0.537 → 1.0.538

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.
@@ -5,17 +5,62 @@
5
5
 
6
6
  const { FieldValue } = require('@google-cloud/firestore');
7
7
 
8
+ /**
9
+ * Get the detail field name for a data type
10
+ * @param {string} dataType - Data type identifier
11
+ * @returns {string} - Detail field name in the index document
12
+ */
13
+ function getDetailFieldName(dataType) {
14
+ const dataTypeMap = {
15
+ 'signedInUserPortfolio': 'signedInUserPortfolio',
16
+ 'signedInUserHistory': 'signedInUserHistory',
17
+ 'signedInUserSocial': 'signedInSocial',
18
+ 'piPortfolios': 'piPortfolios',
19
+ 'piHistory': 'piHistory',
20
+ 'piSocial': 'piSocial',
21
+ 'normalPortfolios': 'normalPortfolio',
22
+ 'normalHistory': 'normalHistory',
23
+ 'speculatorPortfolios': 'speculatorPortfolio',
24
+ 'speculatorHistory': 'speculatorHistory'
25
+ };
26
+ return dataTypeMap[dataType] || dataType;
27
+ }
28
+
8
29
  /**
9
30
  * Check if root data is already indexed for a specific date
10
31
  * @param {Firestore} db - Firestore instance
11
32
  * @param {string} dateStr - Date string (YYYY-MM-DD)
12
33
  * @param {string} availabilityCollection - Collection name for root data index
13
- * @returns {Promise<boolean>} - True if already indexed
34
+ * @param {Array<string>} dataTypesRun - Optional array of data types to verify are indexed (e.g., ['signedInUserPortfolio', 'piSocial'])
35
+ * @returns {Promise<boolean>} - True if already indexed (and all requested data types are indexed if provided)
14
36
  */
15
- async function isRootDataIndexed(db, dateStr, availabilityCollection = 'system_root_data_index') {
37
+ async function isRootDataIndexed(db, dateStr, availabilityCollection = 'system_root_data_index', dataTypesRun = []) {
16
38
  try {
17
39
  const indexDoc = await db.collection(availabilityCollection).doc(dateStr).get();
18
- return indexDoc.exists;
40
+ if (!indexDoc.exists) {
41
+ return false;
42
+ }
43
+
44
+ // If specific data types were requested, verify they are actually indexed
45
+ if (dataTypesRun && dataTypesRun.length > 0) {
46
+ const indexData = indexDoc.data();
47
+ const details = indexData?.details || {};
48
+
49
+ // Check if all requested data types are indexed (have true values)
50
+ // If any are false or missing, return false (needs indexing)
51
+ for (const dataType of dataTypesRun) {
52
+ const detailField = getDetailFieldName(dataType);
53
+ if (details[detailField] !== true) {
54
+ // At least one requested data type is not indexed
55
+ return false;
56
+ }
57
+ }
58
+ // All requested data types are indexed as true
59
+ return true;
60
+ }
61
+
62
+ // No specific data types requested - just check if document exists
63
+ return true;
19
64
  } catch (error) {
20
65
  // If we can't check, assume not indexed to be safe
21
66
  return false;
@@ -39,11 +84,43 @@ async function conditionallyRunRootDataIndexer({ db, logger, dateStr, rootDataIn
39
84
  const { runRootDataIndexer } = require('../../root-data-indexer/index');
40
85
  const availabilityCollection = rootDataIndexerConfig?.availabilityCollection || 'system_root_data_index';
41
86
 
42
- // Check if already indexed
43
- const alreadyIndexed = await isRootDataIndexed(db, dateStr, availabilityCollection);
44
- if (alreadyIndexed) {
45
- logger.log('INFO', `[RootDataIndexer] Root data already indexed for ${dateStr}, skipping`);
46
- return false;
87
+ // IMPORTANT: Only index data types that were successfully stored (dataTypesRun contains only successful operations)
88
+ // If a write failed, it won't be in dataTypesRun, so we won't try to index it
89
+ // However, we still run the indexer to check/update the types that did succeed
90
+
91
+ // Check if already indexed (verify specific data types if provided)
92
+ // Only check the data types that were actually run - if they're all already true, skip indexing (never overwrite true values)
93
+ if (dataTypesRun.length > 0) {
94
+ const alreadyIndexed = await isRootDataIndexed(db, dateStr, availabilityCollection, dataTypesRun);
95
+ if (alreadyIndexed) {
96
+ logger.log('INFO', `[RootDataIndexer] All requested data types (${dataTypesRun.join(', ')}) are already indexed as true for ${dateStr}, skipping (never overwrite true values)`);
97
+ return false;
98
+ }
99
+
100
+ // If document exists but data types aren't indexed, log it
101
+ try {
102
+ const indexDoc = await db.collection(availabilityCollection).doc(dateStr).get();
103
+ if (indexDoc.exists) {
104
+ const indexData = indexDoc.data();
105
+ const details = indexData?.details || {};
106
+ const missingTypes = dataTypesRun.filter(dt => {
107
+ const detailField = getDetailFieldName(dt);
108
+ return details[detailField] !== true;
109
+ });
110
+ if (missingTypes.length > 0) {
111
+ logger.log('INFO', `[RootDataIndexer] Index document exists for ${dateStr} but data types (${missingTypes.join(', ')}) are not indexed. Re-indexing...`);
112
+ }
113
+ }
114
+ } catch (e) {
115
+ // Ignore errors checking document
116
+ }
117
+ } else {
118
+ // No specific data types - check if document exists (legacy behavior)
119
+ const alreadyIndexed = await isRootDataIndexed(db, dateStr, availabilityCollection, []);
120
+ if (alreadyIndexed) {
121
+ logger.log('INFO', `[RootDataIndexer] Root data already indexed for ${dateStr}, skipping`);
122
+ return false;
123
+ }
47
124
  }
48
125
 
49
126
  // Use Firestore transaction to ensure only one instance runs the indexer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.537",
3
+ "version": "1.0.538",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [