Skip to content

Cache oprávnění

Přehled

Permission checky jsou cachované v LRU (Least Recently Used) cache v paměti procesu. To výrazně snižuje zátěž databáze při opakovaných ověřeních.

Konfigurace cache

ParametrHodnota
TTL30 sekund
Max položek5 000
TypLRU (nejméně používané se zahazují)
ScopeIn-memory (per-process)

Klíč cache

Každý záznam v cache je identifikován kombinací:

{email}:{appCode}:{permissionCode}:{resourceType}:{resourceId}

Příklady:

uzivatel@firma.cz:crm:documents.read::
uzivatel@firma.cz:crm:documents.read:document:42

Pokud resourceType nebo resourceId nejsou zadány, v klíči jsou prázdné.

Životní cyklus cache záznamu

Request → cache HIT?

    ├─ ANO → Vrátit cachovný výsledek (< 1 ms)

    └─ NE → Databázový dotaz (vyhodnocení)

              └─ Uložit výsledek do cache (TTL 30 s)
                 └─ Vrátit výsledek

Invalidace cache

Automatická (TTL expirací)

Cache záznamy expirují automaticky po 30 sekundách. Není potřeba žádná akce.

Manuální invalidace

Pokud provedete hromadné změny (přiřazení rolí, změna oprávnění), lze cache okamžitě invalidovat:

bash
POST /api/check/cache/clear

# Odpověď
{ "success": true, "data": { "message": "Cache cleared" } }

Kdy ručně invalidovat?

Po hromadném přiřazení rolí nebo změně oprávnění v admin panelu. Jinak čekejte maximálně 30 sekund, než se změny projeví.

Dopady při horizontálním škálování

Více instancí

Cache je in-memory — každý proces má vlastní cache. Při více instancích (load balancer) mohou různé instance vracet různé výsledky po dobu až 30 sekund po změně.

Řešení:

  1. Přijměte eventual consistency (30 s okno) — doporučeno
  2. Volejte POST /check/cache/clear na všechny instance
  3. Pro kritické aplikace pište POST /check s krátkým TTL a bez cache (není implementováno)

Performance

Dopad LRU cache na latenci:

ScénářLatence
Cache HIT< 1 ms
Cache MISS (DB dotaz)5–30 ms
Bulk check (10 oprávnění, HIT)< 5 ms

Implementace

typescript
// CheckService (zjednodušeně)
import { LRUCache } from 'lru-cache';

const cache = new LRUCache<string, boolean>({
  max: 5000,
  ttl: 30_000,  // 30 sekund v ms
});

function getCacheKey(
  email: string,
  app: string,
  permission: string,
  resourceType?: string,
  resourceId?: string
): string {
  return `${email}:${app}:${permission}:${resourceType ?? ''}:${resourceId ?? ''}`;
}

async function check(email, app, permission, resourceType?, resourceId?) {
  const key = getCacheKey(email, app, permission, resourceType, resourceId);
  
  if (cache.has(key)) {
    return cache.get(key);
  }
  
  const result = await evaluatePermission(email, app, permission, resourceType, resourceId);
  cache.set(key, result);
  return result;
}

Atrea User API — interní dokumentace