import { DatabaseContext, CacheOptions } from '../src/data/repository-data-contexts'; import { ReadRepository } from '../src/data/read-repository'; import { MemoryCacheManager } from '../src/data/cache-manager'; import { MongoSource } from '@soapjs/soap-mongo'; // Przykład dla MongoDB import { MetaMapper } from '../src/data/meta-mapper'; // Przykład 1: Użycie z MemoryCacheManager export function createCachedUserRepository() { // 1. Skonfiguruj opcje cache const cacheOptions: CacheOptions = { ttl: 300, // 5 minut store: 'memory', prefix: 'users', enabled: true }; // 2. Stwórz cache manager z opcjami const cacheManager = new MemoryCacheManager(cacheOptions); // 3. Stwórz source (przykład dla MongoDB) const userSource = new MongoSource(mongo, 'users', { modelClass: UserModel }); // 4. Stwórz mapper const userMapper = new MetaMapper(User, UserModel); // 5. Stwórz context z cache const userContext = new DatabaseContext( userSource, userMapper, sessionRegistry, cacheManager ); // 6. Stwórz repository const userRepository = new ReadRepository(userContext); return userRepository; } // Przykład 2: Użycie z RedisCacheManager (implementacja w soap-node-redis) // export function createRedisCachedUserRepository(redisClient: any) { // const cacheOptions: CacheOptions = { // ttl: 600, // 10 minut // store: 'redis', // prefix: 'users', // enabled: true // }; // // const cacheManager = new RedisCacheManager(redisClient, cacheOptions); // // const userSource = new MongoSource(mongo, 'users', { // modelClass: UserModel // }); // // const userMapper = new MetaMapper(User, UserModel); // // const userContext = new DatabaseContext( // userSource, // userMapper, // sessionRegistry, // cacheManager // ); // // return new ReadRepository(userContext); // } // Przykład 3: Repository bez cache export function createNonCachedUserRepository() { const userSource = new MongoSource(mongo, 'users', { modelClass: UserModel }); const userMapper = new MetaMapper(User, UserModel); // Bez cache managera - cache będzie wyłączone const userContext = new DatabaseContext( userSource, userMapper, sessionRegistry ); return new ReadRepository(userContext); } // Przykład 4: Użycie w Use Case export class GetUserUseCase { constructor(private userRepository: ReadRepository) {} async execute(userId: string): Promise> { // Repository automatycznie sprawdzi cache i zwróci dane z cache lub bazy const result = await this.userRepository.find({ where: { id: userId } }); if (result.isSuccess()) { return Result.withSuccess(result.value[0]); } return Result.withFailure(result.failure); } async getActiveUsers(): Promise> { // To zapytanie również będzie cachowane return await this.userRepository.find({ where: { status: 'active' } }); } } // Przykład 5: Konfiguracja cache per operacja export function createAdvancedCachedRepository() { const cacheManager = new MemoryCacheManager(); // Różne TTL dla różnych operacji const cacheOptions: CacheOptions = { ttl: 300, // Domyślny TTL store: 'memory', prefix: 'users', enabled: true }; const userContext = new DatabaseContext( userSource, userMapper, sessionRegistry, cacheManager, cacheOptions ); const repository = new ReadRepository(userContext); // Można też ręcznie zarządzać cache return { repository, clearUserCache: () => cacheManager.clear('users'), clearSpecificCache: (key: string) => cacheManager.delete(key) }; } // Przykład 6: Testowanie z cache export class UserServiceTest { async testCachedRepository() { // Stwórz repository z cache const userRepository = createCachedUserRepository(); // Pierwsze wywołanie - pobierze z bazy i zapisze do cache const result1 = await userRepository.find({ where: { status: 'active' } }); console.log('First call - from database:', result1.isSuccess()); // Drugie wywołanie - pobierze z cache const result2 = await userRepository.find({ where: { status: 'active' } }); console.log('Second call - from cache:', result2.isSuccess()); // Oba wyniki powinny być identyczne expect(result1.value).toEqual(result2.value); } } // Przykład 7: Wyłączanie cache dla konkretnych operacji export class SelectiveCacheRepository extends ReadRepository { async findWithoutCache(paramsOrQuery?: FindParams | RepositoryQuery): Promise> { // Tymczasowo wyłącz cache const originalEnabled = this.context.cacheOptions?.enabled; if (this.context.cacheOptions) { this.context.cacheOptions.enabled = false; } try { return await this.find(paramsOrQuery); } finally { // Przywróć oryginalne ustawienie if (this.context.cacheOptions) { this.context.cacheOptions.enabled = originalEnabled; } } } } // Przykład 8: Monitoring cache export class CacheMonitoringRepository extends ReadRepository { private cacheHits = 0; private cacheMisses = 0; async find(paramsOrQuery?: FindParams | RepositoryQuery): Promise> { const startTime = Date.now(); try { let query: DbQuery; if (FindParams.isFindParams(paramsOrQuery)) { query = paramsOrQuery; } else if (RepositoryQuery.isQueryBuilder(paramsOrQuery)) { query = paramsOrQuery.build(); } else { query = {}; } // Check cache first if (this.context.isCacheEnabled && this.context.isCacheEnabled()) { const cacheKey = this.context.getCacheKey('find', query); const cached = await this.context.cache!.get(cacheKey); if (cached) { this.cacheHits++; console.log(`Cache HIT for key: ${cacheKey}`); return Result.withSuccess(cached); } this.cacheMisses++; console.log(`Cache MISS for key: ${cacheKey}`); } // Get from database const documents = await this.context.source.find(query); const entities = documents.map((document) => this.context.mapper.toEntity(document)); // Cache the result if (this.context.isCacheEnabled && this.context.isCacheEnabled()) { const cacheKey = this.context.getCacheKey('find', query); const ttl = this.context.cacheOptions?.ttl || 300; await this.context.cache!.set(cacheKey, entities, ttl); } const duration = Date.now() - startTime; console.log(`Query executed in ${duration}ms`); return Result.withSuccess(entities); } catch (error) { return Result.withFailure(Failure.fromError(error)); } } getCacheStats() { return { hits: this.cacheHits, misses: this.cacheMisses, hitRate: this.cacheHits / (this.cacheHits + this.cacheMisses) }; } }