소스 정보
- 저장소
- InugamiDev/ultrathink-oss
- 최근 소스 활동
- 2026년 4월 13일 15:28
- 감지된 SKILL.md 언어
- 영어
- 스타
- 43
- 포크
- 10
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SOC 직업 분류 기준
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill redis명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
| name | redis |
| description | Redis data structures, caching patterns, pub/sub, rate limiting, and session management |
| layer | domain |
| category | database |
| triggers | ["redis","caching","rate limiting","pub/sub","session store","redis cache","distributed lock"] |
| inputs | [{"use_case":"Caching, rate limiting, pub/sub, session management, queues"},{"requirements":"TTL policies, data structures, clustering needs"},{"client":"ioredis | redis (node-redis) | upstash (optional)"}] |
| outputs | [{"redis_client":"Client configuration and connection setup"},{"cache_patterns":"Caching strategies with invalidation"},{"data_structures":"Appropriate Redis data structure recommendations"},{"rate_limiter":"Rate limiting implementation"}] |
| linksTo |
| ["caching","nodejs","microservices","message-queues"] |
| linkedFrom | ["caching","authentication","ecommerce"] |
| preferredNextSkills | ["caching","nodejs"] |
| fallbackSkills | ["caching"] |
| riskLevel | low |
| memoryReadPolicy | selective |
| memoryWritePolicy | none |
| sideEffects | [] |
Implement Redis-backed caching, rate limiting, pub/sub messaging, session management, and distributed locks. This skill covers Redis data structures, caching patterns with proper invalidation, and serverless-compatible clients like Upstash. Redis is not just a cache -- it is a versatile data structure server.
STRING: Simple key-value. Counters, cache entries, session data.
SET key "value" EX 3600
HASH: Object-like fields. User profiles, settings, product details.
HSET user:123 name "Jane" email "jane@example.com"
LIST: Ordered collection. Activity feeds, queues, recent items.
LPUSH feed:user:123 "posted a comment"
SET: Unique collection. Tags, followers, online users.
SADD tags:post:456 "react" "nextjs" "typescript"
SORTED SET: Ranked collection. Leaderboards, rate limiting, priority queues.
ZADD leaderboard 1500 "user:123"
STREAM: Append-only log. Event sourcing, message queues.
XADD events * type "order.created" orderId "789"
USE REDIS:
- Data that changes frequently and is read often (cache)
- Temporary data with TTL (sessions, OTP codes, rate limits)
- Real-time features (pub/sub, presence, typing indicators)
- Counters and aggregations (view counts, rate limits)
- Distributed locks (prevent concurrent operations)
USE DATABASE:
- Source of truth (orders, users, products)
- Complex queries (joins, aggregations, full-text search)
- Data that must survive restarts without rebuild
- Relational data with integrity constraints
// lib/redis.ts (ioredis)
import Redis from 'ioredis';
export const redis = new Redis(process.env.REDIS_URL!, {
maxRetriesPerRequest: 3,
retryStrategy(times) {
const delay = Math.min(times * 50, 2000);
return delay;
},
lazyConnect: true,
});
// Upstash (serverless-compatible)
import { Redis } from '@upstash/redis';
export const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
async function getCachedProduct(id: string): Promise<Product> {
const cacheKey = `product:${id}`;
// Try cache first
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
// Cache miss: fetch from database
const product = await db.product.findUnique({ where: { id } });
if (!product) throw new NotFoundError('Product', id);
// Store in cache with TTL
await redis.set(cacheKey, JSON.stringify(product), 'EX', 3600); // 1 hour
return product;
}
// Invalidate on update
async function updateProduct(id: string, data: Partial<Product>) {
const product = await db.product.({ : { id }, data });
redis.();
product;
}
async function rateLimit(
key: string,
limit: number,
windowSeconds: number,
): Promise<{ allowed: boolean; remaining: number; resetAt: number }> {
const now = Date.now();
const windowStart = now - windowSeconds * 1000;
const redisKey = `rate:${key}`;
// Use sorted set: score = timestamp, member = unique request ID
const pipe = redis.pipeline();
pipe.zremrangebyscore(redisKey, 0, windowStart); // Remove expired
pipe.zadd(redisKey, now, `${now}:${Math.random()}`); // Add current
pipe.zcard(redisKey); // Count in window
pipe.expire(redisKey, windowSeconds); // Set TTL
const results = await pipe.exec();
const count = results![2][1] as number;
return {
allowed: count <= limit,
: .(, limit - count),
: now + windowSeconds * ,
};
}
{ allowed, remaining, resetAt } = (
,
,
,
);
(!allowed) {
(, {
: ,
: {
: ,
: (remaining),
: (.(resetAt / )),
: (.((resetAt - .()) / )),
},
});
}
async function acquireLock(
key: string,
ttlMs: number = 10_000,
): Promise<string | null> {
const lockId = crypto.randomUUID();
const acquired = await redis.set(
`lock:${key}`,
lockId,
'PX', ttlMs,
'NX', // Only set if not exists
);
return acquired ? lockId : null;
}
async function releaseLock(key: string, lockId: string): Promise<boolean> {
// Lua script ensures atomicity: only delete if we own the lock
const script = `
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
`;
const result = await redis.eval(script, 1, `lock:${key}`, lockId);
return result === 1;
}
// Usage
const lockId = await acquireLock(`order:${orderId}`);
(!lockId) ();
{
(orderId);
} {
(, lockId);
}
// Publisher
await redis.publish('notifications', JSON.stringify({
type: 'order.shipped',
userId: 'user_123',
orderId: 'order_456',
}));
// Subscriber (separate connection required)
const subscriber = new Redis(process.env.REDIS_URL!);
subscriber.subscribe('notifications', (err) => {
if (err) console.error('Subscribe error:', err);
});
subscriber.on('message', (channel, message) => {
const event = JSON.parse(message);
console.log(`[${channel}]`, event);
});
product:123, rate:user:456, session:abc not just 123maxmemory and maxmemory-policy (e.g., allkeys-lru)| Pitfall | Impact | Fix |
|---|---|---|
| No TTL on cache keys | Memory grows unbounded | Always set EX or PX on SET |
| Cache stampede | All requests hit DB at once on expiry | Use lock or stale-while-revalidate |
| Hot key problem | Single key overwhelmed | Shard across multiple keys |
| Forgetting to invalidate | Stale data served to users | Delete cache on write, use pub/sub |
| Serverless + persistent connections | Connection exhaustion | Use Upstash REST or connection pooling |
| Storing PII without encryption | Compliance violation | Encrypt sensitive cache values |