Skip to content

Cache API (KV)

Управление высокоуровневым KV хранилищем (Cloudflare KV) для кэширования и флагов интеграций.

Архитектура

Cache - это высокоуровневый API для работы с KV, автоматически группирующий данные по интеграциям.

Admin UI
   |
   v
/api/core/cache (GET, PATCH, DELETE)
   |
   v
CacheController (высокоуровневая логика с группировкой)
   |
   v
Cloudflare KV (CACHE namespace с ключами: integ:*)

Формат ключей

Все ключи в KV группируются по интеграции с использованием префикса:

{integration}:{category}:{id}

Примеры:

  • sofa:ratelimit:client123 - Rate limit счётчик
  • sofa:cache:contact:456 - Кешированный контакт
  • sofa:lock:sync - Лок для синхронизации
  • rozetka:flag:enabled - Флаг включения интеграции

Использование в integ-core

1. Rate Limiting

typescript
// Ограничить запросы к API клиента
const key = `${integration}:ratelimit:${clientId}:${minute}`;
const count = (await env.KV.get(key)) || 0;
if (count > 100) throw new Error("Rate limit exceeded");
await env.KV.put(key, count + 1, { expirationTtl: 60 });

2. Кеш внешних API

typescript
// Кешировать ответ CRM на 5 минут
const cacheKey = `${integration}:cache:contact:${contactId}`;
let contact = await env.KV.get(cacheKey, "json");
if (!contact) {
	contact = await crmApi.getContact(contactId);
	await env.KV.put(cacheKey, JSON.stringify(contact), { expirationTtl: 300 });
}

3. Feature Flags

typescript
// Мгновенно включить/выключить интеграцию
const enabled = await env.KV.get(`${integration}:flag:enabled`);
if (enabled === "false") return new Response("Integration disabled", { status: 503 });

4. Сессии / Временные токены

typescript
// OAuth state, одноразовые ссылки
await env.KV.put(`${integration}:oauth:state:${state}`, userId, { expirationTtl: 600 });

5. Идемпотентность вебхуков

typescript
// Не обрабатывать дубли
const processed = await env.KV.get(`${integration}:webhook:${webhookId}`);
if (processed) return new Response("Already processed");
await env.KV.put(`${integration}:webhook:${webhookId}`, "1", { expirationTtl: 86400 });

6. Лок на обработку

typescript
// Не запускать два процесса параллельно
const lockKey = `${integration}:lock:sync`;
const lock = await env.KV.get(lockKey);
if (lock) return; // уже выполняется
await env.KV.put(lockKey, Date.now(), { expirationTtl: 300 });

API Эндпоинты

GET /api/core/cache

Получить все ключи (grouped by integration).

Query Parameters:

  • integration (optional) - фильтр по названию интеграции (берет prefix={integration}:)

Request:

http
GET /api/core/cache
Authorization: Bearer <token>

или с фильтром:

http
GET /api/core/cache?integration=sofa
Authorization: Bearer <token>

Response (200 OK):

json
{
	"keys": [
		{ "name": "sofa:ratelimit:client123", "metadata": {} },
		{ "name": "sofa:cache:contact:456", "metadata": {} }
	],
	"grouped": {
		"sofa": ["ratelimit:client123", "cache:contact:456"]
	}
}

GET /api/core/cache/keys/:key

Получить значение ключа.

Parameters:

  • :key - Base64-encoded ключ

Request:

http
GET /api/core/cache/keys/c29mYTpyYXRlbGltaXQ6Y2xpZW50MTIz
Authorization: Bearer <token>

Response (200 OK):

json
{
	"value": 42
}

PATCH /api/core/cache/keys/:key

Установить значение ключа.

Parameters:

  • :key - Base64-encoded ключ

Request:

http
PATCH /api/core/cache/keys/c29mYTpyYXRlbGltaXQ6Y2xpZW50MTIz
Authorization: Bearer <token>
Content-Type: application/json

{
  "value": "{ \"count\": 42 }",
  "ttl": 300
}

Response (200 OK):

json
{
	"success": true
}

DELETE /api/core/cache/keys/:key

Удалить ключ.

Parameters:

  • :key - Base64-encoded ключ

Request:

http
DELETE /api/core/cache/keys/c29mYTpyYXRlbGltaXQ6Y2xpZW50MTIz
Authorization: Bearer <token>

Response (200 OK):

json
{
	"success": true
}

DELETE /api/core/cache/integrations/:name

Удалить все ключи интеграции (очистить весь prefix).

Parameters:

  • :name - Название интеграции (sofa, rozetka, etc)

Request:

http
DELETE /api/core/cache/integrations/sofa
Authorization: Bearer <token>

Response (200 OK):

json
{
	"success": true
}

Пример использования

typescript
import axios from "axios";

const api = axios.create({
	baseURL: "http://localhost:3000/api",
	headers: {
		Authorization: `Bearer ${token}`
	}
});

async function manageCache() {
	// 1. Получить все ключи
	const { data: allKeys } = await api.get("/core/cache");
	console.log("All keys:", allKeys);

	// 2. Получить только ключи sofa интеграции
	const { data: sofaKeys } = await api.get("/core/cache?integration=sofa");
	console.log("Sofa keys:", sofaKeys);

	// 3. Установить значение
	const key = Buffer.from("sofa:ratelimit:client123").toString("base64");
	await api.patch(`/core/cache/keys/${key}`, {
		value: "42",
		ttl: 300
	});

	// 4. Получить значение
	const { data: value } = await api.get(`/core/cache/keys/${key}`);
	console.log("Value:", value.value);

	// 5. Удалить ключ
	await api.delete(`/core/cache/keys/${key}`);
	console.log("Deleted");

	// 6. Очистить всю интеграцию
	await api.delete("/core/cache/integrations/sofa");
	console.log("Sofa cache cleared");
}

Дополнительно