brainy/examples/write-only-direct-reads-demo.js
David Snelling 06f502ec4a feat: add direct storage access in write-only mode for efficient deduplication
Enables ID-based lookups in write-only mode without loading search indexes, solving the fundamental conflict between write-only optimization and deduplication needs.

Key Features:
- New allowDirectReads configuration option
- Direct storage methods: has(), exists(), getMetadata(), getBatch()
- Enhanced get() and getVerb() support in write-only mode
- Smart operation separation (storage vs. search operations)

Use Cases:
- Bluesky services: Avoid redundant profile API calls
- GitHub packages: Efficient user processing with existence checks
- General writer services: Smart deduplication without search overhead

Performance Benefits:
- 50-100% reduction in external API calls
- No search index memory usage
- Fast direct storage lookups
- Optimal for high-throughput data ingestion

Configuration:
const brainy = new BrainyData({
  writeOnly: true,        // Skip search index loading
  allowDirectReads: true  // Enable direct ID lookups
})

Includes comprehensive tests (26/26 passing), real-world demo, and complete README documentation with configuration examples.
2025-08-07 07:57:41 -07:00

185 lines
No EOL
6.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Write-Only Mode with Direct Reads Demo
*
* This example demonstrates the new allowDirectReads feature that enables
* direct storage operations in write-only mode for efficient deduplication
* without loading expensive search indexes.
*/
import { BrainyData } from '../dist/index.js'
// Simulate external API calls
const mockBlueskyAPI = {
async getProfile(did) {
// Simulate network latency
await new Promise(resolve => setTimeout(resolve, 100))
return {
did,
handle: `user-${did.split(':')[2]}`,
displayName: `User ${did.split(':')[2]}`,
followersCount: Math.floor(Math.random() * 1000),
postsCount: Math.floor(Math.random() * 500),
createdAt: new Date().toISOString()
}
}
}
async function demonstrateWriteOnlyDirectReads() {
console.log('🚀 Write-Only Mode with Direct Reads Demo\n')
// Create instances with different configurations
console.log('📝 Creating BrainyData instances...')
const writerOnlyService = new BrainyData({
writeOnly: true,
allowDirectReads: false
})
const writerWithReadsService = new BrainyData({
writeOnly: true,
allowDirectReads: true
})
const fullService = new BrainyData({
writeOnly: false
})
await writerOnlyService.init()
await writerWithReadsService.init()
await fullService.init()
console.log('✅ All instances initialized\n')
// Demonstrate the problem with write-only mode without direct reads
console.log('❌ Problem: Write-only mode without direct reads')
console.log(' - Cannot check for existing data')
console.log(' - Must make redundant API calls')
console.log(' - No efficient deduplication possible\n')
// Simulate Bluesky service with write-only + direct reads
console.log('✅ Solution: Write-only mode WITH direct reads')
const processMessage = async (did, messageData) => {
console.log(` Processing message from ${did}...`)
// Check if profile already exists (direct storage lookup)
const existingProfile = await writerWithReadsService.get(did)
if (!existingProfile) {
console.log(` 📡 Making API call for new DID: ${did}`)
// Simulate API call
const profileData = await mockBlueskyAPI.getProfile(did)
// Store the profile
const profileVector = new Array(384).fill(Math.random() * 0.1)
await writerWithReadsService.add(profileVector, profileData, { id: did })
return { action: 'created', profile: profileData, apiCall: true }
} else {
console.log(` ⚡ Using cached profile for: ${did}`)
// Profile exists, skip API call
return { action: 'existing', profile: existingProfile.metadata, apiCall: false }
}
}
// Test deduplication efficiency
console.log('\n🔄 Testing deduplication efficiency...')
const testDIDs = [
'did:plc:user123',
'did:plc:user456',
'did:plc:user123', // Duplicate
'did:plc:user789',
'did:plc:user123', // Another duplicate
'did:plc:user456' // Another duplicate
]
let apiCallCount = 0
const results = []
console.log(`\n📊 Processing ${testDIDs.length} messages...`)
for (const did of testDIDs) {
const result = await processMessage(did, { text: `Message from ${did}` })
results.push(result)
if (result.apiCall) apiCallCount++
}
console.log(`\n📈 Results:`)
console.log(` • Total messages processed: ${testDIDs.length}`)
console.log(` • Unique profiles: ${new Set(testDIDs).size}`)
console.log(` • API calls made: ${apiCallCount}`)
console.log(` • API calls saved: ${testDIDs.length - apiCallCount}`)
console.log(` • Efficiency: ${Math.round((1 - apiCallCount / testDIDs.length) * 100)}% reduction in API calls`)
// Demonstrate direct read operations
console.log('\n🔍 Testing direct read operations...')
const testDID = 'did:plc:user123'
console.log(` • get('${testDID}'): ${await writerWithReadsService.get(testDID) ? '✅ Found' : '❌ Not found'}`)
console.log(` • has('${testDID}'): ${await writerWithReadsService.has(testDID) ? '✅ Exists' : '❌ Missing'}`)
console.log(` • exists('${testDID}'): ${await writerWithReadsService.exists(testDID) ? '✅ Exists' : '❌ Missing'}`)
const metadata = await writerWithReadsService.getMetadata(testDID)
console.log(` • getMetadata('${testDID}'): ${metadata ? `${metadata.handle}` : '❌ No metadata'}`)
const batchResults = await writerWithReadsService.getBatch([
'did:plc:user123',
'did:plc:user456',
'did:plc:nonexistent'
])
console.log(` • getBatch([3 items]): ${batchResults.filter(r => r !== null).length}/3 found`)
// Demonstrate that search operations are still blocked
console.log('\n🚫 Confirming search operations are blocked...')
try {
await writerWithReadsService.search('test')
console.log(' ❌ ERROR: Search should have failed!')
} catch (error) {
console.log(' ✅ search() correctly blocked:', error.message.split('.')[0])
}
// Performance comparison
console.log('\n⚡ Performance Benefits:')
console.log(' • No search index loading in memory')
console.log(' • Fast direct storage lookups')
console.log(' • Reduced memory footprint')
console.log(' • Optimal for high-throughput data ingestion')
console.log(' • Perfect for microservices with specific roles')
// Configuration examples
console.log('\n⚙ Configuration Examples:')
console.log(`
// Writer service with deduplication
const writerService = new BrainyData({
writeOnly: true, // No search index
allowDirectReads: true // Enable direct ID lookups
})
// Pure writer service (no reads)
const pureWriter = new BrainyData({
writeOnly: true, // No search index
allowDirectReads: false // No read operations
})
// Full-featured service
const readerService = new BrainyData({
writeOnly: false // Full search capabilities
})
`)
// Cleanup
console.log('🧹 Cleaning up...')
await writerOnlyService.cleanup?.()
await writerWithReadsService.cleanup?.()
await fullService.cleanup?.()
console.log('✨ Demo completed successfully!')
}
// Run the demo
demonstrateWriteOnlyDirectReads().catch(console.error)