runable
This commit is contained in:
522
HIVE_SETUP.md
Normal file
522
HIVE_SETUP.md
Normal file
@@ -0,0 +1,522 @@
|
||||
# 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!
|
||||
Reference in New Issue
Block a user