엣지 케이스 (Edge Cases)
드물게 발생하는 희귀한 문제 상황과 해결 방법을 알아봅니다.
개요
이 문서에서는 다음과 같은 드문 문제를 다룹니다:
- Rate limiting (속도 제한)
- 대용량 파일 처리
- 동시 세션 관리
- 네트워크 중단 복구
Rate Limiting
문제: API 호출 한도 초과
상황: 짧은 시간 안에 너무 많은 API 호출을 하여 rate limit에 도달
증상:
Error: Rate limit exceeded. Please retry after 60 seconds.
해결 방법:
rateLimits:
custom:
requestsPerMinute: 30
retry:
maxAttempts: 5
initialDelayMs: 1000
backoffMultiplier: 2
export default {
name: 'rate-limiter',
async execute(context) {
const limiter = new RateLimiter({
tokensPerInterval: 30,
interval: 'minute'
});
await limiter.removeTokens(1);
const result = await this.callApi(context);
return result;
}
};
대용량 파일 처리
문제: 100MB 이상 파일 업로드
상황: 워크스페이스의 최대 파일 크기 제한 초과
증상:
Error: File size exceeds maximum allowed size (100MB)
해결 방법:
workspace:
maxFileSize: 1073741824 # 1GB
chunkedUpload:
enabled: true
chunkSize: 10485760 # 10MB 청크
export default {
name: 'chunked-processor',
async execute(context) {
const largeFile = 'huge-data.json';
const stream = await this.readFileStream(largeFile);
let chunkCount = 0;
let results = [];
for await (const chunk of stream) {
const result = await this.processChunk(chunk);
results.push(result);
chunkCount++;
if (chunkCount % 10 === 0) {
console.log(`Processed ${chunkCount} chunks`);
}
}
return {
success: true,
totalChunks: chunkCount,
results: results
};
}
};
동시 세션 관리
문제: 여러 사용자가 동시에 같은 세션 사용
상황: 여러 명이 동시에 같은 채널에서 OpenClaw와 대화
증상:
- 응답이 섞임
- 메모리 충돌
- 순서가 꼬임
해결 방법:
sessions:
isolation:
enabled: true
scope: "user"
concurrency:
maxConcurrent: 5
queue:
enabled: true
maxQueueSize: 100
export default {
name: 'session-isolation',
async execute(context) {
const userId = context.message.from;
const session = await this.getSession(userId);
const lock = await session.acquireLock();
try {
const result = await this.processTask(context);
return result;
} finally {
await lock.release();
}
}
};
네트워크 중단 복구
문제: 일시적 네트워크 중단
상황: API 서버와 연결이 일시적으로 끊김
증상:
Error: ECONNRESET: Connection reset by peer
Error: ETIMEDOUT: Operation timed out
해결 방법:
network:
retry:
enabled: true
maxAttempts: 10
initialDelayMs: 1000
keepAlive:
enabled: true
intervalMs: 30000
fallback:
enabled: true
servers:
- primary: "https://api.anthropic.com"
- backup: "https://api.backup.com"
export default {
name: 'resilient-client',
async execute(context) {
let lastError;
for (let attempt = 1; attempt <= 10; attempt++) {
try {
const result = await this.callApi(context);
return result;
} catch (error) {
lastError = error;
if (this.isRetryable(error)) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`Retry ${attempt}/10 after ${delay}ms`);
await this.sleep(delay);
} else {
throw error;
}
}
}
throw lastError;
},
isRetryable(error) {
const retryableErrors = [
'ECONNRESET',
'ETIMEDOUT',
'ECONNREFUSED',
'Rate limit exceeded'
];
return retryableErrors.some(code =>
error.message.includes(code)
);
}
};
메모리 누수
문제: 장시간 실행 후 메모리 부족
상황: Gateway가 며칠 실행 후 메모리 사용량 급증
증상:
Error: JavaScript heap out of memory
해결 방법:
memory:
maxHeapSize: 2048
gc:
enabled: true
interval: 3600
sessionCleanup:
enabled: true
maxSessions: 100
maxAge: 86400
export default {
name: 'memory-manager',
async start() {
setInterval(() => {
this.cleanup();
}, 3600000);
},
cleanup() {
const oldSessions = this.getOldSessions(86400);
oldSessions.forEach(session => session.close());
if (global.gc) {
global.gc();
}
}
};
동시성 경쟁
문제: 여러 작업이 동시에 같은 파일 수정
상황: 서브 에이전트가 동시에 같은 파일에 쓰기
증상:
Error: EBUSY: resource busy or locked
Error: File corrupted due to concurrent writes
해결 방법:
export default {
name: 'file-lock',
async execute(context) {
const file = 'shared-data.json';
const lock = await this.acquireLock(file);
try {
const data = await this.readFile(file);
data.modified = true;
await this.writeFile(file, data);
return { success: true };
} finally {
await lock.release();
}
},
async acquireLock(file, timeout = 10000) {
const start = Date.now();
while (Date.now() - start < timeout) {
try {
await this.createLockFile(file);
return { file, release: () => this.removeLockFile(file) };
} catch (error) {
if (error.code === 'EEXIST') {
await this.sleep(100);
} else {
throw error;
}
}
}
throw new Error('Lock acquisition timeout');
}
};
대규모 메시지 처리
문제: 한 번에 수천 개의 메시지 수신
상황: Slack에서 대량의 메시지가 한꺼번에 도착
증상:
- Gateway 응답 지연
- 메시지 처리 순서 꼬임
- 메모리 과다 사용
해결 방법:
messaging:
batching:
enabled: true
maxBatchSize: 100
flushInterval: 1000
priority:
enabled: true
levels:
- high: "명령어 메시지"
- normal: "일반 메시지"
- low: "로그 메시지"
export default {
name: 'message-queue',
async start() {
this.queues = {
high: [],
normal: [],
low: []
};
this.processBatches();
},
async processBatches() {
while (true) {
const batch = [];
for (const priority of ['high', 'normal', 'low']) {
batch.push(...this.queues[priority].splice(0, 100));
}
if (batch.length > 0) {
await this.processBatch(batch);
}
await this.sleep(1000);
}
}
};
참고: