bulltrackers-module 1.0.16 → 1.0.17

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.
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @fileoverview
3
+ * Core logic for handling invalid speculator CIDs.
4
+ * Finds or creates a Firestore document and adds the CIDs to it.
5
+ */
6
+
7
+ /**
8
+ * Handles the logic of storing invalid speculator IDs.
9
+ *
10
+ * @param {object} message The Pub/Sub message.
11
+ * @param {object} firestore An initialized Firestore client.
12
+ * @param {object} FieldValue A reference to Firestore.FieldValue.
13
+ * @param {object} logger A logger instance.
14
+ * @param {object} config The configuration object.
15
+ * @param {string} config.invalidSpeculatorsCollectionName The name of the Firestore collection.
16
+ * @param {number} config.maxInvalidUsersPerDoc The max number of IDs to store per doc.
17
+ */
18
+ exports.handleInvalidSpeculator = async (message, firestore, FieldValue, logger, config) => {
19
+ try {
20
+ const { invalidCids } = JSON.parse(Buffer.from(message.data, 'base64').toString());
21
+
22
+ if (!invalidCids || invalidCids.length === 0) {
23
+ logger.log('WARN', 'Received message with no invalid CIDs. Nothing to do.');
24
+ return;
25
+ }
26
+
27
+ // Use config for collection name and max doc size
28
+ const collectionRef = firestore.collection(config.invalidSpeculatorsCollectionName);
29
+ const maxPerDoc = config.maxInvalidUsersPerDoc;
30
+
31
+ // Fetch a pool of documents and pick one randomly
32
+ const querySnapshot = await collectionRef
33
+ .where('userCount', '<', maxPerDoc)
34
+ .limit(10) // Fetch up to 10 potential documents
35
+ .get();
36
+
37
+ let targetDocRef;
38
+
39
+ if (!querySnapshot.empty) {
40
+ // Randomly select one of the available documents to reduce contention
41
+ const randomIndex = Math.floor(Math.random() * querySnapshot.docs.length);
42
+ targetDocRef = querySnapshot.docs[randomIndex].ref;
43
+ } else {
44
+ // If no documents have space, create a new one
45
+ targetDocRef = collectionRef.doc();
46
+ }
47
+
48
+ // Atomic update using a transaction
49
+ await firestore.runTransaction(async (transaction) => {
50
+ const doc = await transaction.get(targetDocRef);
51
+
52
+ const updates = {};
53
+ let newUsersCount = 0;
54
+
55
+ if (!doc.exists) {
56
+ // If it's a new document, initialize the user count
57
+ updates.userCount = 0;
58
+ }
59
+
60
+ for (const cid of invalidCids) {
61
+ const fieldPath = `users.${cid}`;
62
+ // Check if the user ID already exists to avoid recounting
63
+ if (!doc.exists || !doc.data().users || !doc.data().users[cid]) {
64
+ updates[fieldPath] = true;
65
+ newUsersCount++;
66
+ }
67
+ }
68
+
69
+ if (newUsersCount > 0) {
70
+ updates.userCount = FieldValue.increment(newUsersCount);
71
+ transaction.set(targetDocRef, updates, { merge: true });
72
+ }
73
+ });
74
+
75
+ logger.log('SUCCESS', `Successfully stored ${invalidCids.length} invalid speculator IDs in document ${targetDocRef.id}.`);
76
+
77
+ } catch (error) {
78
+ logger.log('ERROR', 'FATAL Error in Invalid Speculator Handler', {
79
+ errorMessage: error.message,
80
+ errorStack: error.stack
81
+ });
82
+ // Re-throw the error to ensure Pub/Sub retries the message
83
+ throw error;
84
+ }
85
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview
3
+ * Exports the InvalidSpeculatorHandler helpers.
4
+ */
5
+
6
+ const helpers = require('./helpers/handler_helpers');
7
+
8
+ module.exports = {
9
+ helpers,
10
+ };
package/index.js CHANGED
@@ -10,6 +10,7 @@ const TaskEngine = require('./functions/task-engine');
10
10
  const ComputationSystem = require('./functions/computation-system');
11
11
  const GenericAPI = require('./functions/generic-api'); // <-- ADD THIS
12
12
  const Dispatcher = require('./functions/dispatcher'); // <-- ADD THIS
13
+ const InvalidSpeculatorHandler = require('./functions/invalid-speculator-handler'); // <-- ADD THIS
13
14
 
14
15
  module.exports = {
15
16
  core,
@@ -17,5 +18,6 @@ module.exports = {
17
18
  TaskEngine,
18
19
  ComputationSystem,
19
20
  GenericAPI, // <-- AND ADD THIS
20
- Dispatcher, // <-- AND ADD THI
21
+ Dispatcher, // <-- AND ADD THIS
22
+ InvalidSpeculatorHandler, // <-- AND ADD THIS
21
23
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -10,7 +10,8 @@
10
10
  "functions/core/",
11
11
  "functions/computation-system/",
12
12
  "functions/generic-api/",
13
- "functions/dispatcher/"
13
+ "functions/dispatcher/",
14
+ "functions/invalid-speculator-handler/"
14
15
  ],
15
16
  "scripts": {
16
17
  "test": "echo \"Error: no test specified\" && exit 1"