The database layer provides IndexedDB abstraction with a centralized helper system and specialized store utilities. All database access flows through this layer, with services as the only consumers.
- Database Name: "review"
- Current Version: 36
- Store Count: 17 specialized object stores
- Upgrade Strategy: Automatic versioned migrations with data preservation
// Primary database connection
await dbHelper.openDB();
// Store access (readonly/readwrite)
const store = await dbHelper.getStore("storeName", "readwrite");
// Index creation utility
dbHelper.ensureIndex(store, indexName, keyPath);Purpose: Individual problem attempt tracking with timing and success data
// Record a problem attempt
await recordAttempt({
sessionId: "session-123",
problemId: "two-sum",
success: true,
timeSpent: 1200, // milliseconds
boxLevel: 2
});
// Get attempts for a session
const attempts = await getAttemptsBySession("session-123");
// Get historical attempts for a problem
const history = await getAttemptHistory("two-sum");
// Calculate success rates and timing metrics
const stats = await calculateAttemptStatistics();Purpose: Structured learning sessions with performance tracking
// Create new session
await saveNewSessionToDB({
id: "session-123",
problems: ["two-sum", "valid-parentheses"],
startTime: Date.now(),
settings: { difficulty: "mixed", count: 5 }
});
// Update session progress
await updateSessionInDB("session-123", {
completedProblems: 2,
currentProblem: "valid-parentheses"
});
// Get session with performance analysis
const session = await getSessionById("session-123");
const performance = await getSessionPerformance("session-123");Purpose: Problem data with Leitner system metadata (box levels, stability scores)
// Add new problem with Leitner metadata
await addProblem({
leetCodeID: "two-sum",
title: "Two Sum",
difficulty: "Easy",
tags: ["Array", "Hash Table"],
boxLevel: 1,
stability: 2.5,
lastReviewed: Date.now()
});
// Update problem state (box levels, stability)
await updateProblemInDB("two-sum", {
boxLevel: 3,
stability: 5.2,
consecutiveCorrect: 2
});
// Get problems with filters
const problems = await fetchAllProblems({
tags: ["Array"],
boxLevel: [2, 3],
difficulty: "Easy"
});
// Statistics for Leitner box distribution
const distribution = await countProblemsByBoxLevel();
// Returns: { box1: 45, box2: 23, box3: 12, box4: 5 }Purpose: Tracks mastery progress per algorithm pattern
// Recalculate mastery scores across all tags
await calculateTagMastery();
// Get mastery data for specific tag
const arrayMastery = await getTagMastery("Array");
// Returns: { tag: "Array", masteryLevel: 0.75, problems: 23, mastered: 17 }
// Get all mastery data
const allMastery = await getTagMastery();
// Update mastery score
await updateTagMasteryScore("Array", 0.05); // +5% improvement
// Get mastered algorithm patterns
const mastered = await getMasteredTags(); // masteryLevel >= 0.8
// Get struggling patterns needing focus
const weak = await getWeakTags(); // masteryLevel < 0.4Purpose: Manages progression through algorithm pattern difficulty levels
// Update ladder progression after attempt
await updatePatternLadder("Array", "two-sum", true); // success
// Get ladder state for algorithm pattern
const ladder = await getPatternLadder("Array");
// Returns: { tag: "Array", currentLevel: 3, problems: [...], completion: 0.6 }
// Get next problem in progression
const nextProblem = await getNextLadderProblem("Array");
// Calculate completion percentage
const completion = await calculateLadderCompletion("Array"); // 0.75 = 75%Purpose: Comprehensive session performance analysis and insights
// Save detailed session analysis
await storeSessionAnalytics({
sessionId: "session-123",
totalTime: 3600000, // 1 hour
problemsAttempted: 5,
problemsCompleted: 4,
averageTime: 720000, // 12 minutes
tagPerformance: { "Array": 0.8, "String": 0.6 },
insights: ["Strong array performance", "Need string practice"]
});
// Get detailed session metrics
const analytics = await getSessionAnalytics("session-123");
// Get performance trends over time
const trends = await getAnalyticsTrends("last30days");
// Returns weekly/monthly accuracy and timing trendsPurpose: Reference database of all LeetCode problems with metadata
// Fetch canonical problem data
const problem = await getProblemFromStandardProblems("two-sum");
// Returns: { slug: "two-sum", title: "Two Sum", difficulty: "Easy", ... }
// Search canonical problem set
const results = await searchStandardProblems({
tags: ["Array", "Hash Table"],
difficulty: "Easy",
companies: ["Google", "Amazon"]
});
// Update canonical problem data
await updateStandardProblem("two-sum", {
acceptanceRate: 0.52,
companies: ["Google", "Amazon", "Microsoft"]
});Purpose: Maintains relationships between similar problems
// Update relationships based on session data
await updateProblemRelationships({
sessionId: "session-123",
problems: ["two-sum", "three-sum", "four-sum"]
});
// Get related problems
const related = await getProblemRelationships("two-sum");
// Returns: [{ problemId: "three-sum", strength: 0.85 }, ...]
// Calculate similarity score between problems
const similarity = await calculateRelationshipStrength("two-sum", "three-sum");
// Returns: 0.75 (75% similar)Purpose: Manages algorithm tag connections and classifications
// Get tag relationship data
const tagData = await getTagRelationships("Array");
// Returns: { classification: "Core", related: ["Hash Table", "Two Pointers"] }
// Get tags by classification tier
const coreTags = await getTagsByClassification("Core");
// Returns: ["Array", "String", "Hash Table", "Two Pointers"]
const advancedTags = await getTagsByClassification("Advanced");
// Returns: ["Dynamic Programming", "Graph", "Tree", "Backtracking"]
// Calculate tag similarity
const similarity = await calculateTagSimilarity("Array", "Hash Table");
// Returns: 0.68 (often used together)Purpose: Manages time limits and attempt constraints for problems
// Get time limits for a problem
const limits = await getProblemLimits("two-sum");
// Returns: { timeLimit: 1200000, attempts: 3, difficulty: "Easy" }
// Update problem time constraints
await updateLimits("two-sum", {
timeLimit: 900000, // 15 minutes
attempts: 2
});
// Calculate personalized limits based on user level
const adaptiveLimits = await calculateAdaptiveLimits("Medium", 0.75);
// Returns personalized time limits based on 75% mastery levelPurpose: Database backup and recovery operations for data safety
// Create complete database backup
const backup = await createBackup();
// Returns: { version: 25, timestamp: ..., data: { problems: [...], sessions: [...] } }
// Restore database from backup
await restoreFromBackup(backupData);
// Verify backup integrity
const isValid = await validateBackup(backupData);
// Schedule automatic backups
await scheduleAutomaticBackup(); // Daily backups to Chrome storageSessions ↔ Attempts: sessions.id = attempts.sessionId
Problems ↔ Attempts: problems.leetCodeID = attempts.problemId
Tags ↔ Mastery: tag_relationships.id = tag_mastery.tag
Tags ↔ Ladders: tag_relationships.id = pattern_ladders.tag
Sessions ↔ Analytics: sessions.id = session_analytics.sessionId
- Primary Keys: Natural keys where possible (leetCodeID, tag), auto-increment for logs
- Secondary Indexes: Query-optimized indexes for common access patterns
- Composite Indexes: Multi-field indexes for complex queries
// Efficient indexed queries
const problems = await fetchAdditionalProblems({
tags: ["Array"], // Uses tag index
boxLevel: [2, 3], // Uses boxLevel index
lastReviewed: { before: Date.now() - 86400000 } // Uses timestamp index
});
// Batch operations for performance
await Promise.all([
updateProblemInDB("problem1", updates),
updateProblemInDB("problem2", updates),
updateProblemInDB("problem3", updates)
]);- Proper Cleanup: All cursors and transactions are properly closed
- Connection Pooling: Singleton pattern prevents connection bloat
- Lazy Loading: Large datasets loaded on demand
- Transaction Batching: Related operations grouped in single transactions
try {
const result = await dbOperation();
return result;
} catch (error) {
if (error.name === 'QuotaExceededError') {
// Handle storage quota issues
await cleanupOldData();
return await fallbackOperation();
}
// Log and transform error for user consumption
console.error('Database operation failed:', error);
throw new Error(`Operation failed: ${error.message}`);
}// Automatic schema upgrades
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Safe store creation with proper indexes
if (!db.objectStoreNames.contains("newStore")) {
const store = db.createObjectStore("newStore", { keyPath: "id" });
store.createIndex("by_timestamp", "timestamp", { unique: false });
}
// Data migration for existing stores
if (event.oldVersion < 25) {
await migrateToVersion25(db);
}
};Database operations are tested through:
- Schema Integrity: Version migration testing ensures no data loss
- Data Consistency: Relationship constraints validated
- Performance: Query optimization verified with large datasets
- Error Scenarios: Storage quota and corruption handling tested
// ✅ Correct: Services access database through store utilities
export const ProblemService = {
async createSession() {
const problems = await fetchAllProblems({ criteria });
return await saveNewSessionToDB({ problems });
}
};
// ❌ Incorrect: Components should never access database directly
const Component = () => {
// Never do this in components
const problems = await fetchAllProblems();
};// Batch related operations in transactions
const transaction = db.transaction(['problems', 'attempts'], 'readwrite');
await Promise.all([
updateProblemInDB(problemId, updates),
recordAttempt(attemptData)
]);// Implement graceful degradation
try {
return await getOptimalSessionProblems();
} catch (error) {
console.warn('Advanced selection failed, using fallback:', error);
return await getBasicSessionProblems();
}All database utilities are located in chrome-extension-app/src/shared/db/:
Core Stores:
problems.js- Problem data with Leitner systemsessions.js- Session management and analyticsattempts.js- Individual attempt trackingtag_mastery.js- Algorithm pattern masterypattern_ladder.js- Progressive difficulty ladders
Supporting Stores:
standard_problems.js- Canonical LeetCode problem databasesession_analytics.js- Detailed performance analysisproblem_relationships.js- Problem similarity graphtag_relationships.js- Algorithm tag classifications
Infrastructure:
index.js- Central database helper and schema managementcommon.js- Shared utilities and error handlingbackupDB.js/restoreDB.js- Backup and recovery operations
For implementation details and usage examples, refer to the individual store files and their integration within the service layer.