@brightchain/brightchain-api-lib 0.14.0 → 0.15.0
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.
- package/package.json +5 -5
- package/src/index.d.ts +3 -0
- package/src/index.d.ts.map +1 -1
- package/src/index.js +5 -0
- package/src/index.js.map +1 -1
- package/src/lib/application.d.ts +1 -0
- package/src/lib/application.d.ts.map +1 -1
- package/src/lib/application.js +23 -0
- package/src/lib/application.js.map +1 -1
- package/src/lib/auth/aclEnforcedAvailability.d.ts +57 -0
- package/src/lib/auth/aclEnforcedAvailability.d.ts.map +1 -0
- package/src/lib/auth/aclEnforcedAvailability.js +87 -0
- package/src/lib/auth/aclEnforcedAvailability.js.map +1 -0
- package/src/lib/auth/aclEnforcedBlockStore.d.ts +66 -0
- package/src/lib/auth/aclEnforcedBlockStore.d.ts.map +1 -0
- package/src/lib/auth/aclEnforcedBlockStore.js +83 -0
- package/src/lib/auth/aclEnforcedBlockStore.js.map +1 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.d.ts +46 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.d.ts.map +1 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.js +110 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.js.map +1 -0
- package/src/lib/auth/index.d.ts +7 -0
- package/src/lib/auth/index.d.ts.map +1 -0
- package/src/lib/auth/index.js +13 -0
- package/src/lib/auth/index.js.map +1 -0
- package/src/lib/auth/poolAclBootstrap.d.ts +36 -0
- package/src/lib/auth/poolAclBootstrap.d.ts.map +1 -0
- package/src/lib/auth/poolAclBootstrap.js +64 -0
- package/src/lib/auth/poolAclBootstrap.js.map +1 -0
- package/src/lib/auth/poolAclStore.d.ts +77 -0
- package/src/lib/auth/poolAclStore.d.ts.map +1 -0
- package/src/lib/auth/poolAclStore.js +189 -0
- package/src/lib/auth/poolAclStore.js.map +1 -0
- package/src/lib/auth/poolAclUpdater.d.ts +79 -0
- package/src/lib/auth/poolAclUpdater.d.ts.map +1 -0
- package/src/lib/auth/poolAclUpdater.js +144 -0
- package/src/lib/auth/poolAclUpdater.js.map +1 -0
- package/src/lib/availability/availabilityService.d.ts +2 -2
- package/src/lib/availability/availabilityService.d.ts.map +1 -1
- package/src/lib/availability/availabilityService.js +12 -5
- package/src/lib/availability/availabilityService.js.map +1 -1
- package/src/lib/availability/blockRegistry.d.ts +45 -3
- package/src/lib/availability/blockRegistry.d.ts.map +1 -1
- package/src/lib/availability/blockRegistry.js +123 -5
- package/src/lib/availability/blockRegistry.js.map +1 -1
- package/src/lib/availability/discoveryProtocol.d.ts +30 -1
- package/src/lib/availability/discoveryProtocol.d.ts.map +1 -1
- package/src/lib/availability/discoveryProtocol.js +76 -0
- package/src/lib/availability/discoveryProtocol.js.map +1 -1
- package/src/lib/availability/gossipService.d.ts +45 -6
- package/src/lib/availability/gossipService.d.ts.map +1 -1
- package/src/lib/availability/gossipService.js +177 -5
- package/src/lib/availability/gossipService.js.map +1 -1
- package/src/lib/availability/reconciliationService.d.ts +88 -1
- package/src/lib/availability/reconciliationService.d.ts.map +1 -1
- package/src/lib/availability/reconciliationService.js +246 -48
- package/src/lib/availability/reconciliationService.js.map +1 -1
- package/src/lib/blockFetch/blockFetcher.d.ts +100 -0
- package/src/lib/blockFetch/blockFetcher.d.ts.map +1 -0
- package/src/lib/blockFetch/blockFetcher.js +279 -0
- package/src/lib/blockFetch/blockFetcher.js.map +1 -0
- package/src/lib/blockFetch/fetchQueue.d.ts +88 -0
- package/src/lib/blockFetch/fetchQueue.d.ts.map +1 -0
- package/src/lib/blockFetch/fetchQueue.js +204 -0
- package/src/lib/blockFetch/fetchQueue.js.map +1 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.d.ts +65 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.d.ts.map +1 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.js +104 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.js.map +1 -0
- package/src/lib/blockFetch/index.d.ts +10 -0
- package/src/lib/blockFetch/index.d.ts.map +1 -0
- package/src/lib/blockFetch/index.js +13 -0
- package/src/lib/blockFetch/index.js.map +1 -0
- package/src/lib/controllers/api/brightpass.d.ts +72 -0
- package/src/lib/controllers/api/brightpass.d.ts.map +1 -0
- package/src/lib/controllers/api/brightpass.js +577 -0
- package/src/lib/controllers/api/brightpass.js.map +1 -0
- package/src/lib/controllers/api/channels.d.ts +122 -0
- package/src/lib/controllers/api/channels.d.ts.map +1 -0
- package/src/lib/controllers/api/channels.js +701 -0
- package/src/lib/controllers/api/channels.js.map +1 -0
- package/src/lib/controllers/api/conversations.d.ts +89 -0
- package/src/lib/controllers/api/conversations.d.ts.map +1 -0
- package/src/lib/controllers/api/conversations.js +259 -0
- package/src/lib/controllers/api/conversations.js.map +1 -0
- package/src/lib/controllers/api/emails.d.ts +122 -0
- package/src/lib/controllers/api/emails.d.ts.map +1 -0
- package/src/lib/controllers/api/emails.js +494 -0
- package/src/lib/controllers/api/emails.js.map +1 -0
- package/src/lib/controllers/api/explodingMessages.d.ts +79 -0
- package/src/lib/controllers/api/explodingMessages.d.ts.map +1 -0
- package/src/lib/controllers/api/explodingMessages.js +378 -0
- package/src/lib/controllers/api/explodingMessages.js.map +1 -0
- package/src/lib/controllers/api/groups.d.ts +94 -0
- package/src/lib/controllers/api/groups.d.ts.map +1 -0
- package/src/lib/controllers/api/groups.js +484 -0
- package/src/lib/controllers/api/groups.js.map +1 -0
- package/src/lib/controllers/api/index.d.ts +6 -0
- package/src/lib/controllers/api/index.d.ts.map +1 -1
- package/src/lib/controllers/api/index.js +6 -0
- package/src/lib/controllers/api/index.js.map +1 -1
- package/src/lib/controllers/api/messages.d.ts.map +1 -1
- package/src/lib/controllers/api/messages.js +2 -1
- package/src/lib/controllers/api/messages.js.map +1 -1
- package/src/lib/controllers/api/sync.d.ts +38 -2
- package/src/lib/controllers/api/sync.d.ts.map +1 -1
- package/src/lib/controllers/api/sync.js +89 -0
- package/src/lib/controllers/api/sync.js.map +1 -1
- package/src/lib/controllers/crypto/gitController.d.ts +70 -0
- package/src/lib/controllers/crypto/gitController.d.ts.map +1 -0
- package/src/lib/controllers/crypto/gitController.js +306 -0
- package/src/lib/controllers/crypto/gitController.js.map +1 -0
- package/src/lib/controllers/crypto/index.d.ts +3 -0
- package/src/lib/controllers/crypto/index.d.ts.map +1 -0
- package/src/lib/controllers/crypto/index.js +6 -0
- package/src/lib/controllers/crypto/index.js.map +1 -0
- package/src/lib/controllers/crypto/walletController.d.ts +64 -0
- package/src/lib/controllers/crypto/walletController.d.ts.map +1 -0
- package/src/lib/controllers/crypto/walletController.js +260 -0
- package/src/lib/controllers/crypto/walletController.js.map +1 -0
- package/src/lib/controllers/identity/deviceController.d.ts +96 -0
- package/src/lib/controllers/identity/deviceController.d.ts.map +1 -0
- package/src/lib/controllers/identity/deviceController.js +355 -0
- package/src/lib/controllers/identity/deviceController.js.map +1 -0
- package/src/lib/controllers/identity/directoryController.d.ts +75 -0
- package/src/lib/controllers/identity/directoryController.d.ts.map +1 -0
- package/src/lib/controllers/identity/directoryController.js +288 -0
- package/src/lib/controllers/identity/directoryController.js.map +1 -0
- package/src/lib/controllers/identity/identityProofController.d.ts +94 -0
- package/src/lib/controllers/identity/identityProofController.d.ts.map +1 -0
- package/src/lib/controllers/identity/identityProofController.js +454 -0
- package/src/lib/controllers/identity/identityProofController.js.map +1 -0
- package/src/lib/controllers/identity/index.d.ts +4 -0
- package/src/lib/controllers/identity/index.d.ts.map +1 -0
- package/src/lib/controllers/identity/index.js +7 -0
- package/src/lib/controllers/identity/index.js.map +1 -0
- package/src/lib/controllers/index.d.ts +2 -0
- package/src/lib/controllers/index.d.ts.map +1 -1
- package/src/lib/controllers/index.js +2 -0
- package/src/lib/controllers/index.js.map +1 -1
- package/src/lib/encryption/encryptedMetadataService.d.ts +87 -0
- package/src/lib/encryption/encryptedMetadataService.d.ts.map +1 -0
- package/src/lib/encryption/encryptedMetadataService.js +224 -0
- package/src/lib/encryption/encryptedMetadataService.js.map +1 -0
- package/src/lib/encryption/encryptionAwareReplication.d.ts +76 -0
- package/src/lib/encryption/encryptionAwareReplication.d.ts.map +1 -0
- package/src/lib/encryption/encryptionAwareReplication.js +116 -0
- package/src/lib/encryption/encryptionAwareReplication.js.map +1 -0
- package/src/lib/encryption/errors.d.ts +49 -0
- package/src/lib/encryption/errors.d.ts.map +1 -0
- package/src/lib/encryption/errors.js +80 -0
- package/src/lib/encryption/errors.js.map +1 -0
- package/src/lib/encryption/index.d.ts +6 -0
- package/src/lib/encryption/index.d.ts.map +1 -0
- package/src/lib/encryption/index.js +9 -0
- package/src/lib/encryption/index.js.map +1 -0
- package/src/lib/encryption/poolEncryptionService.d.ts +94 -0
- package/src/lib/encryption/poolEncryptionService.d.ts.map +1 -0
- package/src/lib/encryption/poolEncryptionService.js +252 -0
- package/src/lib/encryption/poolEncryptionService.js.map +1 -0
- package/src/lib/encryption/poolKeyManager.d.ts +82 -0
- package/src/lib/encryption/poolKeyManager.d.ts.map +1 -0
- package/src/lib/encryption/poolKeyManager.js +156 -0
- package/src/lib/encryption/poolKeyManager.js.map +1 -0
- package/src/lib/environment.d.ts +3 -0
- package/src/lib/environment.d.ts.map +1 -1
- package/src/lib/environment.js +5 -0
- package/src/lib/environment.js.map +1 -1
- package/src/lib/interfaces/environment.d.ts +7 -1
- package/src/lib/interfaces/environment.d.ts.map +1 -1
- package/src/lib/interfaces/index.d.ts +0 -1
- package/src/lib/interfaces/index.d.ts.map +1 -1
- package/src/lib/interfaces/requests/getBlockDataRequest.d.ts +12 -0
- package/src/lib/interfaces/requests/getBlockDataRequest.d.ts.map +1 -0
- package/src/lib/interfaces/{blockStore.js → requests/getBlockDataRequest.js} +1 -1
- package/src/lib/interfaces/requests/getBlockDataRequest.js.map +1 -0
- package/src/lib/interfaces/requests/index.d.ts +1 -0
- package/src/lib/interfaces/requests/index.d.ts.map +1 -1
- package/src/lib/routers/api.d.ts +54 -1
- package/src/lib/routers/api.d.ts.map +1 -1
- package/src/lib/routers/api.js +77 -0
- package/src/lib/routers/api.js.map +1 -1
- package/src/lib/services/blockStore.d.ts +5 -2
- package/src/lib/services/blockStore.d.ts.map +1 -1
- package/src/lib/services/blockStore.js +4 -0
- package/src/lib/services/blockStore.js.map +1 -1
- package/src/lib/services/brightpass/auditLogger.d.ts +77 -0
- package/src/lib/services/brightpass/auditLogger.d.ts.map +1 -0
- package/src/lib/services/brightpass/auditLogger.js +184 -0
- package/src/lib/services/brightpass/auditLogger.js.map +1 -0
- package/src/lib/services/brightpass/vaultEncryption.d.ts +82 -0
- package/src/lib/services/brightpass/vaultEncryption.d.ts.map +1 -0
- package/src/lib/services/brightpass/vaultEncryption.js +144 -0
- package/src/lib/services/brightpass/vaultEncryption.js.map +1 -0
- package/src/lib/services/brightpass.d.ts +294 -0
- package/src/lib/services/brightpass.d.ts.map +1 -0
- package/src/lib/services/brightpass.js +1260 -0
- package/src/lib/services/brightpass.js.map +1 -0
- package/src/lib/services/eventNotificationSystem.d.ts +69 -3
- package/src/lib/services/eventNotificationSystem.d.ts.map +1 -1
- package/src/lib/services/eventNotificationSystem.js +200 -0
- package/src/lib/services/eventNotificationSystem.js.map +1 -1
- package/src/lib/services/expirationScheduler.d.ts +90 -0
- package/src/lib/services/expirationScheduler.d.ts.map +1 -0
- package/src/lib/services/expirationScheduler.js +131 -0
- package/src/lib/services/expirationScheduler.js.map +1 -0
- package/src/lib/services/fecUsageExample.d.ts +2 -2
- package/src/lib/services/index.d.ts +2 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +2 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/paginationService.d.ts +18 -0
- package/src/lib/services/paginationService.d.ts.map +1 -0
- package/src/lib/services/paginationService.js +32 -0
- package/src/lib/services/paginationService.js.map +1 -0
- package/src/lib/services/presenceService.d.ts +76 -0
- package/src/lib/services/presenceService.d.ts.map +1 -0
- package/src/lib/services/presenceService.js +143 -0
- package/src/lib/services/presenceService.js.map +1 -0
- package/src/lib/services/wireConversationPromotion.d.ts +23 -0
- package/src/lib/services/wireConversationPromotion.d.ts.map +1 -0
- package/src/lib/services/wireConversationPromotion.js +26 -0
- package/src/lib/services/wireConversationPromotion.js.map +1 -0
- package/src/lib/stores/availabilityAwareBlockStore.d.ts +115 -10
- package/src/lib/stores/availabilityAwareBlockStore.d.ts.map +1 -1
- package/src/lib/stores/availabilityAwareBlockStore.js +267 -23
- package/src/lib/stores/availabilityAwareBlockStore.js.map +1 -1
- package/src/lib/stores/diskBlockAsyncStore.d.ts +81 -2
- package/src/lib/stores/diskBlockAsyncStore.d.ts.map +1 -1
- package/src/lib/stores/diskBlockAsyncStore.js +297 -10
- package/src/lib/stores/diskBlockAsyncStore.js.map +1 -1
- package/src/lib/utils/communicationValidation.d.ts +44 -0
- package/src/lib/utils/communicationValidation.d.ts.map +1 -0
- package/src/lib/utils/communicationValidation.js +291 -0
- package/src/lib/utils/communicationValidation.js.map +1 -0
- package/src/lib/utils/emailValidation.d.ts +19 -0
- package/src/lib/utils/emailValidation.d.ts.map +1 -0
- package/src/lib/utils/emailValidation.js +232 -0
- package/src/lib/utils/emailValidation.js.map +1 -0
- package/src/lib/interfaces/blockStore.d.ts +0 -7
- package/src/lib/interfaces/blockStore.d.ts.map +0 -1
- package/src/lib/interfaces/blockStore.js.map +0 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview BlockFetcher Implementation
|
|
4
|
+
*
|
|
5
|
+
* Retrieves block data from remote nodes with:
|
|
6
|
+
* - Checksum verification
|
|
7
|
+
* - Retry logic with exponential backoff
|
|
8
|
+
* - Node health tracking (cooldown)
|
|
9
|
+
* - Pool-scoped storage via putInPool
|
|
10
|
+
* - Pool metadata validation (PoolMismatchError on mismatch)
|
|
11
|
+
*
|
|
12
|
+
* @see cross-node-eventual-consistency design, Section 9
|
|
13
|
+
* @see pool-scoped-whitening requirements 7.1, 7.2, 7.3, 7.4
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.BlockFetcher = void 0;
|
|
17
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
18
|
+
/**
|
|
19
|
+
* BlockFetcher retrieves blocks from remote nodes, verifies checksums,
|
|
20
|
+
* stores them in the correct pool, and validates pool metadata.
|
|
21
|
+
*
|
|
22
|
+
* Pool-scoped fetch behavior (Requirements 7.1–7.4):
|
|
23
|
+
* - When poolId is provided, fetched blocks are stored via putInPool(poolId, data)
|
|
24
|
+
* - The fetcher verifies that the block's metadata poolId matches the requested poolId
|
|
25
|
+
* - PoolMismatchError is thrown when metadata doesn't match
|
|
26
|
+
* - Tuple reconstruction callers pass the same poolId for all blocks
|
|
27
|
+
*/
|
|
28
|
+
class BlockFetcher {
|
|
29
|
+
constructor(transport, availabilityService, store, config = brightchain_lib_1.DEFAULT_BLOCK_FETCHER_CONFIG, gossipService, fetchQueue) {
|
|
30
|
+
this.transport = transport;
|
|
31
|
+
this.availabilityService = availabilityService;
|
|
32
|
+
this.store = store;
|
|
33
|
+
this.config = config;
|
|
34
|
+
this.gossipService = gossipService;
|
|
35
|
+
this.fetchQueue = fetchQueue;
|
|
36
|
+
this.nodeCooldowns = new Map();
|
|
37
|
+
this.checksumService = new brightchain_lib_1.ChecksumService();
|
|
38
|
+
this.running = false;
|
|
39
|
+
/**
|
|
40
|
+
* Bound handler for gossip announcements, stored so we can unsubscribe in stop().
|
|
41
|
+
* Only set when proactiveFetchEnabled is true and gossipService is provided.
|
|
42
|
+
*/
|
|
43
|
+
this.announcementHandler = null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fetch a block from remote nodes and store it locally.
|
|
47
|
+
*
|
|
48
|
+
* The entire operation is bounded by `fetchTimeoutMs` (Req 1.6).
|
|
49
|
+
*
|
|
50
|
+
* When poolId is provided:
|
|
51
|
+
* 1. The block is stored in the specified pool via putInPool (Req 7.1)
|
|
52
|
+
* 2. After storage, the block's metadata poolId is verified against the requested poolId (Req 7.2)
|
|
53
|
+
* 3. If metadata doesn't match, the block is rejected with PoolMismatchError (Req 7.3)
|
|
54
|
+
*
|
|
55
|
+
* For tuple reconstruction, callers pass the same poolId for all blocks (Req 7.4).
|
|
56
|
+
*/
|
|
57
|
+
async fetchBlock(blockId, poolId) {
|
|
58
|
+
return this.withTimeout(blockId, () => this.doFetchBlock(blockId, poolId));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Core fetch logic: query locations, filter cooldowns, try nodes in order.
|
|
62
|
+
*/
|
|
63
|
+
async doFetchBlock(blockId, poolId) {
|
|
64
|
+
const locations = await this.availabilityService.getBlockLocations(blockId);
|
|
65
|
+
const candidateNodes = locations
|
|
66
|
+
.map((loc) => loc.nodeId)
|
|
67
|
+
.filter((nodeId) => this.isNodeAvailable(nodeId));
|
|
68
|
+
if (candidateNodes.length === 0) {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: `No available nodes for block ${blockId}`,
|
|
72
|
+
attemptedNodes: [],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const attemptedNodes = [];
|
|
76
|
+
for (const nodeId of candidateNodes) {
|
|
77
|
+
const result = await this.tryFetchFromNode(nodeId, blockId, poolId, attemptedNodes);
|
|
78
|
+
if (result) {
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
error: `All ${candidateNodes.length} candidate nodes failed for block ${blockId}`,
|
|
85
|
+
attemptedNodes,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Try fetching a block from a single node with retries.
|
|
90
|
+
* Returns a successful BlockFetchResult or null if all retries failed.
|
|
91
|
+
*/
|
|
92
|
+
async tryFetchFromNode(nodeId, blockId, poolId, attemptedNodes) {
|
|
93
|
+
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
94
|
+
try {
|
|
95
|
+
if (attempt > 0) {
|
|
96
|
+
const delay = this.config.retryBaseDelayMs * Math.pow(2, attempt - 1);
|
|
97
|
+
await this.sleep(delay);
|
|
98
|
+
}
|
|
99
|
+
const data = await this.transport.fetchBlockFromNode(nodeId, blockId, poolId);
|
|
100
|
+
// Verify checksum matches blockId
|
|
101
|
+
const computedChecksum = this.checksumService
|
|
102
|
+
.calculateChecksum(data)
|
|
103
|
+
.toHex();
|
|
104
|
+
if (computedChecksum !== blockId) {
|
|
105
|
+
const msg = `Checksum mismatch: expected ${blockId}, got ${computedChecksum}`;
|
|
106
|
+
attemptedNodes.push({ nodeId, error: msg });
|
|
107
|
+
this.markNodeUnavailable(nodeId);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
// Store the block in the correct pool
|
|
111
|
+
await this.storeBlock(blockId, data, poolId);
|
|
112
|
+
// Validate pool metadata if poolId was specified (Req 7.2, 7.3)
|
|
113
|
+
if (poolId) {
|
|
114
|
+
await this.validatePoolMetadata(blockId, poolId);
|
|
115
|
+
}
|
|
116
|
+
attemptedNodes.push({ nodeId });
|
|
117
|
+
return {
|
|
118
|
+
success: true,
|
|
119
|
+
data,
|
|
120
|
+
attemptedNodes,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
// Re-throw PoolMismatchError immediately — don't retry pool violations
|
|
125
|
+
if (error instanceof brightchain_lib_1.PoolMismatchError) {
|
|
126
|
+
attemptedNodes.push({ nodeId, error: error.message });
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
if (error instanceof brightchain_lib_1.BlockFetchError) {
|
|
130
|
+
attemptedNodes.push({ nodeId, error: error.message });
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
134
|
+
// Only record the final attempt failure
|
|
135
|
+
if (attempt === this.config.maxRetries) {
|
|
136
|
+
attemptedNodes.push({ nodeId, error: errorMsg });
|
|
137
|
+
this.markNodeUnavailable(nodeId);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Store a fetched block. When poolId is provided and the store supports pools,
|
|
145
|
+
* the block is stored in the specified pool via putInPool (Req 7.1).
|
|
146
|
+
* Otherwise falls back to the standard put method.
|
|
147
|
+
*/
|
|
148
|
+
async storeBlock(blockId, data, poolId) {
|
|
149
|
+
if (poolId && (0, brightchain_lib_1.isPooledBlockStore)(this.store)) {
|
|
150
|
+
await this.store.putInPool(poolId, data);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
await this.store.put(blockId, data);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Validate that the stored block's metadata poolId matches the requested poolId.
|
|
158
|
+
* Throws PoolMismatchError if there's a mismatch (Req 7.2, 7.3).
|
|
159
|
+
*/
|
|
160
|
+
async validatePoolMetadata(blockId, expectedPoolId) {
|
|
161
|
+
const metadata = await this.store.getMetadata(blockId);
|
|
162
|
+
if (metadata?.poolId && metadata.poolId !== expectedPoolId) {
|
|
163
|
+
throw new brightchain_lib_1.PoolMismatchError(blockId, expectedPoolId, metadata.poolId);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Check if a node is currently available (not in cooldown) */
|
|
167
|
+
isNodeAvailable(nodeId) {
|
|
168
|
+
const cooldownUntil = this.nodeCooldowns.get(nodeId);
|
|
169
|
+
if (cooldownUntil === undefined) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
if (Date.now() >= cooldownUntil) {
|
|
173
|
+
this.nodeCooldowns.delete(nodeId);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
/** Mark a node as unavailable for the configured cooldown period */
|
|
179
|
+
markNodeUnavailable(nodeId) {
|
|
180
|
+
this.nodeCooldowns.set(nodeId, Date.now() + this.config.nodeCooldownMs);
|
|
181
|
+
}
|
|
182
|
+
/** Get the current configuration */
|
|
183
|
+
getConfig() {
|
|
184
|
+
return { ...this.config };
|
|
185
|
+
}
|
|
186
|
+
/** Start the fetcher and subscribe to gossip announcements if proactive fetching is enabled */
|
|
187
|
+
start() {
|
|
188
|
+
this.running = true;
|
|
189
|
+
if (this.config.proactiveFetchEnabled &&
|
|
190
|
+
this.gossipService &&
|
|
191
|
+
this.fetchQueue) {
|
|
192
|
+
this.announcementHandler = (announcement) => {
|
|
193
|
+
void this.handleProactiveAnnouncement(announcement);
|
|
194
|
+
};
|
|
195
|
+
this.gossipService.onAnnouncement(this.announcementHandler);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** Stop the fetcher, unsubscribe from gossip, and clean up */
|
|
199
|
+
stop() {
|
|
200
|
+
if (this.announcementHandler && this.gossipService) {
|
|
201
|
+
this.gossipService.offAnnouncement(this.announcementHandler);
|
|
202
|
+
this.announcementHandler = null;
|
|
203
|
+
}
|
|
204
|
+
this.running = false;
|
|
205
|
+
this.nodeCooldowns.clear();
|
|
206
|
+
}
|
|
207
|
+
/** Whether the fetcher is currently running */
|
|
208
|
+
isRunning() {
|
|
209
|
+
return this.running;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Handle a gossip announcement for proactive fetching.
|
|
213
|
+
* Checks if the block is already local; if not, enqueues a low-priority fetch.
|
|
214
|
+
*
|
|
215
|
+
* @see Requirements 6.1, 6.2
|
|
216
|
+
*/
|
|
217
|
+
async handleProactiveAnnouncement(announcement) {
|
|
218
|
+
// Only proactively fetch for 'add' announcements
|
|
219
|
+
if (announcement.type !== 'add') {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const { blockId } = announcement;
|
|
223
|
+
try {
|
|
224
|
+
const state = await this.availabilityService.getAvailabilityState(blockId);
|
|
225
|
+
// Block is already locally accessible — no need to fetch
|
|
226
|
+
if ((0, brightchain_lib_1.isLocallyAccessible)(state)) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Enqueue a low-priority fetch via the fetch queue
|
|
230
|
+
if (this.fetchQueue) {
|
|
231
|
+
// Fire-and-forget: we don't need to await the result for proactive fetches
|
|
232
|
+
void this.fetchQueue.enqueue(blockId);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Proactive fetch is best-effort; swallow errors silently
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Race the fetch operation against fetchTimeoutMs (Req 1.6).
|
|
241
|
+
* Returns a FetchTimeoutError result if the timeout fires first.
|
|
242
|
+
*/
|
|
243
|
+
withTimeout(blockId, operation) {
|
|
244
|
+
const { fetchTimeoutMs } = this.config;
|
|
245
|
+
return new Promise((resolve, reject) => {
|
|
246
|
+
let settled = false;
|
|
247
|
+
const timer = setTimeout(() => {
|
|
248
|
+
if (settled)
|
|
249
|
+
return;
|
|
250
|
+
settled = true;
|
|
251
|
+
resolve({
|
|
252
|
+
success: false,
|
|
253
|
+
error: `Fetch for block ${blockId} timed out after ${fetchTimeoutMs}ms`,
|
|
254
|
+
attemptedNodes: [],
|
|
255
|
+
});
|
|
256
|
+
}, fetchTimeoutMs);
|
|
257
|
+
operation()
|
|
258
|
+
.then((result) => {
|
|
259
|
+
if (settled)
|
|
260
|
+
return;
|
|
261
|
+
settled = true;
|
|
262
|
+
clearTimeout(timer);
|
|
263
|
+
resolve(result);
|
|
264
|
+
})
|
|
265
|
+
.catch((err) => {
|
|
266
|
+
if (settled)
|
|
267
|
+
return;
|
|
268
|
+
settled = true;
|
|
269
|
+
clearTimeout(timer);
|
|
270
|
+
reject(err);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
sleep(ms) {
|
|
275
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
exports.BlockFetcher = BlockFetcher;
|
|
279
|
+
//# sourceMappingURL=blockFetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blockFetcher.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/blockFetch/blockFetcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FetchQueue Implementation
|
|
3
|
+
*
|
|
4
|
+
* Priority queue with deduplication for remote block fetch requests.
|
|
5
|
+
* - Coalesces concurrent requests for the same blockId into a single fetch
|
|
6
|
+
* - Bounds concurrency to maxConcurrency simultaneous fetches
|
|
7
|
+
* - Orders pending fetches by waiter count (more waiters = higher priority)
|
|
8
|
+
* - Enforces per-request timeout with cancellation for all waiters
|
|
9
|
+
*
|
|
10
|
+
* The queue delegates actual fetch execution to an injected executor function,
|
|
11
|
+
* which allows the BlockFetcher to handle node selection, retries, and
|
|
12
|
+
* checksum verification while the queue handles scheduling concerns.
|
|
13
|
+
*
|
|
14
|
+
* @see cross-node-eventual-consistency design, Section 10
|
|
15
|
+
* @see Requirements 4.1, 4.2, 4.3, 4.4
|
|
16
|
+
*/
|
|
17
|
+
import { BlockFetchResult, FetchQueueConfig, IFetchQueue, PoolId } from '@brightchain/brightchain-lib';
|
|
18
|
+
/**
|
|
19
|
+
* Function type for the fetch executor.
|
|
20
|
+
* The queue calls this to perform the actual block retrieval.
|
|
21
|
+
* The executor is responsible for node selection, retries, and verification.
|
|
22
|
+
*/
|
|
23
|
+
export type FetchExecutor = (blockId: string, poolId?: PoolId) => Promise<BlockFetchResult>;
|
|
24
|
+
/**
|
|
25
|
+
* FetchQueue manages block fetch requests with deduplication, priority ordering,
|
|
26
|
+
* and bounded concurrency.
|
|
27
|
+
*
|
|
28
|
+
* Deduplication (Req 4.1): If blockId is already pending or active, new callers
|
|
29
|
+
* are appended to the existing waiters list — only one fetch executes.
|
|
30
|
+
*
|
|
31
|
+
* Concurrency (Req 4.2): At most `maxConcurrency` fetches run in parallel.
|
|
32
|
+
*
|
|
33
|
+
* Priority (Req 4.3): When a slot opens, the pending entry with the most waiters
|
|
34
|
+
* is dispatched next.
|
|
35
|
+
*
|
|
36
|
+
* Timeout (Req 4.4): Each active fetch is bounded by `fetchTimeoutMs`. On timeout,
|
|
37
|
+
* all waiters for that blockId receive a FetchTimeoutError.
|
|
38
|
+
*/
|
|
39
|
+
export declare class FetchQueue implements IFetchQueue {
|
|
40
|
+
private readonly executor;
|
|
41
|
+
/** Queued blockIds not yet dispatched — keyed by blockId */
|
|
42
|
+
private readonly pending;
|
|
43
|
+
/**
|
|
44
|
+
* Currently executing blockIds.
|
|
45
|
+
* Maps blockId to its waiters list and the timeout handle for cancellation.
|
|
46
|
+
*/
|
|
47
|
+
private readonly active;
|
|
48
|
+
private readonly config;
|
|
49
|
+
/**
|
|
50
|
+
* @param executor - Function that performs the actual block fetch.
|
|
51
|
+
* The queue calls this when dispatching; the executor handles node
|
|
52
|
+
* selection, retries, and checksum verification.
|
|
53
|
+
* @param config - Optional partial config; merged with defaults.
|
|
54
|
+
*/
|
|
55
|
+
constructor(executor: FetchExecutor, config?: Partial<FetchQueueConfig>);
|
|
56
|
+
/**
|
|
57
|
+
* Enqueue a block fetch request.
|
|
58
|
+
* If the blockId is already pending or active, the caller's promise is
|
|
59
|
+
* coalesced with the existing request (Req 4.1).
|
|
60
|
+
*/
|
|
61
|
+
enqueue(blockId: string, poolId?: PoolId): Promise<BlockFetchResult>;
|
|
62
|
+
/** Number of requests waiting to be dispatched */
|
|
63
|
+
getPendingCount(): number;
|
|
64
|
+
/** Number of fetches currently in progress */
|
|
65
|
+
getActiveCount(): number;
|
|
66
|
+
/**
|
|
67
|
+
* Cancel all pending and active fetch requests.
|
|
68
|
+
* Every waiter receives a rejection with the given reason.
|
|
69
|
+
*/
|
|
70
|
+
cancelAll(reason: string): void;
|
|
71
|
+
/** Current queue configuration */
|
|
72
|
+
getConfig(): FetchQueueConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Dispatch pending entries up to the concurrency limit.
|
|
75
|
+
* Selects the entry with the most waiters first (Req 4.3).
|
|
76
|
+
*/
|
|
77
|
+
private drain;
|
|
78
|
+
/**
|
|
79
|
+
* Pick and remove the pending entry with the most waiters.
|
|
80
|
+
*/
|
|
81
|
+
private pickHighestPriority;
|
|
82
|
+
/**
|
|
83
|
+
* Dispatch a single fetch: move entry to active, start the executor,
|
|
84
|
+
* and arm the timeout (Req 4.4).
|
|
85
|
+
*/
|
|
86
|
+
private dispatch;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=fetchQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchQueue.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/blockFetch/fetchQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,gBAAgB,EAEhB,gBAAgB,EAEhB,WAAW,EACX,MAAM,EACP,MAAM,8BAA8B,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,KACZ,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAe/B;;;;;;;;;;;;;;GAcG;AACH,qBAAa,UAAW,YAAW,WAAW;IAsB1C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IArB3B,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;IAEhE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGT;IAEd,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAE1C;;;;;OAKG;gBAEgB,QAAQ,EAAE,aAAa,EACxC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAKpC;;;;OAIG;IACI,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8B3E,kDAAkD;IAC3C,eAAe,IAAI,MAAM;IAIhC,8CAA8C;IACvC,cAAc,IAAI,MAAM;IAI/B;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAmBtC,kCAAkC;IAC3B,SAAS,IAAI,gBAAgB;IAMpC;;;OAGG;IACH,OAAO,CAAC,KAAK;IAWb;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAmEjB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview FetchQueue Implementation
|
|
4
|
+
*
|
|
5
|
+
* Priority queue with deduplication for remote block fetch requests.
|
|
6
|
+
* - Coalesces concurrent requests for the same blockId into a single fetch
|
|
7
|
+
* - Bounds concurrency to maxConcurrency simultaneous fetches
|
|
8
|
+
* - Orders pending fetches by waiter count (more waiters = higher priority)
|
|
9
|
+
* - Enforces per-request timeout with cancellation for all waiters
|
|
10
|
+
*
|
|
11
|
+
* The queue delegates actual fetch execution to an injected executor function,
|
|
12
|
+
* which allows the BlockFetcher to handle node selection, retries, and
|
|
13
|
+
* checksum verification while the queue handles scheduling concerns.
|
|
14
|
+
*
|
|
15
|
+
* @see cross-node-eventual-consistency design, Section 10
|
|
16
|
+
* @see Requirements 4.1, 4.2, 4.3, 4.4
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.FetchQueue = void 0;
|
|
20
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
21
|
+
/**
|
|
22
|
+
* FetchQueue manages block fetch requests with deduplication, priority ordering,
|
|
23
|
+
* and bounded concurrency.
|
|
24
|
+
*
|
|
25
|
+
* Deduplication (Req 4.1): If blockId is already pending or active, new callers
|
|
26
|
+
* are appended to the existing waiters list — only one fetch executes.
|
|
27
|
+
*
|
|
28
|
+
* Concurrency (Req 4.2): At most `maxConcurrency` fetches run in parallel.
|
|
29
|
+
*
|
|
30
|
+
* Priority (Req 4.3): When a slot opens, the pending entry with the most waiters
|
|
31
|
+
* is dispatched next.
|
|
32
|
+
*
|
|
33
|
+
* Timeout (Req 4.4): Each active fetch is bounded by `fetchTimeoutMs`. On timeout,
|
|
34
|
+
* all waiters for that blockId receive a FetchTimeoutError.
|
|
35
|
+
*/
|
|
36
|
+
class FetchQueue {
|
|
37
|
+
/**
|
|
38
|
+
* @param executor - Function that performs the actual block fetch.
|
|
39
|
+
* The queue calls this when dispatching; the executor handles node
|
|
40
|
+
* selection, retries, and checksum verification.
|
|
41
|
+
* @param config - Optional partial config; merged with defaults.
|
|
42
|
+
*/
|
|
43
|
+
constructor(executor, config) {
|
|
44
|
+
this.executor = executor;
|
|
45
|
+
/** Queued blockIds not yet dispatched — keyed by blockId */
|
|
46
|
+
this.pending = new Map();
|
|
47
|
+
/**
|
|
48
|
+
* Currently executing blockIds.
|
|
49
|
+
* Maps blockId to its waiters list and the timeout handle for cancellation.
|
|
50
|
+
*/
|
|
51
|
+
this.active = new Map();
|
|
52
|
+
this.config = { ...brightchain_lib_1.DEFAULT_FETCH_QUEUE_CONFIG, ...config };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Enqueue a block fetch request.
|
|
56
|
+
* If the blockId is already pending or active, the caller's promise is
|
|
57
|
+
* coalesced with the existing request (Req 4.1).
|
|
58
|
+
*/
|
|
59
|
+
enqueue(blockId, poolId) {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const waiter = { resolve, reject };
|
|
62
|
+
// Coalesce with an already-active fetch
|
|
63
|
+
const activeEntry = this.active.get(blockId);
|
|
64
|
+
if (activeEntry) {
|
|
65
|
+
activeEntry.waiters.push(waiter);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Coalesce with a pending entry
|
|
69
|
+
const pendingEntry = this.pending.get(blockId);
|
|
70
|
+
if (pendingEntry) {
|
|
71
|
+
pendingEntry.waiters.push(waiter);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Create a new pending entry
|
|
75
|
+
this.pending.set(blockId, {
|
|
76
|
+
blockId,
|
|
77
|
+
poolId,
|
|
78
|
+
waiters: [waiter],
|
|
79
|
+
});
|
|
80
|
+
// Try to dispatch immediately if there's capacity
|
|
81
|
+
this.drain();
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/** Number of requests waiting to be dispatched */
|
|
85
|
+
getPendingCount() {
|
|
86
|
+
return this.pending.size;
|
|
87
|
+
}
|
|
88
|
+
/** Number of fetches currently in progress */
|
|
89
|
+
getActiveCount() {
|
|
90
|
+
return this.active.size;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Cancel all pending and active fetch requests.
|
|
94
|
+
* Every waiter receives a rejection with the given reason.
|
|
95
|
+
*/
|
|
96
|
+
cancelAll(reason) {
|
|
97
|
+
const error = new Error(reason);
|
|
98
|
+
for (const [, entry] of this.pending) {
|
|
99
|
+
for (const waiter of entry.waiters) {
|
|
100
|
+
waiter.reject(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
this.pending.clear();
|
|
104
|
+
for (const [, entry] of this.active) {
|
|
105
|
+
clearTimeout(entry.timeoutHandle);
|
|
106
|
+
for (const waiter of entry.waiters) {
|
|
107
|
+
waiter.reject(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.active.clear();
|
|
111
|
+
}
|
|
112
|
+
/** Current queue configuration */
|
|
113
|
+
getConfig() {
|
|
114
|
+
return { ...this.config };
|
|
115
|
+
}
|
|
116
|
+
// ── Private helpers ──────────────────────────────────────────────────
|
|
117
|
+
/**
|
|
118
|
+
* Dispatch pending entries up to the concurrency limit.
|
|
119
|
+
* Selects the entry with the most waiters first (Req 4.3).
|
|
120
|
+
*/
|
|
121
|
+
drain() {
|
|
122
|
+
while (this.active.size < this.config.maxConcurrency &&
|
|
123
|
+
this.pending.size > 0) {
|
|
124
|
+
const next = this.pickHighestPriority();
|
|
125
|
+
if (!next)
|
|
126
|
+
break;
|
|
127
|
+
this.dispatch(next);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Pick and remove the pending entry with the most waiters.
|
|
132
|
+
*/
|
|
133
|
+
pickHighestPriority() {
|
|
134
|
+
let best;
|
|
135
|
+
for (const [, entry] of this.pending) {
|
|
136
|
+
if (!best || entry.waiters.length > best.waiters.length) {
|
|
137
|
+
best = entry;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (best) {
|
|
141
|
+
this.pending.delete(best.blockId);
|
|
142
|
+
}
|
|
143
|
+
return best;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Dispatch a single fetch: move entry to active, start the executor,
|
|
147
|
+
* and arm the timeout (Req 4.4).
|
|
148
|
+
*/
|
|
149
|
+
dispatch(entry) {
|
|
150
|
+
const { blockId, poolId, waiters } = entry;
|
|
151
|
+
let settled = false;
|
|
152
|
+
const timeoutHandle = setTimeout(() => {
|
|
153
|
+
if (settled)
|
|
154
|
+
return;
|
|
155
|
+
settled = true;
|
|
156
|
+
const current = this.active.get(blockId);
|
|
157
|
+
this.active.delete(blockId);
|
|
158
|
+
const timeoutError = new brightchain_lib_1.FetchTimeoutError(blockId, this.config.fetchTimeoutMs);
|
|
159
|
+
if (current) {
|
|
160
|
+
for (const w of current.waiters) {
|
|
161
|
+
w.reject(timeoutError);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
this.drain();
|
|
165
|
+
}, this.config.fetchTimeoutMs);
|
|
166
|
+
this.active.set(blockId, { waiters, timeoutHandle });
|
|
167
|
+
this.executor(blockId, poolId)
|
|
168
|
+
.then((result) => {
|
|
169
|
+
if (settled)
|
|
170
|
+
return;
|
|
171
|
+
settled = true;
|
|
172
|
+
clearTimeout(timeoutHandle);
|
|
173
|
+
const current = this.active.get(blockId);
|
|
174
|
+
this.active.delete(blockId);
|
|
175
|
+
if (current) {
|
|
176
|
+
for (const w of current.waiters) {
|
|
177
|
+
w.resolve(result);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
this.drain();
|
|
181
|
+
})
|
|
182
|
+
.catch((err) => {
|
|
183
|
+
if (settled)
|
|
184
|
+
return;
|
|
185
|
+
settled = true;
|
|
186
|
+
clearTimeout(timeoutHandle);
|
|
187
|
+
const current = this.active.get(blockId);
|
|
188
|
+
this.active.delete(blockId);
|
|
189
|
+
const failResult = {
|
|
190
|
+
success: false,
|
|
191
|
+
error: err.message,
|
|
192
|
+
attemptedNodes: [],
|
|
193
|
+
};
|
|
194
|
+
if (current) {
|
|
195
|
+
for (const w of current.waiters) {
|
|
196
|
+
w.resolve(failResult);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
this.drain();
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
exports.FetchQueue = FetchQueue;
|
|
204
|
+
//# sourceMappingURL=fetchQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchQueue.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/blockFetch/fetchQueue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview HTTP Block Fetch Transport
|
|
3
|
+
*
|
|
4
|
+
* Implements IBlockFetchTransport using HTTP GET requests to remote nodes'
|
|
5
|
+
* SyncController `/api/sync/blocks/:blockId` endpoint.
|
|
6
|
+
*
|
|
7
|
+
* Node.js specific (uses fetch API available in Node 18+).
|
|
8
|
+
*
|
|
9
|
+
* @see cross-node-eventual-consistency design, Section 2
|
|
10
|
+
* @see Requirements 1.1, 5.2
|
|
11
|
+
*/
|
|
12
|
+
import { IBlockFetchTransport, PoolId } from '@brightchain/brightchain-lib';
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a node ID to its base URL (e.g., `http://node-address:port`).
|
|
15
|
+
* Implementations may use a static registry, DNS, or discovery service.
|
|
16
|
+
*/
|
|
17
|
+
export interface INodeAddressResolver {
|
|
18
|
+
/**
|
|
19
|
+
* Get the base URL for a given node.
|
|
20
|
+
* @param nodeId - The node identifier
|
|
21
|
+
* @returns The base URL (without trailing slash), or undefined if unknown
|
|
22
|
+
*/
|
|
23
|
+
getNodeBaseUrl(nodeId: string): string | undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Simple map-based node address resolver.
|
|
27
|
+
* Maps node IDs to their base URLs.
|
|
28
|
+
*/
|
|
29
|
+
export declare class MapNodeAddressResolver implements INodeAddressResolver {
|
|
30
|
+
private readonly nodeAddresses;
|
|
31
|
+
constructor(nodeAddresses: Map<string, string>);
|
|
32
|
+
getNodeBaseUrl(nodeId: string): string | undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* HTTP-based implementation of IBlockFetchTransport.
|
|
36
|
+
*
|
|
37
|
+
* Fetches block data from remote nodes via their SyncController endpoint:
|
|
38
|
+
* GET /api/sync/blocks/:blockId[?poolId=<poolId>]
|
|
39
|
+
*
|
|
40
|
+
* The response is JSON with `{ message, blockId, data }` where `data` is
|
|
41
|
+
* base64-encoded. This transport decodes the base64 data and returns raw bytes.
|
|
42
|
+
*
|
|
43
|
+
* @see Requirements 1.1 — Block fetching protocol
|
|
44
|
+
* @see Requirements 5.2 — Pool ID included in fetch request
|
|
45
|
+
*/
|
|
46
|
+
export declare class HttpBlockFetchTransport implements IBlockFetchTransport {
|
|
47
|
+
private readonly addressResolver;
|
|
48
|
+
constructor(addressResolver: INodeAddressResolver);
|
|
49
|
+
/**
|
|
50
|
+
* Fetch raw block data from a specific remote node via HTTP GET.
|
|
51
|
+
*
|
|
52
|
+
* @param nodeId - The target node identifier (resolved to URL via addressResolver)
|
|
53
|
+
* @param blockId - The block checksum/ID to fetch
|
|
54
|
+
* @param poolId - Optional pool scope; appended as query parameter
|
|
55
|
+
* @returns The raw block bytes decoded from the base64 response
|
|
56
|
+
* @throws BlockFetchError if the node address is unknown, HTTP request fails, or response is invalid
|
|
57
|
+
*/
|
|
58
|
+
fetchBlockFromNode(nodeId: string, blockId: string, poolId?: PoolId): Promise<Uint8Array>;
|
|
59
|
+
/**
|
|
60
|
+
* Build the full URL for the block fetch request.
|
|
61
|
+
* Format: {baseUrl}/api/sync/blocks/{blockId}[?poolId={poolId}]
|
|
62
|
+
*/
|
|
63
|
+
private buildUrl;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=httpBlockFetchTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpBlockFetchTransport.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/blockFetch/httpBlockFetchTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAGL,oBAAoB,EACpB,MAAM,EACP,MAAM,8BAA8B,CAAC;AAEtC;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACpD;AAED;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,oBAAoB;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAExD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAG1D;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,uBAAwB,YAAW,oBAAoB;IACtD,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAAf,eAAe,EAAE,oBAAoB;IAElE;;;;;;;;OAQG;IACU,kBAAkB,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,UAAU,CAAC;IA+DtB;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAUjB"}
|