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": { "cleared": true } }

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;
}

Jabcore Platform — interní dokumentace