⚠️ This is a backend issue — work is done inside the backend/ folder
Description
backend/src/modules/blockchain/ipfs.service.ts uploads medical record hashes to IPFS via a single Kubo RPC client. If the IPFS node is unavailable, the upload throws immediately with no retry, causing the entire medical record sync to fail. There is also no fallback provider (e.g. Pinata, Web3.Storage) if the primary node is down.
Current State
IPFSService.upload() — single try/catch, no retry
IPFSService.retrieve() — single attempt, no fallback
- No health check for the IPFS node
BlockchainSyncService calls IPFSService directly and propagates failures upward
What Needs to Be Built
1. Retry Logic with Exponential Backoff
async upload(data: string | Buffer, retries = 3): Promise<string> {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
return await this.primaryUpload(data);
} catch (err) {
if (attempt === retries) break;
await sleep(500 * 2 ** attempt);
}
}
return this.fallbackUpload(data); // Pinata fallback
}
2. Pinata Fallback Provider
- Add
PINATA_API_KEY and PINATA_SECRET_KEY to blockchain.config.ts
- Implement
fallbackUpload() using Pinata's REST API
- Log which provider was used for each upload
3. IPFS Node Health Check
GET /blockchain/ipfs/health
- Ping the IPFS node and return
{ status: 'ok' | 'degraded' | 'down', provider: 'kubo' | 'pinata' }
- Expose via
ObservabilityController or a new BlockchainController
4. Retrieve Fallback
- On
retrieve(cid), try primary node first, then Pinata gateway on failure
Acceptance Criteria
Files to Modify
backend/src/modules/blockchain/ipfs.service.ts
backend/src/config/blockchain.config.ts (add Pinata config)
backend/src/modules/blockchain/blockchain.module.ts (expose health endpoint)
backend/src/modules/blockchain/ipfs.service.spec.ts (new)
Environment Variables Required
PINATA_API_KEY=
PINATA_SECRET_KEY=
Priority
High — IPFS failures currently break medical record blockchain sync entirely
Estimated Effort
2 days
backend/folderDescription
backend/src/modules/blockchain/ipfs.service.tsuploads medical record hashes to IPFS via a single Kubo RPC client. If the IPFS node is unavailable, the upload throws immediately with no retry, causing the entire medical record sync to fail. There is also no fallback provider (e.g. Pinata, Web3.Storage) if the primary node is down.Current State
IPFSService.upload()— single try/catch, no retryIPFSService.retrieve()— single attempt, no fallbackBlockchainSyncServicecallsIPFSServicedirectly and propagates failures upwardWhat Needs to Be Built
1. Retry Logic with Exponential Backoff
2. Pinata Fallback Provider
PINATA_API_KEYandPINATA_SECRET_KEYtoblockchain.config.tsfallbackUpload()using Pinata's REST API3. IPFS Node Health Check
{ status: 'ok' | 'degraded' | 'down', provider: 'kubo' | 'pinata' }ObservabilityControlleror a newBlockchainController4. Retrieve Fallback
retrieve(cid), try primary node first, then Pinata gateway on failureAcceptance Criteria
GET /blockchain/ipfs/healthreturns current provider statusFiles to Modify
backend/src/modules/blockchain/ipfs.service.tsbackend/src/config/blockchain.config.ts(add Pinata config)backend/src/modules/blockchain/blockchain.module.ts(expose health endpoint)backend/src/modules/blockchain/ipfs.service.spec.ts(new)Environment Variables Required
Priority
High — IPFS failures currently break medical record blockchain sync entirely
Estimated Effort
2 days