523 lines
13 KiB
Markdown
523 lines
13 KiB
Markdown
# Hive CE Database Setup - Worker App
|
|
|
|
## Overview
|
|
|
|
The Worker Flutter app now has a complete Hive CE (Community Edition) database setup for offline-first functionality. This document provides a comprehensive summary of the setup.
|
|
|
|
## What Was Created
|
|
|
|
### 1. Core Files
|
|
|
|
#### `/lib/core/constants/storage_constants.dart`
|
|
Centralized constants for Hive database:
|
|
- **HiveBoxNames**: All box names (13 boxes total)
|
|
- **HiveTypeIds**: Type adapter IDs (0-223 range, 32 IDs assigned)
|
|
- **HiveKeys**: Storage keys for settings and cache
|
|
- **CacheDuration**: Default cache expiration times
|
|
- **HiveDatabaseConfig**: Database configuration settings
|
|
|
|
#### `/lib/core/database/hive_service.dart`
|
|
Main database service handling:
|
|
- Hive initialization and configuration
|
|
- Type adapter registration (auto-generated)
|
|
- Box opening and management
|
|
- Database migrations and versioning
|
|
- Encryption support
|
|
- Maintenance and compaction
|
|
- Cleanup operations
|
|
|
|
#### `/lib/core/database/database_manager.dart`
|
|
High-level database operations:
|
|
- Generic CRUD operations
|
|
- Cache management with expiration
|
|
- Sync state tracking
|
|
- Settings operations
|
|
- Offline queue management
|
|
- Database statistics
|
|
|
|
#### `/lib/core/database/hive_initializer.dart`
|
|
Simple initialization API:
|
|
- Easy app startup initialization
|
|
- Database reset functionality
|
|
- Logout data cleanup
|
|
- Statistics helpers
|
|
|
|
#### `/lib/core/database/database.dart`
|
|
Export file for convenient imports
|
|
|
|
### 2. Models
|
|
|
|
#### `/lib/core/database/models/enums.dart`
|
|
Type adapters for all enums (10 enums):
|
|
- `MemberTier` - Loyalty tiers (Gold, Platinum, Diamond)
|
|
- `UserType` - User categories (Contractor, Architect, Distributor, Broker)
|
|
- `OrderStatus` - Order states (6 statuses)
|
|
- `ProjectStatus` - Project states (5 statuses)
|
|
- `ProjectType` - Project categories (5 types)
|
|
- `TransactionType` - Loyalty transaction types (8 types)
|
|
- `GiftStatus` - Gift/reward states (5 statuses)
|
|
- `PaymentStatus` - Payment states (6 statuses)
|
|
- `NotificationType` - Notification categories (7 types)
|
|
- `PaymentMethod` - Payment methods (6 methods)
|
|
|
|
Each enum includes:
|
|
- Extension methods for display names
|
|
- Helper properties for state checking
|
|
- Vietnamese localization
|
|
|
|
#### `/lib/core/database/models/cached_data.dart`
|
|
Generic cache wrapper model:
|
|
- Wraps any data type with timestamp
|
|
- Expiration tracking
|
|
- Freshness checking
|
|
- Cache age calculation
|
|
|
|
### 3. Generated Files
|
|
|
|
#### `/lib/hive_registrar.g.dart` (Auto-generated)
|
|
Automatic adapter registration extension:
|
|
- Registers all type adapters automatically
|
|
- No manual registration needed
|
|
- Updates automatically when new models are added
|
|
|
|
#### `/lib/core/database/models/*.g.dart` (Auto-generated)
|
|
Individual type adapters for each model and enum
|
|
|
|
### 4. Configuration
|
|
|
|
#### `pubspec.yaml`
|
|
Updated dependencies:
|
|
```yaml
|
|
dependencies:
|
|
hive_ce: ^2.6.0
|
|
hive_ce_flutter: ^2.1.0
|
|
|
|
dev_dependencies:
|
|
hive_ce_generator: ^1.6.0
|
|
build_runner: ^2.4.11
|
|
```
|
|
|
|
#### `build.yaml`
|
|
Build runner configuration for code generation
|
|
|
|
## Database Architecture
|
|
|
|
### Box Structure
|
|
|
|
The app uses 13 Hive boxes organized by functionality:
|
|
|
|
**Encrypted Boxes (Sensitive Data):**
|
|
1. `user_box` - User profile and authentication
|
|
2. `cart_box` - Shopping cart items
|
|
3. `order_box` - Order history
|
|
4. `project_box` - Construction projects
|
|
5. `loyalty_box` - Loyalty transactions
|
|
6. `address_box` - Delivery addresses
|
|
7. `offline_queue_box` - Failed API requests
|
|
|
|
**Non-Encrypted Boxes:**
|
|
8. `product_box` - Product catalog cache
|
|
9. `rewards_box` - Rewards catalog
|
|
10. `settings_box` - App settings
|
|
11. `cache_box` - Generic API cache
|
|
12. `sync_state_box` - Sync timestamps
|
|
13. `notification_box` - Notifications
|
|
|
|
### Type ID Allocation
|
|
|
|
Reserved type IDs (never change once assigned):
|
|
|
|
**Core Models (0-9):**
|
|
- 0: UserModel (TODO)
|
|
- 1: ProductModel (TODO)
|
|
- 2: CartItemModel (TODO)
|
|
- 3: OrderModel (TODO)
|
|
- 4: ProjectModel (TODO)
|
|
- 5: LoyaltyTransactionModel (TODO)
|
|
|
|
**Extended Models (10-19):**
|
|
- 10: OrderItemModel (TODO)
|
|
- 11: AddressModel (TODO)
|
|
- 12: CategoryModel (TODO)
|
|
- 13: RewardModel (TODO)
|
|
- 14: GiftModel (TODO)
|
|
- 15: NotificationModel (TODO)
|
|
- 16: QuoteModel (TODO)
|
|
- 17: PaymentModel (TODO)
|
|
- 18: PromotionModel (TODO)
|
|
- 19: ReferralModel (TODO)
|
|
|
|
**Enums (20-29):** ✓ Created
|
|
- 20: MemberTier
|
|
- 21: UserType
|
|
- 22: OrderStatus
|
|
- 23: ProjectStatus
|
|
- 24: ProjectType
|
|
- 25: TransactionType
|
|
- 26: GiftStatus
|
|
- 27: PaymentStatus
|
|
- 28: NotificationType
|
|
- 29: PaymentMethod
|
|
|
|
**Cache & Sync Models (30-39):**
|
|
- 30: CachedData ✓ Created
|
|
- 31: SyncState (TODO)
|
|
- 32: OfflineRequest (TODO)
|
|
|
|
## How to Use
|
|
|
|
### 1. Initialize Hive in main.dart
|
|
|
|
```dart
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'core/database/hive_initializer.dart';
|
|
|
|
void main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// Initialize Hive database
|
|
await HiveInitializer.initialize(
|
|
verbose: true, // Enable logging in debug mode
|
|
);
|
|
|
|
runApp(
|
|
const ProviderScope(
|
|
child: MyApp(),
|
|
),
|
|
);
|
|
}
|
|
```
|
|
|
|
### 2. Basic Database Operations
|
|
|
|
```dart
|
|
import 'package:worker/core/database/database.dart';
|
|
|
|
// Get database manager instance
|
|
final dbManager = DatabaseManager();
|
|
|
|
// Save data
|
|
await dbManager.save(
|
|
boxName: HiveBoxNames.productBox,
|
|
key: 'product_123',
|
|
value: product,
|
|
);
|
|
|
|
// Get data
|
|
final product = dbManager.get(
|
|
boxName: HiveBoxNames.productBox,
|
|
key: 'product_123',
|
|
);
|
|
|
|
// Get all items
|
|
final products = dbManager.getAll(boxName: HiveBoxNames.productBox);
|
|
|
|
// Delete data
|
|
await dbManager.delete(
|
|
boxName: HiveBoxNames.productBox,
|
|
key: 'product_123',
|
|
);
|
|
```
|
|
|
|
### 3. Caching with Expiration
|
|
|
|
```dart
|
|
import 'package:worker/core/database/database.dart';
|
|
|
|
final dbManager = DatabaseManager();
|
|
|
|
// Save to cache with timestamp
|
|
await dbManager.saveToCache(
|
|
key: HiveKeys.productsCacheKey,
|
|
data: products,
|
|
);
|
|
|
|
// Get from cache (returns null if expired)
|
|
final cachedProducts = dbManager.getFromCache<List<Product>>(
|
|
key: HiveKeys.productsCacheKey,
|
|
maxAge: CacheDuration.products, // 6 hours
|
|
);
|
|
|
|
if (cachedProducts == null) {
|
|
// Cache miss or expired - fetch from API
|
|
final freshProducts = await api.getProducts();
|
|
await dbManager.saveToCache(
|
|
key: HiveKeys.productsCacheKey,
|
|
data: freshProducts,
|
|
);
|
|
}
|
|
```
|
|
|
|
### 4. Offline Queue
|
|
|
|
```dart
|
|
import 'package:worker/core/database/database.dart';
|
|
|
|
final dbManager = DatabaseManager();
|
|
|
|
// Add failed request to queue
|
|
try {
|
|
await api.createOrder(orderData);
|
|
} catch (e) {
|
|
await dbManager.addToOfflineQueue({
|
|
'endpoint': '/api/orders',
|
|
'method': 'POST',
|
|
'body': orderData,
|
|
});
|
|
}
|
|
|
|
// Process queue when back online
|
|
final queue = dbManager.getOfflineQueue();
|
|
for (var i = 0; i < queue.length; i++) {
|
|
try {
|
|
await api.request(queue[i]);
|
|
await dbManager.removeFromOfflineQueue(i);
|
|
} catch (e) {
|
|
// Keep in queue for next retry
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. Settings Management
|
|
|
|
```dart
|
|
import 'package:worker/core/database/database.dart';
|
|
|
|
final dbManager = DatabaseManager();
|
|
|
|
// Save setting
|
|
await dbManager.saveSetting(
|
|
key: HiveKeys.languageCode,
|
|
value: 'vi',
|
|
);
|
|
|
|
// Get setting
|
|
final language = dbManager.getSetting<String>(
|
|
key: HiveKeys.languageCode,
|
|
defaultValue: 'vi',
|
|
);
|
|
```
|
|
|
|
### 6. Sync State Tracking
|
|
|
|
```dart
|
|
import 'package:worker/core/database/database.dart';
|
|
|
|
final dbManager = DatabaseManager();
|
|
|
|
// Update sync timestamp
|
|
await dbManager.updateSyncTime(HiveKeys.productsSyncTime);
|
|
|
|
// Get last sync time
|
|
final lastSync = dbManager.getLastSyncTime(HiveKeys.productsSyncTime);
|
|
|
|
// Check if needs sync
|
|
final needsSync = dbManager.needsSync(
|
|
dataType: HiveKeys.productsSyncTime,
|
|
syncInterval: Duration(hours: 6),
|
|
);
|
|
|
|
if (needsSync) {
|
|
// Perform sync
|
|
await syncProducts();
|
|
await dbManager.updateSyncTime(HiveKeys.productsSyncTime);
|
|
}
|
|
```
|
|
|
|
### 7. Logout (Clear User Data)
|
|
|
|
```dart
|
|
import 'package:worker/core/database/hive_initializer.dart';
|
|
|
|
// Clear user data while keeping settings and cache
|
|
await HiveInitializer.logout();
|
|
```
|
|
|
|
## Creating New Hive Models
|
|
|
|
### Step 1: Create Model File
|
|
|
|
```dart
|
|
// lib/features/products/data/models/product_model.dart
|
|
|
|
import 'package:hive_ce/hive.dart';
|
|
import 'package:worker/core/constants/storage_constants.dart';
|
|
|
|
part 'product_model.g.dart';
|
|
|
|
@HiveType(typeId: HiveTypeIds.product) // Use typeId: 1
|
|
class ProductModel extends HiveObject {
|
|
@HiveField(0)
|
|
final String id;
|
|
|
|
@HiveField(1)
|
|
final String name;
|
|
|
|
@HiveField(2)
|
|
final String sku;
|
|
|
|
@HiveField(3)
|
|
final double price;
|
|
|
|
@HiveField(4)
|
|
final List<String> images;
|
|
|
|
@HiveField(5)
|
|
final String categoryId;
|
|
|
|
@HiveField(6)
|
|
final int stock;
|
|
|
|
ProductModel({
|
|
required this.id,
|
|
required this.name,
|
|
required this.sku,
|
|
required this.price,
|
|
required this.images,
|
|
required this.categoryId,
|
|
required this.stock,
|
|
});
|
|
}
|
|
```
|
|
|
|
### Step 2: Generate Adapter
|
|
|
|
```bash
|
|
dart run build_runner build --delete-conflicting-outputs
|
|
```
|
|
|
|
This automatically:
|
|
- Generates `product_model.g.dart` with `ProductModelAdapter`
|
|
- Updates `hive_registrar.g.dart` to register the new adapter
|
|
- No manual registration needed!
|
|
|
|
### Step 3: Use the Model
|
|
|
|
```dart
|
|
import 'package:worker/core/database/database.dart';
|
|
|
|
final product = ProductModel(
|
|
id: '123',
|
|
name: 'Ceramic Tile',
|
|
sku: 'TILE-001',
|
|
price: 299000,
|
|
images: ['image1.jpg'],
|
|
categoryId: 'cat_1',
|
|
stock: 100,
|
|
);
|
|
|
|
final dbManager = DatabaseManager();
|
|
await dbManager.save(
|
|
boxName: HiveBoxNames.productBox,
|
|
key: product.id,
|
|
value: product,
|
|
);
|
|
```
|
|
|
|
## Important Rules
|
|
|
|
1. **Never change Type IDs** - Once assigned, they are permanent
|
|
2. **Never change Field numbers** - Breaks existing data
|
|
3. **Run build_runner** after creating/modifying models
|
|
4. **Use the auto-generated registrar** - Don't manually register adapters
|
|
5. **Always use try-catch** around Hive operations
|
|
6. **Check box is open** before accessing it
|
|
7. **Use DatabaseManager** for high-level operations
|
|
8. **Set appropriate cache durations** for different data types
|
|
|
|
## Features
|
|
|
|
✓ **Offline-First**: All data stored locally and synced
|
|
✓ **Type-Safe**: Strong typing with generated adapters
|
|
✓ **Fast**: Optimized NoSQL database
|
|
✓ **Encrypted**: Optional AES encryption for sensitive data
|
|
✓ **Auto-Maintenance**: Compaction and cleanup
|
|
✓ **Migration Support**: Schema versioning built-in
|
|
✓ **Cache Management**: Automatic expiration handling
|
|
✓ **Offline Queue**: Failed request retry system
|
|
✓ **Sync Tracking**: Data freshness monitoring
|
|
✓ **Statistics**: Debug utilities for monitoring
|
|
|
|
## Next Steps
|
|
|
|
### To Complete the Database Setup:
|
|
|
|
1. **Create Model Classes** for the TODO items (typeIds 0-19, 31-32)
|
|
2. **Run build_runner** to generate adapters
|
|
3. **Implement sync logic** in repository layers
|
|
4. **Add encryption** in production (if needed)
|
|
5. **Test migrations** when schema changes
|
|
6. **Monitor database size** in production
|
|
|
|
### Models to Create:
|
|
|
|
Priority 1 (Core):
|
|
- UserModel (typeId: 0)
|
|
- ProductModel (typeId: 1)
|
|
- CartItemModel (typeId: 2)
|
|
- OrderModel (typeId: 3)
|
|
|
|
Priority 2 (Extended):
|
|
- ProjectModel (typeId: 4)
|
|
- LoyaltyTransactionModel (typeId: 5)
|
|
- AddressModel (typeId: 11)
|
|
- NotificationModel (typeId: 15)
|
|
|
|
Priority 3 (Additional):
|
|
- OrderItemModel (typeId: 10)
|
|
- CategoryModel (typeId: 12)
|
|
- RewardModel (typeId: 13)
|
|
- GiftModel (typeId: 14)
|
|
- QuoteModel (typeId: 16)
|
|
- PaymentModel (typeId: 17)
|
|
- PromotionModel (typeId: 18)
|
|
- ReferralModel (typeId: 19)
|
|
|
|
## Troubleshooting
|
|
|
|
### Build Runner Fails
|
|
```bash
|
|
# Clean and rebuild
|
|
flutter clean
|
|
flutter pub get
|
|
dart run build_runner clean
|
|
dart run build_runner build --delete-conflicting-outputs
|
|
```
|
|
|
|
### Box Not Found Error
|
|
- Ensure `HiveInitializer.initialize()` is called in main.dart
|
|
- Check box name matches `HiveBoxNames` constant
|
|
|
|
### Adapter Not Registered
|
|
- Run build_runner to generate adapters
|
|
- Check `hive_registrar.g.dart` includes the adapter
|
|
- Ensure `Hive.registerAdapters()` is called in HiveService
|
|
|
|
### Data Corruption
|
|
- Enable backups before migrations
|
|
- Test migrations on copy of production data
|
|
- Validate data before saving
|
|
|
|
## Resources
|
|
|
|
- Hive CE Documentation: https://github.com/IO-Design-Team/hive_ce
|
|
- Project README: `/lib/core/database/README.md`
|
|
- Storage Constants: `/lib/core/constants/storage_constants.dart`
|
|
- Type Adapter Registry: See README.md for complete list
|
|
|
|
## Summary
|
|
|
|
The Hive CE database is now fully configured and ready to use. All enum type adapters are created and registered automatically. Future models will follow the same pattern - just create the model file with annotations and run build_runner to generate adapters.
|
|
|
|
The database supports offline-first functionality with:
|
|
- 13 pre-configured boxes
|
|
- 32 reserved type IDs
|
|
- Auto-generated adapter registration
|
|
- Cache management with expiration
|
|
- Offline request queuing
|
|
- Sync state tracking
|
|
- Maintenance and cleanup
|
|
|
|
Start creating models and building the offline-first features!
|