@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
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @see Requirements 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6
|
|
9
9
|
*/
|
|
10
|
-
import { BaseBlock, BlockHandle, BlockStoreOptions, BrightenResult, CBLMagnetComponents, CBLStorageResult, CBLWhiteningOptions, Checksum, IAvailabilityService, IBlockMetadata, IBlockRegistry, IBlockStore, IGossipService, IReconciliationService, RawDataBlock, RecoveryResult } from '@brightchain/brightchain-lib';
|
|
10
|
+
import { BaseBlock, BlockFetcherConfig, BlockHandle, BlockStoreOptions, BrightenResult, CBLMagnetComponents, CBLStorageResult, CBLWhiteningOptions, Checksum, FetchQueueConfig, IAvailabilityService, IBlockFetcher, IBlockMetadata, IBlockRegistry, IBlockStore, IGossipService, IReconciliationService, PoolDeletionTombstoneConfig, PoolId, RawDataBlock, ReadConcern, RecoveryResult } from '@brightchain/brightchain-lib';
|
|
11
|
+
export { PoolDeletionTombstoneError } from '@brightchain/brightchain-lib';
|
|
11
12
|
/**
|
|
12
13
|
* Error thrown when an operation is attempted during partition mode
|
|
13
14
|
* that requires network access.
|
|
@@ -33,11 +34,39 @@ export interface AvailabilityAwareBlockStoreConfig {
|
|
|
33
34
|
* Default: true
|
|
34
35
|
*/
|
|
35
36
|
trackAccess?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Default read concern for getData calls when none is specified.
|
|
39
|
+
* Default: ReadConcern.Local (preserves backward compatibility)
|
|
40
|
+
*/
|
|
41
|
+
defaultReadConcern?: ReadConcern;
|
|
42
|
+
/**
|
|
43
|
+
* Configuration for the block fetcher service.
|
|
44
|
+
* Only relevant when an IBlockFetcher is provided.
|
|
45
|
+
*/
|
|
46
|
+
blockFetcherConfig?: BlockFetcherConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Configuration for the fetch queue.
|
|
49
|
+
* Only relevant when an IBlockFetcher is provided.
|
|
50
|
+
*/
|
|
51
|
+
fetchQueueConfig?: FetchQueueConfig;
|
|
52
|
+
/**
|
|
53
|
+
* Tombstone configuration for pool deletion tracking.
|
|
54
|
+
* Default: DEFAULT_TOMBSTONE_CONFIG (7 days TTL)
|
|
55
|
+
*/
|
|
56
|
+
tombstoneConfig?: PoolDeletionTombstoneConfig;
|
|
36
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolved configuration type for AvailabilityAwareBlockStore.
|
|
60
|
+
* Core fields are required; fetch-related configs remain optional since
|
|
61
|
+
* they are only meaningful when an IBlockFetcher is provided.
|
|
62
|
+
*/
|
|
63
|
+
export type ResolvedAvailabilityAwareBlockStoreConfig = Omit<Required<AvailabilityAwareBlockStoreConfig>, 'blockFetcherConfig' | 'fetchQueueConfig' | 'tombstoneConfig'> & Pick<AvailabilityAwareBlockStoreConfig, 'blockFetcherConfig' | 'fetchQueueConfig'> & {
|
|
64
|
+
tombstoneConfig: PoolDeletionTombstoneConfig;
|
|
65
|
+
};
|
|
37
66
|
/**
|
|
38
67
|
* Default configuration values.
|
|
39
68
|
*/
|
|
40
|
-
export declare const DEFAULT_AVAILABILITY_AWARE_BLOCK_STORE_CONFIG:
|
|
69
|
+
export declare const DEFAULT_AVAILABILITY_AWARE_BLOCK_STORE_CONFIG: ResolvedAvailabilityAwareBlockStoreConfig;
|
|
41
70
|
/**
|
|
42
71
|
* AvailabilityAwareBlockStore
|
|
43
72
|
*
|
|
@@ -78,6 +107,16 @@ export declare class AvailabilityAwareBlockStore implements IBlockStore {
|
|
|
78
107
|
* Configuration.
|
|
79
108
|
*/
|
|
80
109
|
private readonly config;
|
|
110
|
+
/**
|
|
111
|
+
* Optional block fetcher for remote block retrieval.
|
|
112
|
+
* When provided, enables Available and Consistent read concerns.
|
|
113
|
+
*/
|
|
114
|
+
private readonly blockFetcher?;
|
|
115
|
+
/**
|
|
116
|
+
* Tombstones for deleted pools. Blocks cannot be stored in a pool
|
|
117
|
+
* with an active tombstone until it expires.
|
|
118
|
+
*/
|
|
119
|
+
private readonly tombstones;
|
|
81
120
|
/**
|
|
82
121
|
* Create a new AvailabilityAwareBlockStore.
|
|
83
122
|
*
|
|
@@ -87,8 +126,9 @@ export declare class AvailabilityAwareBlockStore implements IBlockStore {
|
|
|
87
126
|
* @param gossipService - Service for block announcements
|
|
88
127
|
* @param reconciliationService - Service for pending sync queue
|
|
89
128
|
* @param config - Configuration options
|
|
129
|
+
* @param blockFetcher - Optional block fetcher for remote block retrieval
|
|
90
130
|
*/
|
|
91
|
-
constructor(innerStore: IBlockStore, registry: IBlockRegistry, availabilityService: IAvailabilityService, gossipService: IGossipService, reconciliationService: IReconciliationService, config: AvailabilityAwareBlockStoreConfig);
|
|
131
|
+
constructor(innerStore: IBlockStore, registry: IBlockRegistry, availabilityService: IAvailabilityService, gossipService: IGossipService, reconciliationService: IReconciliationService, config: AvailabilityAwareBlockStoreConfig, blockFetcher?: IBlockFetcher);
|
|
92
132
|
/**
|
|
93
133
|
* Get the block size for this store.
|
|
94
134
|
*/
|
|
@@ -101,15 +141,41 @@ export declare class AvailabilityAwareBlockStore implements IBlockStore {
|
|
|
101
141
|
*/
|
|
102
142
|
has(key: Checksum | string): Promise<boolean>;
|
|
103
143
|
/**
|
|
104
|
-
* Get a block's data.
|
|
144
|
+
* Get a block's data with optional read concern.
|
|
105
145
|
* Updates access metadata if tracking is enabled.
|
|
106
146
|
*
|
|
147
|
+
* Read concern behavior:
|
|
148
|
+
* - Local (default): return only locally available blocks, error for remote/unknown
|
|
149
|
+
* - Consistent: await remote fetch, store result, return or timeout
|
|
150
|
+
* - Available: try fetch with initialWaitMs, return PendingBlockError if not resolved
|
|
151
|
+
*
|
|
152
|
+
* During partition mode, remote blocks always throw PartitionModeError
|
|
153
|
+
* regardless of read concern.
|
|
154
|
+
*
|
|
107
155
|
* @param key - The block's checksum
|
|
156
|
+
* @param readConcern - Optional read concern level (defaults to config.defaultReadConcern)
|
|
108
157
|
* @returns Promise resolving to the block data
|
|
109
|
-
* @throws
|
|
110
|
-
* @
|
|
158
|
+
* @throws PartitionModeError if block is remote and system is in partition mode
|
|
159
|
+
* @throws PendingBlockError if Available concern and fetch not resolved in time
|
|
160
|
+
* @throws FetchTimeoutError if Consistent concern and fetch exceeds timeout
|
|
161
|
+
* @throws Error if block not found locally and concern is Local
|
|
162
|
+
* @see Requirements 2.2, 2.3, 2.4, 2.5, 7.3
|
|
111
163
|
*/
|
|
112
|
-
getData(key: Checksum): Promise<RawDataBlock>;
|
|
164
|
+
getData(key: Checksum, readConcern?: ReadConcern): Promise<RawDataBlock>;
|
|
165
|
+
/**
|
|
166
|
+
* Fetch a block with Consistent read concern.
|
|
167
|
+
* Awaits the full fetch result — returns the block or throws on timeout/failure.
|
|
168
|
+
*
|
|
169
|
+
* @see Requirements 2.4, 2.5
|
|
170
|
+
*/
|
|
171
|
+
private fetchBlockConsistent;
|
|
172
|
+
/**
|
|
173
|
+
* Fetch a block with Available read concern.
|
|
174
|
+
* Tries to fetch within initialWaitMs; throws PendingBlockError if not resolved in time.
|
|
175
|
+
*
|
|
176
|
+
* @see Requirements 2.3
|
|
177
|
+
*/
|
|
178
|
+
private fetchBlockAvailable;
|
|
113
179
|
/**
|
|
114
180
|
* Store a block's data with optional durability settings.
|
|
115
181
|
* Updates registry, availability state, and announces via gossip.
|
|
@@ -199,24 +265,45 @@ export declare class AvailabilityAwareBlockStore implements IBlockStore {
|
|
|
199
265
|
*/
|
|
200
266
|
verifyBlockIntegrity(key: Checksum | string): Promise<boolean>;
|
|
201
267
|
/**
|
|
202
|
-
* Get blocks that are pending replication.
|
|
268
|
+
* Get blocks that are pending replication, scoped by pool.
|
|
269
|
+
*
|
|
270
|
+
* A block's replication count for pool P = number of distinct nodes
|
|
271
|
+
* with a location record for that block with poolId: P.
|
|
272
|
+
* Blocks without a poolId use the inner store's default pending check.
|
|
203
273
|
*
|
|
204
274
|
* @returns Array of block checksums pending replication
|
|
275
|
+
* @see Requirements 6.1, 6.2
|
|
205
276
|
*/
|
|
206
277
|
getBlocksPendingReplication(): Promise<Checksum[]>;
|
|
207
278
|
/**
|
|
208
|
-
* Get blocks that are under-replicated.
|
|
279
|
+
* Get blocks that are under-replicated, scoped by pool.
|
|
280
|
+
*
|
|
281
|
+
* A block's replication count for pool P = number of distinct nodes
|
|
282
|
+
* with a location record for that block with poolId: P.
|
|
283
|
+
* Under-replicated when pool-scoped replica count < targetReplicationFactor.
|
|
209
284
|
*
|
|
210
285
|
* @returns Array of block checksums that need additional replicas
|
|
286
|
+
* @see Requirements 6.1, 6.2
|
|
211
287
|
*/
|
|
212
288
|
getUnderReplicatedBlocks(): Promise<Checksum[]>;
|
|
213
289
|
/**
|
|
214
290
|
* Record that a block has been replicated to a node.
|
|
291
|
+
* Includes poolId in the location record when the block belongs to a pool.
|
|
215
292
|
*
|
|
216
293
|
* @param key - The block's checksum or ID
|
|
217
294
|
* @param nodeId - The ID of the node that now holds a replica
|
|
295
|
+
* @see Requirements 6.1, 6.2
|
|
218
296
|
*/
|
|
219
297
|
recordReplication(key: Checksum | string, nodeId: string): Promise<void>;
|
|
298
|
+
/**
|
|
299
|
+
* Count the number of distinct nodes with a location record
|
|
300
|
+
* for a block that matches the given poolId.
|
|
301
|
+
*
|
|
302
|
+
* @param locations - All location records for the block
|
|
303
|
+
* @param poolId - The pool to scope the count to
|
|
304
|
+
* @returns Number of distinct nodes with matching poolId
|
|
305
|
+
*/
|
|
306
|
+
private countPoolScopedReplicas;
|
|
220
307
|
/**
|
|
221
308
|
* Record that a replica node is no longer available.
|
|
222
309
|
*
|
|
@@ -232,6 +319,24 @@ export declare class AvailabilityAwareBlockStore implements IBlockStore {
|
|
|
232
319
|
* @returns Result containing the brightened block ID and random block IDs
|
|
233
320
|
*/
|
|
234
321
|
brightenBlock(key: Checksum | string, randomBlockCount: number): Promise<BrightenResult>;
|
|
322
|
+
/**
|
|
323
|
+
* Handle a pool deletion event (triggered by a gossip `pool_deleted` announcement).
|
|
324
|
+
* Records a tombstone, removes all blocks in the pool from the local store,
|
|
325
|
+
* and removes pool entries from the registry.
|
|
326
|
+
*
|
|
327
|
+
* @param poolId - The pool that was deleted
|
|
328
|
+
* @param originNodeId - The node that originated the deletion
|
|
329
|
+
* @see Requirements 2.3, 2.4, 2.5
|
|
330
|
+
*/
|
|
331
|
+
handlePoolDeletion(poolId: PoolId, originNodeId: string): Promise<void>;
|
|
332
|
+
/**
|
|
333
|
+
* Check if a pool has an active deletion tombstone.
|
|
334
|
+
* Cleans up expired tombstones automatically.
|
|
335
|
+
*
|
|
336
|
+
* @param poolId - The pool ID to check
|
|
337
|
+
* @returns True if an active (non-expired) tombstone exists
|
|
338
|
+
*/
|
|
339
|
+
private hasTombstone;
|
|
235
340
|
/**
|
|
236
341
|
* Convert a key to hex string format.
|
|
237
342
|
*/
|
|
@@ -282,7 +387,7 @@ export declare class AvailabilityAwareBlockStore implements IBlockStore {
|
|
|
282
387
|
*
|
|
283
388
|
* @returns The configuration
|
|
284
389
|
*/
|
|
285
|
-
getConfig():
|
|
390
|
+
getConfig(): ResolvedAvailabilityAwareBlockStoreConfig;
|
|
286
391
|
/**
|
|
287
392
|
* Store a CBL with XOR whitening for Owner-Free storage.
|
|
288
393
|
* Delegates to the inner store and updates availability tracking for both blocks.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"availabilityAwareBlockStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/stores/availabilityAwareBlockStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,QAAQ,
|
|
1
|
+
{"version":3,"file":"availabilityAwareBlockStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/stores/availabilityAwareBlockStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
* @see Requirements 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AvailabilityAwareBlockStore = exports.DEFAULT_AVAILABILITY_AWARE_BLOCK_STORE_CONFIG = exports.PartitionModeError = void 0;
|
|
12
|
+
exports.AvailabilityAwareBlockStore = exports.DEFAULT_AVAILABILITY_AWARE_BLOCK_STORE_CONFIG = exports.PartitionModeError = exports.PoolDeletionTombstoneError = void 0;
|
|
13
13
|
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
14
|
+
// Re-export so existing consumers of this module continue to work
|
|
15
|
+
var brightchain_lib_2 = require("@brightchain/brightchain-lib");
|
|
16
|
+
Object.defineProperty(exports, "PoolDeletionTombstoneError", { enumerable: true, get: function () { return brightchain_lib_2.PoolDeletionTombstoneError; } });
|
|
14
17
|
/**
|
|
15
18
|
* Error thrown when an operation is attempted during partition mode
|
|
16
19
|
* that requires network access.
|
|
@@ -29,6 +32,10 @@ exports.DEFAULT_AVAILABILITY_AWARE_BLOCK_STORE_CONFIG = {
|
|
|
29
32
|
localNodeId: '',
|
|
30
33
|
autoAnnounce: true,
|
|
31
34
|
trackAccess: true,
|
|
35
|
+
defaultReadConcern: brightchain_lib_1.ReadConcern.Local,
|
|
36
|
+
blockFetcherConfig: undefined,
|
|
37
|
+
fetchQueueConfig: undefined,
|
|
38
|
+
tombstoneConfig: brightchain_lib_1.DEFAULT_TOMBSTONE_CONFIG,
|
|
32
39
|
};
|
|
33
40
|
/**
|
|
34
41
|
* AvailabilityAwareBlockStore
|
|
@@ -55,8 +62,14 @@ class AvailabilityAwareBlockStore {
|
|
|
55
62
|
* @param gossipService - Service for block announcements
|
|
56
63
|
* @param reconciliationService - Service for pending sync queue
|
|
57
64
|
* @param config - Configuration options
|
|
58
|
-
|
|
59
|
-
|
|
65
|
+
* @param blockFetcher - Optional block fetcher for remote block retrieval
|
|
66
|
+
*/
|
|
67
|
+
constructor(innerStore, registry, availabilityService, gossipService, reconciliationService, config, blockFetcher) {
|
|
68
|
+
/**
|
|
69
|
+
* Tombstones for deleted pools. Blocks cannot be stored in a pool
|
|
70
|
+
* with an active tombstone until it expires.
|
|
71
|
+
*/
|
|
72
|
+
this.tombstones = new Map();
|
|
60
73
|
this.innerStore = innerStore;
|
|
61
74
|
this.registry = registry;
|
|
62
75
|
this.availabilityService = availabilityService;
|
|
@@ -66,6 +79,7 @@ class AvailabilityAwareBlockStore {
|
|
|
66
79
|
...exports.DEFAULT_AVAILABILITY_AWARE_BLOCK_STORE_CONFIG,
|
|
67
80
|
...config,
|
|
68
81
|
};
|
|
82
|
+
this.blockFetcher = blockFetcher;
|
|
69
83
|
}
|
|
70
84
|
/**
|
|
71
85
|
* Get the block size for this store.
|
|
@@ -84,30 +98,128 @@ class AvailabilityAwareBlockStore {
|
|
|
84
98
|
return this.innerStore.has(key);
|
|
85
99
|
}
|
|
86
100
|
/**
|
|
87
|
-
* Get a block's data.
|
|
101
|
+
* Get a block's data with optional read concern.
|
|
88
102
|
* Updates access metadata if tracking is enabled.
|
|
89
103
|
*
|
|
104
|
+
* Read concern behavior:
|
|
105
|
+
* - Local (default): return only locally available blocks, error for remote/unknown
|
|
106
|
+
* - Consistent: await remote fetch, store result, return or timeout
|
|
107
|
+
* - Available: try fetch with initialWaitMs, return PendingBlockError if not resolved
|
|
108
|
+
*
|
|
109
|
+
* During partition mode, remote blocks always throw PartitionModeError
|
|
110
|
+
* regardless of read concern.
|
|
111
|
+
*
|
|
90
112
|
* @param key - The block's checksum
|
|
113
|
+
* @param readConcern - Optional read concern level (defaults to config.defaultReadConcern)
|
|
91
114
|
* @returns Promise resolving to the block data
|
|
92
|
-
* @throws
|
|
93
|
-
* @
|
|
115
|
+
* @throws PartitionModeError if block is remote and system is in partition mode
|
|
116
|
+
* @throws PendingBlockError if Available concern and fetch not resolved in time
|
|
117
|
+
* @throws FetchTimeoutError if Consistent concern and fetch exceeds timeout
|
|
118
|
+
* @throws Error if block not found locally and concern is Local
|
|
119
|
+
* @see Requirements 2.2, 2.3, 2.4, 2.5, 7.3
|
|
94
120
|
*/
|
|
95
|
-
async getData(key) {
|
|
121
|
+
async getData(key, readConcern) {
|
|
96
122
|
const blockId = this.keyToHex(key);
|
|
97
|
-
|
|
123
|
+
const concern = readConcern ?? this.config.defaultReadConcern;
|
|
124
|
+
// Step 1: Check partition mode for remote blocks BEFORE trying inner store.
|
|
125
|
+
// This preserves the original contract: remote blocks are inaccessible during partition
|
|
126
|
+
// regardless of whether the data happens to be in the inner store.
|
|
98
127
|
if (this.availabilityService.isInPartitionMode()) {
|
|
99
128
|
const state = await this.availabilityService.getAvailabilityState(blockId);
|
|
100
129
|
if (state === brightchain_lib_1.AvailabilityState.Remote) {
|
|
101
130
|
throw new PartitionModeError(`Cannot access remote block ${blockId} during partition mode`);
|
|
102
131
|
}
|
|
103
132
|
}
|
|
104
|
-
//
|
|
105
|
-
|
|
133
|
+
// Step 2: Try inner store first
|
|
134
|
+
try {
|
|
135
|
+
const block = await this.innerStore.getData(key);
|
|
136
|
+
// Update access metadata if tracking is enabled
|
|
137
|
+
if (this.config.trackAccess) {
|
|
138
|
+
await this.updateAccessMetadata(blockId);
|
|
139
|
+
}
|
|
140
|
+
return block;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Block not found locally — fall through to read concern logic
|
|
144
|
+
}
|
|
145
|
+
// Step 3: Block not found locally — check availability state
|
|
146
|
+
const state = await this.availabilityService.getAvailabilityState(blockId);
|
|
147
|
+
// Step 4: Apply read concern logic
|
|
148
|
+
if (concern === brightchain_lib_1.ReadConcern.Local) {
|
|
149
|
+
// Local concern: only return locally available blocks
|
|
150
|
+
throw new Error(`Block ${blockId} not found locally (state: ${state})`);
|
|
151
|
+
}
|
|
152
|
+
// For Available and Consistent concerns, we need a block fetcher
|
|
153
|
+
if (!this.blockFetcher) {
|
|
154
|
+
throw new Error(`Block ${blockId} not found locally and no block fetcher configured (state: ${state})`);
|
|
155
|
+
}
|
|
156
|
+
// Only attempt remote fetch for Remote state
|
|
157
|
+
if (state !== brightchain_lib_1.AvailabilityState.Remote) {
|
|
158
|
+
throw new Error(`Block ${blockId} not found (state: ${state})`);
|
|
159
|
+
}
|
|
160
|
+
if (concern === brightchain_lib_1.ReadConcern.Consistent) {
|
|
161
|
+
return this.fetchBlockConsistent(key, blockId);
|
|
162
|
+
}
|
|
163
|
+
// ReadConcern.Available
|
|
164
|
+
return this.fetchBlockAvailable(key, blockId);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Fetch a block with Consistent read concern.
|
|
168
|
+
* Awaits the full fetch result — returns the block or throws on timeout/failure.
|
|
169
|
+
*
|
|
170
|
+
* @see Requirements 2.4, 2.5
|
|
171
|
+
*/
|
|
172
|
+
async fetchBlockConsistent(key, blockId) {
|
|
173
|
+
const result = await this.blockFetcher.fetchBlock(blockId);
|
|
174
|
+
if (!result.success) {
|
|
175
|
+
const fetcherConfig = this.blockFetcher.getConfig();
|
|
176
|
+
throw new brightchain_lib_1.FetchTimeoutError(blockId, fetcherConfig.fetchTimeoutMs);
|
|
177
|
+
}
|
|
178
|
+
// Store the fetched block locally and update state to Cached
|
|
179
|
+
await this.innerStore.put(blockId, result.data);
|
|
180
|
+
await this.availabilityService.setAvailabilityState(blockId, brightchain_lib_1.AvailabilityState.Cached);
|
|
181
|
+
// Update access metadata if tracking is enabled
|
|
182
|
+
if (this.config.trackAccess) {
|
|
183
|
+
await this.updateAccessMetadata(blockId);
|
|
184
|
+
}
|
|
185
|
+
// Return the block from the inner store (now stored locally)
|
|
186
|
+
return this.innerStore.getData(key);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Fetch a block with Available read concern.
|
|
190
|
+
* Tries to fetch within initialWaitMs; throws PendingBlockError if not resolved in time.
|
|
191
|
+
*
|
|
192
|
+
* @see Requirements 2.3
|
|
193
|
+
*/
|
|
194
|
+
async fetchBlockAvailable(key, blockId) {
|
|
195
|
+
const fetcherConfig = this.blockFetcher.getConfig();
|
|
196
|
+
const initialWaitMs = fetcherConfig.initialWaitMs;
|
|
197
|
+
const fetchPromise = this.blockFetcher.fetchBlock(blockId);
|
|
198
|
+
// Race the fetch against the initial wait timeout
|
|
199
|
+
const result = await Promise.race([
|
|
200
|
+
fetchPromise.then((r) => ({ kind: 'result', value: r })),
|
|
201
|
+
new Promise((resolve) => setTimeout(() => resolve({ kind: 'timeout' }), initialWaitMs)),
|
|
202
|
+
]);
|
|
203
|
+
if (result.kind === 'timeout') {
|
|
204
|
+
// Fetch didn't complete in time — throw PendingBlockError
|
|
205
|
+
const locations = await this.availabilityService.getBlockLocations(blockId);
|
|
206
|
+
throw new brightchain_lib_1.PendingBlockError(blockId, brightchain_lib_1.AvailabilityState.Remote, locations.map((loc) => loc.nodeId));
|
|
207
|
+
}
|
|
208
|
+
// Fetch completed within initialWaitMs
|
|
209
|
+
if (!result.value.success) {
|
|
210
|
+
// Fetch failed — still throw PendingBlockError since the block may become available later
|
|
211
|
+
const locations = await this.availabilityService.getBlockLocations(blockId);
|
|
212
|
+
throw new brightchain_lib_1.PendingBlockError(blockId, brightchain_lib_1.AvailabilityState.Remote, locations.map((loc) => loc.nodeId));
|
|
213
|
+
}
|
|
214
|
+
// Store the fetched block locally and update state to Cached
|
|
215
|
+
await this.innerStore.put(blockId, result.value.data);
|
|
216
|
+
await this.availabilityService.setAvailabilityState(blockId, brightchain_lib_1.AvailabilityState.Cached);
|
|
106
217
|
// Update access metadata if tracking is enabled
|
|
107
218
|
if (this.config.trackAccess) {
|
|
108
219
|
await this.updateAccessMetadata(blockId);
|
|
109
220
|
}
|
|
110
|
-
|
|
221
|
+
// Return the block from the inner store
|
|
222
|
+
return this.innerStore.getData(key);
|
|
111
223
|
}
|
|
112
224
|
/**
|
|
113
225
|
* Store a block's data with optional durability settings.
|
|
@@ -119,17 +231,33 @@ class AvailabilityAwareBlockStore {
|
|
|
119
231
|
*/
|
|
120
232
|
async setData(block, options) {
|
|
121
233
|
const blockId = this.keyToHex(block.idChecksum);
|
|
234
|
+
// Look up pool context from the inner store's metadata
|
|
235
|
+
// (metadata may already exist if the block was previously stored)
|
|
236
|
+
const existingMetadata = await this.innerStore.getMetadata(blockId);
|
|
237
|
+
const poolId = existingMetadata?.poolId;
|
|
238
|
+
// Check tombstone — reject if pool was deleted
|
|
239
|
+
if (poolId && this.hasTombstone(poolId)) {
|
|
240
|
+
throw new brightchain_lib_1.PoolDeletionTombstoneError(poolId);
|
|
241
|
+
}
|
|
122
242
|
// Store in inner store first
|
|
123
243
|
await this.innerStore.setData(block, options);
|
|
124
|
-
//
|
|
125
|
-
this.
|
|
244
|
+
// Re-read metadata after store in case it was created during setData
|
|
245
|
+
const storedMetadata = await this.innerStore.getMetadata(blockId);
|
|
246
|
+
const resolvedPoolId = poolId ?? storedMetadata?.poolId;
|
|
247
|
+
// Check tombstone again with resolved poolId (in case metadata was created during store)
|
|
248
|
+
if (resolvedPoolId && !poolId && this.hasTombstone(resolvedPoolId)) {
|
|
249
|
+
throw new brightchain_lib_1.PoolDeletionTombstoneError(resolvedPoolId);
|
|
250
|
+
}
|
|
251
|
+
// Update registry with pool context
|
|
252
|
+
this.registry.addLocal(blockId, resolvedPoolId);
|
|
126
253
|
// Update availability state to Local
|
|
127
254
|
await this.availabilityService.setAvailabilityState(blockId, brightchain_lib_1.AvailabilityState.Local);
|
|
128
|
-
// Update location metadata
|
|
255
|
+
// Update location metadata with pool context
|
|
129
256
|
const locationRecord = {
|
|
130
257
|
nodeId: this.config.localNodeId,
|
|
131
258
|
lastSeen: new Date(),
|
|
132
259
|
isAuthoritative: true,
|
|
260
|
+
...(resolvedPoolId ? { poolId: resolvedPoolId } : {}),
|
|
133
261
|
};
|
|
134
262
|
await this.availabilityService.updateLocation(blockId, locationRecord);
|
|
135
263
|
// Handle partition mode - add to pending sync queue
|
|
@@ -143,8 +271,8 @@ class AvailabilityAwareBlockStore {
|
|
|
143
271
|
this.reconciliationService.addToPendingSyncQueue(syncItem);
|
|
144
272
|
}
|
|
145
273
|
else if (this.config.autoAnnounce) {
|
|
146
|
-
// Announce to network via gossip
|
|
147
|
-
await this.gossipService.announceBlock(blockId);
|
|
274
|
+
// Announce to network via gossip with pool context
|
|
275
|
+
await this.gossipService.announceBlock(blockId, resolvedPoolId);
|
|
148
276
|
}
|
|
149
277
|
}
|
|
150
278
|
/**
|
|
@@ -156,6 +284,9 @@ class AvailabilityAwareBlockStore {
|
|
|
156
284
|
*/
|
|
157
285
|
async deleteData(key) {
|
|
158
286
|
const blockId = this.keyToHex(key);
|
|
287
|
+
// Look up pool context before deletion
|
|
288
|
+
const metadata = await this.innerStore.getMetadata(blockId);
|
|
289
|
+
const poolId = metadata?.poolId;
|
|
159
290
|
// Delete from inner store first
|
|
160
291
|
await this.innerStore.deleteData(key);
|
|
161
292
|
// Update registry
|
|
@@ -172,8 +303,8 @@ class AvailabilityAwareBlockStore {
|
|
|
172
303
|
this.reconciliationService.addToPendingSyncQueue(syncItem);
|
|
173
304
|
}
|
|
174
305
|
else if (this.config.autoAnnounce) {
|
|
175
|
-
// Announce removal to network via gossip
|
|
176
|
-
await this.gossipService.announceRemoval(blockId);
|
|
306
|
+
// Announce removal to network via gossip with pool context
|
|
307
|
+
await this.gossipService.announceRemoval(blockId, poolId);
|
|
177
308
|
}
|
|
178
309
|
}
|
|
179
310
|
/**
|
|
@@ -299,39 +430,108 @@ class AvailabilityAwareBlockStore {
|
|
|
299
430
|
}
|
|
300
431
|
// === Replication Operations ===
|
|
301
432
|
/**
|
|
302
|
-
* Get blocks that are pending replication.
|
|
433
|
+
* Get blocks that are pending replication, scoped by pool.
|
|
434
|
+
*
|
|
435
|
+
* A block's replication count for pool P = number of distinct nodes
|
|
436
|
+
* with a location record for that block with poolId: P.
|
|
437
|
+
* Blocks without a poolId use the inner store's default pending check.
|
|
303
438
|
*
|
|
304
439
|
* @returns Array of block checksums pending replication
|
|
440
|
+
* @see Requirements 6.1, 6.2
|
|
305
441
|
*/
|
|
306
442
|
async getBlocksPendingReplication() {
|
|
307
|
-
|
|
443
|
+
const pendingFromInner = await this.innerStore.getBlocksPendingReplication();
|
|
444
|
+
const result = [];
|
|
445
|
+
for (const checksum of pendingFromInner) {
|
|
446
|
+
const blockId = this.keyToHex(checksum);
|
|
447
|
+
const metadata = await this.innerStore.getMetadata(blockId);
|
|
448
|
+
if (!metadata?.poolId) {
|
|
449
|
+
// No pool context — use inner store's determination
|
|
450
|
+
result.push(checksum);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
// Pool-scoped: count distinct nodes with matching poolId
|
|
454
|
+
const locations = await this.availabilityService.getBlockLocations(blockId);
|
|
455
|
+
const poolReplicaCount = this.countPoolScopedReplicas(locations, metadata.poolId);
|
|
456
|
+
// Still pending if no pool-scoped replicas exist (excluding local node)
|
|
457
|
+
if (poolReplicaCount <= 1) {
|
|
458
|
+
result.push(checksum);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return result;
|
|
308
462
|
}
|
|
309
463
|
/**
|
|
310
|
-
* Get blocks that are under-replicated.
|
|
464
|
+
* Get blocks that are under-replicated, scoped by pool.
|
|
465
|
+
*
|
|
466
|
+
* A block's replication count for pool P = number of distinct nodes
|
|
467
|
+
* with a location record for that block with poolId: P.
|
|
468
|
+
* Under-replicated when pool-scoped replica count < targetReplicationFactor.
|
|
311
469
|
*
|
|
312
470
|
* @returns Array of block checksums that need additional replicas
|
|
471
|
+
* @see Requirements 6.1, 6.2
|
|
313
472
|
*/
|
|
314
473
|
async getUnderReplicatedBlocks() {
|
|
315
|
-
|
|
474
|
+
const underReplicatedFromInner = await this.innerStore.getUnderReplicatedBlocks();
|
|
475
|
+
const result = [];
|
|
476
|
+
for (const checksum of underReplicatedFromInner) {
|
|
477
|
+
const blockId = this.keyToHex(checksum);
|
|
478
|
+
const metadata = await this.innerStore.getMetadata(blockId);
|
|
479
|
+
if (!metadata?.poolId) {
|
|
480
|
+
// No pool context — use inner store's determination
|
|
481
|
+
result.push(checksum);
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
// Pool-scoped: count distinct nodes with matching poolId
|
|
485
|
+
const locations = await this.availabilityService.getBlockLocations(blockId);
|
|
486
|
+
const poolReplicaCount = this.countPoolScopedReplicas(locations, metadata.poolId);
|
|
487
|
+
// Under-replicated if pool-scoped replicas < target
|
|
488
|
+
if (poolReplicaCount < metadata.targetReplicationFactor) {
|
|
489
|
+
result.push(checksum);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return result;
|
|
316
493
|
}
|
|
317
494
|
/**
|
|
318
495
|
* Record that a block has been replicated to a node.
|
|
496
|
+
* Includes poolId in the location record when the block belongs to a pool.
|
|
319
497
|
*
|
|
320
498
|
* @param key - The block's checksum or ID
|
|
321
499
|
* @param nodeId - The ID of the node that now holds a replica
|
|
500
|
+
* @see Requirements 6.1, 6.2
|
|
322
501
|
*/
|
|
323
502
|
async recordReplication(key, nodeId) {
|
|
324
503
|
const blockId = this.keyToHex(key);
|
|
325
504
|
// Record in inner store
|
|
326
505
|
await this.innerStore.recordReplication(key, nodeId);
|
|
327
|
-
//
|
|
506
|
+
// Look up pool context from block metadata
|
|
507
|
+
const metadata = await this.innerStore.getMetadata(blockId);
|
|
508
|
+
const poolId = metadata?.poolId;
|
|
509
|
+
// Update location metadata with pool context
|
|
328
510
|
const locationRecord = {
|
|
329
511
|
nodeId,
|
|
330
512
|
lastSeen: new Date(),
|
|
331
513
|
isAuthoritative: false,
|
|
514
|
+
...(poolId ? { poolId } : {}),
|
|
332
515
|
};
|
|
333
516
|
await this.availabilityService.updateLocation(blockId, locationRecord);
|
|
334
517
|
}
|
|
518
|
+
/**
|
|
519
|
+
* Count the number of distinct nodes with a location record
|
|
520
|
+
* for a block that matches the given poolId.
|
|
521
|
+
*
|
|
522
|
+
* @param locations - All location records for the block
|
|
523
|
+
* @param poolId - The pool to scope the count to
|
|
524
|
+
* @returns Number of distinct nodes with matching poolId
|
|
525
|
+
*/
|
|
526
|
+
countPoolScopedReplicas(locations, poolId) {
|
|
527
|
+
const nodeIds = new Set();
|
|
528
|
+
for (const loc of locations) {
|
|
529
|
+
if (loc.poolId === poolId) {
|
|
530
|
+
nodeIds.add(loc.nodeId);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return nodeIds.size;
|
|
534
|
+
}
|
|
335
535
|
/**
|
|
336
536
|
* Record that a replica node is no longer available.
|
|
337
537
|
*
|
|
@@ -371,7 +571,51 @@ class AvailabilityAwareBlockStore {
|
|
|
371
571
|
}
|
|
372
572
|
return result;
|
|
373
573
|
}
|
|
574
|
+
// === Pool Deletion ===
|
|
575
|
+
/**
|
|
576
|
+
* Handle a pool deletion event (triggered by a gossip `pool_deleted` announcement).
|
|
577
|
+
* Records a tombstone, removes all blocks in the pool from the local store,
|
|
578
|
+
* and removes pool entries from the registry.
|
|
579
|
+
*
|
|
580
|
+
* @param poolId - The pool that was deleted
|
|
581
|
+
* @param originNodeId - The node that originated the deletion
|
|
582
|
+
* @see Requirements 2.3, 2.4, 2.5
|
|
583
|
+
*/
|
|
584
|
+
async handlePoolDeletion(poolId, originNodeId) {
|
|
585
|
+
// Record tombstone
|
|
586
|
+
this.tombstones.set(poolId, {
|
|
587
|
+
poolId,
|
|
588
|
+
deletedAt: new Date(),
|
|
589
|
+
expiresAt: new Date(Date.now() + this.config.tombstoneConfig.tombstoneTtlMs),
|
|
590
|
+
originNodeId,
|
|
591
|
+
});
|
|
592
|
+
// Remove all blocks in the pool from local store
|
|
593
|
+
if ((0, brightchain_lib_1.isPooledBlockStore)(this.innerStore)) {
|
|
594
|
+
await this.innerStore.forceDeletePool(poolId);
|
|
595
|
+
}
|
|
596
|
+
// Remove from registry (bulk removal by pool)
|
|
597
|
+
// The registry's removeLocal with poolId handles per-block removal;
|
|
598
|
+
// for bulk removal we rely on the pool-scoped manifest to identify blocks.
|
|
599
|
+
// Future task 11.1 will add pool-aware registry internals.
|
|
600
|
+
}
|
|
374
601
|
// === Helper Methods ===
|
|
602
|
+
/**
|
|
603
|
+
* Check if a pool has an active deletion tombstone.
|
|
604
|
+
* Cleans up expired tombstones automatically.
|
|
605
|
+
*
|
|
606
|
+
* @param poolId - The pool ID to check
|
|
607
|
+
* @returns True if an active (non-expired) tombstone exists
|
|
608
|
+
*/
|
|
609
|
+
hasTombstone(poolId) {
|
|
610
|
+
const tombstone = this.tombstones.get(poolId);
|
|
611
|
+
if (!tombstone)
|
|
612
|
+
return false;
|
|
613
|
+
if (new Date() > tombstone.expiresAt) {
|
|
614
|
+
this.tombstones.delete(poolId); // Clean up expired
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
return true;
|
|
618
|
+
}
|
|
375
619
|
/**
|
|
376
620
|
* Convert a key to hex string format.
|
|
377
621
|
*/
|