fix: change cache service to component

This commit is contained in:
Polianin Nikita 2024-06-11 00:26:51 +03:00
parent 6fd78e7830
commit f5c7ceb850
2 changed files with 81 additions and 65 deletions

View File

@ -0,0 +1,81 @@
<h1>Настройка кэша</h1>
<hr/>
<p class="mat-body-2 secondary">
На этой странице вы можете выбрать и настроить параметры кэширования для приложения.
</p>
<p class="mat-body-2 secondary">
Укажите тип кэша, например, Redis, и настройте параметры подключения, чтобы улучшить производительность и снизить
нагрузку на базу данных.
</p>
<form [formGroup]="databaseForm">
<p>
Выберите базу данных для хранения кэша:
</p>
<mat-form-field color="accent">
<mat-label>База данных</mat-label>
<mat-select (valueChange)="onDatabaseChange($event)">
<mat-option value="redis">Redis</mat-option>
<mat-option value="memcached">Memcached</mat-option>
</mat-select>
</mat-form-field>
<div style="display:flex; flex-direction: column;">
@if (database && database !== "memcached") {
<hr/>
<mat-form-field color="accent">
<mat-label>Сервер</mat-label>
<input matInput
matTooltip='Укажите сервер в формате: "winsomnia.net" или ip адреса формата IPv4 или IPv6'
required
formControlName="server">
@if (databaseForm.get('server')?.hasError('required')) {
<mat-error>
Сервер является <i>обязательным</i>
</mat-error>
}
@if (databaseForm.get('server')?.hasError('pattern')) {
<mat-error>
Сервер должен содержать доменное имя сервера или ip адрес IPv4 или IPv6
</mat-error>
}
</mat-form-field>
<mat-form-field color="accent">
<mat-label>Порт</mat-label>
<input matInput
matTooltip="Укажите порт сервера"
required
formControlName="port">
@if (databaseForm.get('port')?.hasError('required')) {
<mat-error>
Порт является <i>обязательным</i>
</mat-error>
}
@if (databaseForm.get('port')?.hasError('pattern')) {
<mat-error>
Порт должен содержать цифры НЕ начиная с цифры 0 и далее не менее 2 цифр
</mat-error>
}
</mat-form-field>
<mat-form-field color="accent">
<mat-label>Пароль</mat-label>
<input matInput
matTooltip="Укажите пароль"
formControlName="password"
[type]="hidePass ? 'password' : 'text'">
<button mat-icon-button matSuffix (click)="togglePassword($event)" [attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hidePass">
<mat-icon>{{ hidePass ? 'visibility_off' : 'visibility' }}</mat-icon>
</button>
</mat-form-field>
}
</div>
</form>

View File

@ -1,65 +0,0 @@
import {Injectable} from '@angular/core';
interface CacheEntry<T> {
data: T;
expiry: number;
}
@Injectable({
providedIn: 'root'
})
export class CacheService {
private handleQuotaExceeded(): void {
const keys: string[] = [];
const expiries: number[] = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (!key) continue;
const cacheEntry = JSON.parse(localStorage.getItem(key) as string) as CacheEntry<any>;
keys.push(key);
expiries.push(cacheEntry.expiry);
}
// Удаляем самый старый элемент
const oldestIndex = expiries.indexOf(Math.min(...expiries));
localStorage.removeItem(keys[oldestIndex]);
}
private isQuotaExceededError(e: unknown): e is DOMException {
return e instanceof DOMException && (
e.name === 'QuotaExceededError' ||
e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
);
}
set<T>(key: string, data: T, ttl: number): void {
const expiry = Date.now() + ttl;
const cacheEntry: CacheEntry<T> = {data, expiry};
try {
localStorage.setItem(key, JSON.stringify(cacheEntry));
} catch (e) {
if (this.isQuotaExceededError(e)) {
this.handleQuotaExceeded();
localStorage.setItem(key, JSON.stringify(cacheEntry));
} else {
throw e;
}
}
}
get<T>(key: string): T | null {
const cached = localStorage.getItem(key);
if (!cached) return null;
const cacheEntry = JSON.parse(cached) as CacheEntry<T>;
if (Date.now() > cacheEntry.expiry) {
localStorage.removeItem(key);
return null;
}
return cacheEntry.data;
}
}