Files
worker/HIVE_SETUP.md
Phuoc Nguyen 628c81ce13 runable
2025-10-17 17:22:28 +07:00

13 KiB

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:

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

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

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

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

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

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

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)

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

// 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

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

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

# 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!