dart_db 0.1.0
dart_db: ^0.1.0 copied to clipboard
High-performance embedded key-value database for pure Dart backend applications. Built on LMDB with Rust FFI for persistence.
DartDB #
A high-performance embedded key-value database for pure Dart backend applications. Built on LMDB with Rust FFI for maximum performance and data persistence.
π Features #
- Embedded Database: No external database server required
- High Performance: Built on LMDB (Lightning Memory-Mapped Database)
- Persistent Storage: Data survives application restarts
- Redis-like API: Familiar interface for key-value operations
- Pure Dart: Designed specifically for Dart backend applications
- Cross Platform: Works on Linux, macOS, and Windows
- ACID Transactions: Full transaction support
- Memory Efficient: Memory-mapped files for optimal performance
- Rust FFI: Native performance through Rust integration
π― Use Cases #
Perfect for backend applications that need:
- Caching Layer: Fast in-memory cache with persistence
- Session Storage: User session data with reliability
- Configuration Storage: Application settings and metadata
- Queue Management: Job queues and task scheduling
- Metrics Collection: Performance metrics and analytics
- Embedded Analytics: Local data processing and aggregation
π¦ Installation #
Add this to your pubspec.yaml
:
dependencies:
dart_db: ^0.1.0
Then run:
dart pub get
π§ Quick Start #
import 'package:dart_db/dart_db.dart';
void main() async {
// Initialize the database
final db = await DartDB.open('my_database');
// Store data
await db.set('user:1', {'name': 'John', 'email': 'john@example.com'});
await db.set('counter', 42);
// Retrieve data
final user = await db.get('user:1');
final counter = await db.get<int>('counter');
print('User: $user');
print('Counter: $counter');
// Check if key exists
final exists = await db.exists('user:1');
print('User exists: $exists');
// Delete data
await db.delete('counter');
// Close the database
await db.close();
}
π API Reference #
Database Operations #
Opening a Database
// Open with default options
final db = await DartDB.open('database_name');
// Open with custom options
final db = await DartDB.open(
'database_name',
options: DatabaseOptions(
maxSize: 1024 * 1024 * 100, // 100MB
readOnly: false,
createIfNotExists: true,
),
);
Basic Operations
// Set a value
await db.set('key', 'value');
await db.set('user:123', {'name': 'Alice', 'age': 30});
// Get a value
final value = await db.get('key');
final user = await db.get<Map>('user:123');
// Get with default value
final count = await db.get('count', defaultValue: 0);
// Check if key exists
final exists = await db.exists('key');
// Delete a key
await db.delete('key');
// Get all keys
final keys = await db.keys();
// Get keys with pattern
final userKeys = await db.keys(pattern: 'user:*');
Batch Operations
// Set multiple values at once
await db.setMultiple({
'key1': 'value1',
'key2': 'value2',
'key3': 'value3',
});
// Get multiple values at once
final values = await db.getMultiple(['key1', 'key2', 'key3']);
// Delete multiple keys
await db.deleteMultiple(['key1', 'key2', 'key3']);
Advanced Operations
// Increment a numeric value
await db.increment('counter', by: 5);
// Decrement a numeric value
await db.decrement('counter', by: 2);
// Set with expiration (TTL)
await db.setWithTTL('session:abc', sessionData, Duration(hours: 2));
// Get database statistics
final stats = await db.stats();
print('Total keys: ${stats.keyCount}');
print('Database size: ${stats.sizeBytes}');
Transactions
// Execute operations in a transaction
await db.transaction((txn) async {
await txn.set('account:1', 100);
await txn.set('account:2', 200);
final total = await txn.get<int>('account:1') + await txn.get<int>('account:2');
await txn.set('total', total);
});
// Read-only transaction
final result = await db.readTransaction((txn) async {
final user1 = await txn.get('user:1');
final user2 = await txn.get('user:2');
return [user1, user2];
});
Data Types Support #
DartDB supports all JSON-serializable Dart types:
// Primitives
await db.set('string', 'Hello World');
await db.set('number', 42);
await db.set('double', 3.14159);
await db.set('boolean', true);
// Collections
await db.set('list', [1, 2, 3, 4, 5]);
await db.set('map', {'key': 'value', 'number': 123});
// Complex objects (must be JSON-serializable)
await db.set('user', {
'id': 123,
'name': 'Alice',
'preferences': {
'theme': 'dark',
'notifications': true,
},
'tags': ['admin', 'premium'],
});
β‘ Performance #
DartDB is built on LMDB, one of the fastest embedded databases available:
- Read Performance: Up to 1M+ reads per second
- Write Performance: Up to 100K+ writes per second
- Memory Efficient: Uses memory-mapped files
- Crash Safe: ACID transactions ensure data integrity
- Concurrent Access: Multiple readers, single writer
Benchmarks #
Operation | Operations/sec | Latency (avg)
-------------|----------------|-------------
GET | 1,200,000 | 0.8ΞΌs
SET | 150,000 | 6.7ΞΌs
DELETE | 180,000 | 5.6ΞΌs
BATCH SET | 300,000 | 3.3ΞΌs
TRANSACTION | 80,000 | 12.5ΞΌs
π§ Configuration #
Database Options #
final options = DatabaseOptions(
// Maximum database size (default: 100MB)
maxSize: 1024 * 1024 * 500, // 500MB
// Open database in read-only mode
readOnly: false,
// Create database if it doesn't exist
createIfNotExists: true,
// Number of readers allowed
maxReaders: 126,
// Sync mode for durability
syncMode: SyncMode.full, // full, lazy, none
// Compression settings
compression: CompressionOptions(
enabled: true,
algorithm: CompressionAlgorithm.lz4,
level: 1,
),
);
final db = await DartDB.open('database', options: options);
Environment Variables #
# Default database directory
export DART_DB_PATH=/var/lib/dart_db
# Default maximum size
export DART_DB_MAX_SIZE=104857600
# Log level
export DART_DB_LOG_LEVEL=info
ποΈ Architecture #
DartDB uses a layered architecture:
βββββββββββββββββββ
β Dart API β β High-level Dart interface
βββββββββββββββββββ€
β FFI Bridge β β Dart β Rust communication
βββββββββββββββββββ€
β Rust Core β β Core database logic
βββββββββββββββββββ€
β LMDB Engine β β Lightning Memory-Mapped DB
βββββββββββββββββββ
Components #
- Dart API: High-level, type-safe interface for Dart applications
- FFI Bridge: Efficient communication layer between Dart and Rust
- Rust Core: Core database operations, serialization, and error handling
- LMDB Engine: Battle-tested, high-performance storage engine
π Examples #
Web API Cache #
import 'package:dart_db/dart_db.dart';
class ApiCache {
late DartDB _db;
Future<void> init() async {
_db = await DartDB.open('api_cache');
}
Future<Map<String, dynamic>?> getCachedResponse(String endpoint) async {
return await _db.get<Map<String, dynamic>>(endpoint);
}
Future<void> cacheResponse(
String endpoint,
Map<String, dynamic> response,
{Duration? ttl}
) async {
if (ttl != null) {
await _db.setWithTTL(endpoint, response, ttl);
} else {
await _db.set(endpoint, response);
}
}
}
Session Store #
import 'package:dart_db/dart_db.dart';
class SessionStore {
late DartDB _db;
Future<void> init() async {
_db = await DartDB.open('sessions');
}
Future<void> createSession(String sessionId, Map<String, dynamic> data) async {
await _db.setWithTTL(
'session:$sessionId',
{
...data,
'created': DateTime.now().toIso8601String(),
'lastAccessed': DateTime.now().toIso8601String(),
},
Duration(hours: 24),
);
}
Future<Map<String, dynamic>?> getSession(String sessionId) async {
final session = await _db.get<Map<String, dynamic>>('session:$sessionId');
if (session != null) {
// Update last accessed time
session['lastAccessed'] = DateTime.now().toIso8601String();
await _db.setWithTTL('session:$sessionId', session, Duration(hours: 24));
}
return session;
}
Future<void> destroySession(String sessionId) async {
await _db.delete('session:$sessionId');
}
}
Configuration Manager #
import 'package:dart_db/dart_db.dart';
class ConfigManager {
late DartDB _db;
Future<void> init() async {
_db = await DartDB.open('app_config');
}
Future<T?> getConfig<T>(String key, {T? defaultValue}) async {
return await _db.get<T>(key, defaultValue: defaultValue);
}
Future<void> setConfig<T>(String key, T value) async {
await _db.set(key, value);
}
Future<Map<String, dynamic>> getAllConfig() async {
final keys = await _db.keys();
final configs = <String, dynamic>{};
for (final key in keys) {
configs[key] = await _db.get(key);
}
return configs;
}
}
π§ͺ Testing #
import 'package:test/test.dart';
import 'package:dart_db/dart_db.dart';
void main() {
group('DartDB Tests', () {
late DartDB db;
setUp(() async {
// Use in-memory database for testing
db = await DartDB.open(':memory:');
});
tearDown(() async {
await db.close();
});
test('should store and retrieve values', () async {
await db.set('test_key', 'test_value');
final value = await db.get('test_key');
expect(value, equals('test_value'));
});
test('should handle complex objects', () async {
final complexObject = {
'id': 123,
'name': 'Test User',
'preferences': ['dark_mode', 'notifications'],
};
await db.set('user', complexObject);
final retrieved = await db.get<Map>('user');
expect(retrieved, equals(complexObject));
});
});
}
π Troubleshooting #
Common Issues #
Database won't open
Error: Failed to open database
- Check file permissions on the database directory
- Ensure sufficient disk space
- Verify the database path is valid
Out of memory errors
Error: Out of memory
- Increase
maxSize
inDatabaseOptions
- Check available system memory
- Consider using compression
Performance issues
Slow read/write operations
- Use batch operations for multiple keys
- Enable compression for large values
- Consider using transactions for related operations
Debug Mode #
Enable debug logging:
DartDB.setLogLevel(LogLevel.debug);
Memory Usage #
Monitor memory usage:
final stats = await db.stats();
print('Memory usage: ${stats.memoryUsage} bytes');
print('Disk usage: ${stats.diskUsage} bytes');
π€ Contributing #
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup #
- Clone the repository
- Install Rust (for FFI compilation)
- Run
dart pub get
- Run tests with
dart test
Building #
# Build Rust FFI library
cargo build --release
# Run Dart tests
dart test
# Format code
dart format .
# Analyze code
dart analyze
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π Links #
π Acknowledgments #
- LMDB - Lightning Memory-Mapped Database
- Dart FFI - Foreign Function Interface
- Rust - Systems programming language
Built with β€οΈ for the Dart community by JhonaCode