420 lines
12 KiB
Markdown
420 lines
12 KiB
Markdown
# Design Document - Sistema de Cache de Perfis
|
|
|
|
## Overview
|
|
|
|
Sistema de cache intermediário usando IndexedDB para armazenar dados de perfis estruturais. O sistema fornece uma camada de abstração entre os arquivos CSV originais e o aplicativo, permitindo carregamento rápido, sincronização sob demanda, e gerenciamento flexível de fontes de dados.
|
|
|
|
## Architecture
|
|
|
|
### High-Level Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Application Layer │
|
|
│ (UI Components, Sections, Calculations) │
|
|
└────────────────────┬────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Data Service API │
|
|
│ getPerfis() | searchPerfis() | getPerfilById() │
|
|
└────────────────────┬────────────────────────────────────┘
|
|
│
|
|
┌────────────┴────────────┐
|
|
▼ ▼
|
|
┌──────────────┐ ┌──────────────┐
|
|
│ Cache Layer │ │ CSV Loader │
|
|
│ (IndexedDB) │◄────────►│ (Fetch API) │
|
|
└──────────────┘ └──────────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌──────────────┐ ┌──────────────┐
|
|
│ Browser │ │ BD/perfis/ │
|
|
│ Storage │ │ *.csv │
|
|
└──────────────┘ └──────────────┘
|
|
```
|
|
|
|
### Component Diagram
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ CacheManager │
|
|
│ - init() │
|
|
│ - checkHealth() │
|
|
│ - clearAll() │
|
|
└────────────────────┬────────────────────────────────────┘
|
|
│
|
|
┌────────────┼────────────┬────────────┐
|
|
▼ ▼ ▼ ▼
|
|
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
│ DataStore│ │SyncManager│ │CSVParser │ │DataService│
|
|
│ │ │ │ │ │ │ │
|
|
│ -get() │ │ -sync() │ │ -parse() │ │ -query() │
|
|
│ -set() │ │ -check() │ │ -validate│ │ -filter()│
|
|
│ -delete()│ │ -update()│ │ │ │ -search()│
|
|
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
|
```
|
|
|
|
## Components and Interfaces
|
|
|
|
### 1. CacheManager (Core)
|
|
|
|
**Responsabilidade:** Gerenciar ciclo de vida do cache e coordenar componentes
|
|
|
|
```javascript
|
|
class CacheManager {
|
|
constructor(config) {
|
|
this.dbName = 'AcoCalcProDB';
|
|
this.version = 1;
|
|
this.db = null;
|
|
this.config = config;
|
|
}
|
|
|
|
async init() {
|
|
// Inicializar IndexedDB
|
|
// Criar object stores
|
|
// Verificar versão
|
|
}
|
|
|
|
async checkHealth() {
|
|
// Verificar integridade do cache
|
|
// Retornar estatísticas
|
|
}
|
|
|
|
async clearAll() {
|
|
// Limpar todo o cache
|
|
}
|
|
|
|
getStats() {
|
|
// Retornar estatísticas de uso
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. DataStore (Storage Layer)
|
|
|
|
**Responsabilidade:** Interface com IndexedDB
|
|
|
|
```javascript
|
|
class DataStore {
|
|
constructor(db) {
|
|
this.db = db;
|
|
}
|
|
|
|
async get(storeName, key) {
|
|
// Buscar item por chave
|
|
}
|
|
|
|
async getAll(storeName) {
|
|
// Buscar todos os itens
|
|
}
|
|
|
|
async set(storeName, data) {
|
|
// Armazenar dados
|
|
}
|
|
|
|
async delete(storeName, key) {
|
|
// Deletar item
|
|
}
|
|
|
|
async clear(storeName) {
|
|
// Limpar store
|
|
}
|
|
|
|
async count(storeName) {
|
|
// Contar itens
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. SyncManager (Synchronization)
|
|
|
|
**Responsabilidade:** Sincronizar dados entre CSV e cache
|
|
|
|
```javascript
|
|
class SyncManager {
|
|
constructor(dataStore, csvParser) {
|
|
this.dataStore = dataStore;
|
|
this.csvParser = csvParser;
|
|
this.sources = {}; // Mapeamento tipo -> caminho CSV
|
|
}
|
|
|
|
async syncAll(progressCallback) {
|
|
// Sincronizar todos os tipos
|
|
}
|
|
|
|
async syncType(tipo, progressCallback) {
|
|
// Sincronizar tipo específico
|
|
}
|
|
|
|
async checkUpdates() {
|
|
// Verificar se há atualizações disponíveis
|
|
}
|
|
|
|
async getLastSync(tipo) {
|
|
// Retornar timestamp da última sincronização
|
|
}
|
|
|
|
async calculateHash(csvText) {
|
|
// Calcular hash MD5 do CSV
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. CSVParser (Data Processing)
|
|
|
|
**Responsabilidade:** Parse e validação de arquivos CSV
|
|
|
|
```javascript
|
|
class CSVParser {
|
|
async parse(csvText, schema) {
|
|
// Parse CSV para objetos
|
|
// Validar contra schema
|
|
// Retornar dados processados
|
|
}
|
|
|
|
validate(data, schema) {
|
|
// Validar estrutura dos dados
|
|
}
|
|
|
|
transform(data, transformFn) {
|
|
// Aplicar transformações
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. DataService (API Layer)
|
|
|
|
**Responsabilidade:** API pública para acesso aos dados
|
|
|
|
```javascript
|
|
class DataService {
|
|
constructor(cacheManager, syncManager) {
|
|
this.cache = cacheManager;
|
|
this.sync = syncManager;
|
|
}
|
|
|
|
async getPerfis(tipo, options = {}) {
|
|
// Buscar perfis do cache ou CSV
|
|
// options: { forceRefresh, includeMetadata }
|
|
}
|
|
|
|
async searchPerfis(tipo, filters) {
|
|
// Buscar com filtros
|
|
// filters: { nome, peso_min, peso_max, etc }
|
|
}
|
|
|
|
async getPerfilById(tipo, id) {
|
|
// Buscar perfil específico
|
|
}
|
|
|
|
async getMetadata(tipo) {
|
|
// Retornar metadados (última sync, count, etc)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Data Models
|
|
|
|
### IndexedDB Schema
|
|
|
|
```javascript
|
|
const DB_SCHEMA = {
|
|
name: 'AcoCalcProDB',
|
|
version: 1,
|
|
stores: {
|
|
// Store para cada tipo de perfil
|
|
cantoneiras: {
|
|
keyPath: 'id',
|
|
indexes: [
|
|
{ name: 'nome', keyPath: 'nome', unique: false },
|
|
{ name: 'tipo', keyPath: 'tipo', unique: false },
|
|
{ name: 'peso_kg_m', keyPath: 'peso_kg_m', unique: false }
|
|
]
|
|
},
|
|
perfis_w: {
|
|
keyPath: 'id',
|
|
indexes: [
|
|
{ name: 'nome', keyPath: 'nome', unique: false },
|
|
{ name: 'peso', keyPath: 'peso', unique: false }
|
|
]
|
|
},
|
|
// ... outros tipos
|
|
|
|
// Store para metadados
|
|
_metadata: {
|
|
keyPath: 'tipo',
|
|
indexes: []
|
|
},
|
|
|
|
// Store para configuração
|
|
_config: {
|
|
keyPath: 'key',
|
|
indexes: []
|
|
}
|
|
}
|
|
};
|
|
```
|
|
|
|
### Metadata Model
|
|
|
|
```javascript
|
|
{
|
|
tipo: 'cantoneiras',
|
|
lastSync: 1699564800000, // timestamp
|
|
hash: 'a1b2c3d4e5f6...', // MD5 hash do CSV
|
|
count: 39,
|
|
version: '1.0',
|
|
source: 'BD/perfis/cantoneiras_brasil_completo.csv',
|
|
size: 12345 // bytes
|
|
}
|
|
```
|
|
|
|
### Config Model
|
|
|
|
```javascript
|
|
{
|
|
key: 'csv_sources',
|
|
value: {
|
|
cantoneiras: 'BD/perfis/cantoneiras_brasil_completo.csv',
|
|
perfis_w: 'BD/perfis/perfis_w_brasil_completo.csv',
|
|
// ... outros
|
|
}
|
|
}
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
### Error Types
|
|
|
|
```javascript
|
|
class CacheError extends Error {
|
|
constructor(message, code, details) {
|
|
super(message);
|
|
this.name = 'CacheError';
|
|
this.code = code;
|
|
this.details = details;
|
|
}
|
|
}
|
|
|
|
// Códigos de erro
|
|
const ERROR_CODES = {
|
|
DB_NOT_AVAILABLE: 'DB_NOT_AVAILABLE',
|
|
SYNC_FAILED: 'SYNC_FAILED',
|
|
CSV_PARSE_ERROR: 'CSV_PARSE_ERROR',
|
|
DATA_NOT_FOUND: 'DATA_NOT_FOUND',
|
|
QUOTA_EXCEEDED: 'QUOTA_EXCEEDED'
|
|
};
|
|
```
|
|
|
|
### Fallback Strategy
|
|
|
|
```
|
|
1. Tentar carregar do cache
|
|
↓ (falha)
|
|
2. Tentar carregar do CSV
|
|
↓ (falha)
|
|
3. Usar dados em memória (se disponível)
|
|
↓ (falha)
|
|
4. Exibir erro ao usuário
|
|
```
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Tests
|
|
|
|
- DataStore: CRUD operations
|
|
- CSVParser: Parse e validação
|
|
- SyncManager: Lógica de sincronização
|
|
- DataService: API pública
|
|
|
|
### Integration Tests
|
|
|
|
- Fluxo completo: CSV → Cache → UI
|
|
- Sincronização com múltiplos tipos
|
|
- Fallback quando IndexedDB não disponível
|
|
|
|
### Performance Tests
|
|
|
|
- Tempo de carregamento do cache
|
|
- Tempo de sincronização
|
|
- Uso de memória
|
|
- Tamanho do banco de dados
|
|
|
|
## Migration Strategy
|
|
|
|
### Phase 1: Implementação Base
|
|
- Criar estrutura do cache
|
|
- Implementar DataStore e CSVParser
|
|
- Testes unitários
|
|
|
|
### Phase 2: Integração
|
|
- Integrar com código existente
|
|
- Manter compatibilidade
|
|
- Testes de integração
|
|
|
|
### Phase 3: UI Admin
|
|
- Painel de administração
|
|
- Botões de sincronização
|
|
- Estatísticas
|
|
|
|
### Phase 4: Otimizações
|
|
- Web Workers para parsing
|
|
- Compressão de dados
|
|
- Lazy loading
|
|
|
|
## Configuration
|
|
|
|
### Default Configuration
|
|
|
|
```javascript
|
|
const DEFAULT_CONFIG = {
|
|
dbName: 'AcoCalcProDB',
|
|
version: 1,
|
|
autoSync: false, // Sincronizar automaticamente na inicialização
|
|
syncInterval: null, // Intervalo de sincronização automática (ms)
|
|
cacheExpiry: 7 * 24 * 60 * 60 * 1000, // 7 dias
|
|
enableCompression: false,
|
|
enableWebWorkers: false,
|
|
debug: false,
|
|
sources: {
|
|
cantoneiras: 'BD/perfis/cantoneiras_brasil_completo.csv',
|
|
barras: 'BD/perfis/barras_brasil_completo.csv',
|
|
// ... outros
|
|
}
|
|
};
|
|
```
|
|
|
|
## Performance Considerations
|
|
|
|
### Optimization Techniques
|
|
|
|
1. **Indexing**: Criar índices para campos frequentemente buscados
|
|
2. **Lazy Loading**: Carregar apenas dados necessários
|
|
3. **Compression**: Comprimir dados grandes antes de armazenar
|
|
4. **Web Workers**: Parse de CSV em background thread
|
|
5. **Batch Operations**: Inserir múltiplos registros de uma vez
|
|
|
|
### Expected Performance
|
|
|
|
- Cache hit: < 100ms
|
|
- Cache miss + CSV load: < 2s
|
|
- Sync all types: < 10s
|
|
- Search with filters: < 50ms
|
|
|
|
## Security Considerations
|
|
|
|
- IndexedDB é isolado por origem (same-origin policy)
|
|
- Dados não são criptografados (não contêm informações sensíveis)
|
|
- Validar dados do CSV antes de armazenar
|
|
- Limitar tamanho máximo do cache (50MB)
|
|
|
|
## Future Enhancements
|
|
|
|
1. **Sync com servidor remoto**: Permitir sincronizar com API REST
|
|
2. **Versionamento de dados**: Manter histórico de versões
|
|
3. **Diff e merge**: Detectar conflitos entre versões
|
|
4. **Export/Import**: Exportar cache para backup
|
|
5. **Compression**: Comprimir dados automaticamente
|
|
6. **Service Worker**: Cache de arquivos CSV para offline completo
|