feat: add optimistic locking and improve type safety

- Implement optimistic locking for deposit balance updates
  - Prevent race conditions in concurrent deposit requests
  - Add automatic retry with exponential backoff (max 3 attempts)
  - Add version column to user_deposits table

- Improve type safety across codebase
  - Add explicit types for Namecheap API responses
  - Add typed function arguments (ManageDepositArgs, etc.)
  - Remove `any` types from deposit-agent and tool files

- Add reconciliation job for balance integrity verification
  - Compare user_deposits.balance vs SUM(confirmed transactions)
  - Alert admin on discrepancy detection

- Set up test environment with Vitest + Miniflare
  - Add 50+ test cases for deposit system
  - Add helper functions for test data creation

- Update documentation
  - Add migration guide for version columns
  - Document optimistic locking patterns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-19 23:23:09 +09:00
parent 8d0fe30722
commit f5df0c0ffe
21 changed files with 13448 additions and 169 deletions

283
TESTING_INSTALLATION.md Normal file
View File

@@ -0,0 +1,283 @@
# 테스트 인프라 설치 가이드
## 개요
이 문서는 `deposit-agent.ts`에 대한 포괄적인 단위 테스트를 위한 Vitest + Miniflare 환경 설정 가이드입니다.
## 생성된 파일
```
telegram-bot-workers/
├── vitest.config.ts # Vitest 설정 (Miniflare 환경)
├── tests/
│ ├── setup.ts # D1 Database 초기화 및 헬퍼 함수
│ ├── deposit-agent.test.ts # 예치금 시스템 테스트 (50+ cases)
│ └── README.md # 테스트 가이드
├── package.json # 업데이트됨 (vitest, miniflare 추가)
├── README.md # 업데이트됨 (테스트 섹션 추가)
├── CLAUDE.md # 업데이트됨 (테스트 명령어 추가)
└── TESTING_INSTALLATION.md # 이 파일
```
## 설치 단계
### 1. 의존성 설치
```bash
npm install
```
새로 추가된 패키지:
- `vitest@^1.2.0` - 테스트 러너
- `miniflare@^3.20231030.0` - Cloudflare Workers 시뮬레이터
- `@cloudflare/vitest-pool-workers@^0.1.0` - Vitest Workers 통합
- `@vitest/coverage-v8@^1.2.0` - 커버리지 리포트
### 2. 테스트 실행
```bash
# 모든 테스트 실행
npm test
# Watch 모드 (개발 중)
npm run test:watch
# 커버리지 리포트
npm run test:coverage
```
### 3. 예상 출력
```
✓ tests/deposit-agent.test.ts (50+)
✓ executeDepositFunction
✓ get_balance (2)
✓ get_account_info (1)
✓ request_deposit - Negative Amount Validation (4)
✓ request_deposit - 7-Character Prefix Matching (4)
✓ request_deposit - Pending Transaction (2)
✓ request_deposit - Batch Failure Handling (1)
✓ get_transactions (5)
✓ cancel_transaction (5)
✓ Admin Functions - Permission Checks (3)
✓ Admin Functions - get_pending_list (2)
✓ Admin Functions - confirm_deposit (3)
✓ Admin Functions - reject_deposit (2)
✓ Concurrency Safety (2)
✓ Edge Cases (4)
✓ Unknown Function (1)
Test Files 1 passed (1)
Tests 50+ passed (50+)
Duration < 10s
```
## 테스트 범위
### 금융 작업 안전성
**음수 금액 거부**
- 음수 입금 시도 → 에러 반환
- 0원 입금 시도 → 에러 반환
- 누락된 금액/입금자명 → 에러 반환
**동시성 처리 안전성**
- 동일 사용자의 동시 입금 요청
- Race condition 시뮬레이션
- 3개 동시 요청 처리 검증
**부분 배치 실패 처리**
- `db.batch()` 일부 실패 시뮬레이션
- `allSuccessful` 검증 로직
- 에러 throw 및 로깅 확인
**입금자명 7글자 매칭**
- "홍길동아버지님" (8글자) → "홍길동아버지" (7글자) 자동 매칭
- `depositor_name_prefix` 컬럼 활용
- 금액/이름 불일치 시나리오
**관리자 권한 검증**
- 비관리자의 `get_pending_list` 차단
- 비관리자의 `confirm_deposit` 차단
- 비관리자의 `reject_deposit` 차단
**거래 상태 검증**
- confirmed 거래 취소 차단
- pending 거래만 확인/거절 허용
- 다른 사용자 거래 취소 차단
**Edge Cases**
- 999,999,999원 (매우 큰 금액)
- "홍길동(주)" (특수문자)
- "김" (1글자 이름)
- "1234567" (정확히 7글자)
## Mock 전략
### D1 Database
Miniflare가 자동으로 in-memory SQLite 제공:
- `schema.sql` 자동 로드 (`beforeAll`)
- 각 테스트 후 데이터 정리 (`afterEach`)
- 실제 SQL 쿼리 실행 가능
### 환경 변수
`vitest.config.ts`에서 바인딩:
```typescript
bindings: {
BOT_TOKEN: 'test-bot-token',
WEBHOOK_SECRET: 'test-webhook-secret',
OPENAI_API_KEY: 'test-openai-key',
DEPOSIT_ADMIN_ID: '999999999',
}
```
### 헬퍼 함수
`tests/setup.ts`:
```typescript
createTestUser(telegramId, username) // 사용자 생성
createBankNotification(depositorName, amount) // 은행 알림 생성
createDepositTransaction(userId, amount, status) // 거래 생성
getTestDB() // DB 바인딩
```
## 디버깅
### 실패한 테스트 확인
```bash
npm test -- --reporter=verbose
```
### 특정 테스트만 실행
```bash
# 파일명 필터링
npm test deposit-agent
# 테스트 설명 필터링
npm test -- -t "should reject negative amounts"
```
### 로그 출력
```typescript
it('debugging test', async () => {
const result = await executeDepositFunction(...);
console.log('Result:', result); // 출력됨
expect(result).toBeDefined();
});
```
## 커버리지 리포트
```bash
npm run test:coverage
```
출력:
- `coverage/` 디렉토리에 HTML 리포트 생성
- 브라우저로 `coverage/index.html` 열기
## 문제 해결
### "Cannot find module" 에러
```bash
rm -rf node_modules package-lock.json
npm install
```
### Miniflare 버전 충돌
`package.json` 확인:
```json
{
"miniflare": "^3.20231030.0",
"@cloudflare/vitest-pool-workers": "^0.1.0"
}
```
### D1 스키마 초기화 실패
`tests/setup.ts`에서 경로 확인:
```typescript
const schemaPath = join(__dirname, '../schema.sql');
```
### 테스트 타임아웃
`vitest.config.ts` 수정:
```typescript
test: {
testTimeout: 10000, // 기본 5초 → 10초
}
```
## 다음 단계
### 추가 테스트 작성
1. **openai-service.ts**
- Function Calling 도구 테스트
- AI 응답 생성 테스트
2. **summary-service.ts**
- 프로필 업데이트 로직
- 3개 요약 통합 테스트
3. **Integration Tests**
- Webhook → AI → DB 전체 플로우
- Email Handler 파싱 테스트
### CI/CD 통합
**GitHub Actions** (`.github/workflows/test.yml`):
```yaml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm install
- run: npm test
- run: npm run test:coverage
- uses: codecov/codecov-action@v3
```
## 참고 자료
- [Vitest 공식 문서](https://vitest.dev/)
- [Miniflare 공식 문서](https://miniflare.dev/)
- [Cloudflare Workers Testing Guide](https://developers.cloudflare.com/workers/testing/)
- [Project README](./README.md) - 프로젝트 개요 및 기능
- [Developer Guide](./CLAUDE.md) - 개발 환경 설정
- [Tests README](./tests/README.md) - 테스트 상세 가이드
## 완료 체크리스트
- [x] `vitest.config.ts` 생성
- [x] `tests/setup.ts` 생성 (D1 초기화)
- [x] `tests/deposit-agent.test.ts` 생성 (50+ test cases)
- [x] `package.json` 업데이트 (의존성 추가)
- [x] `README.md` 업데이트 (테스트 섹션)
- [x] `CLAUDE.md` 업데이트 (명령어 추가)
- [x] `tests/README.md` 생성 (가이드)
- [x] `.gitignore` 확인 (coverage/ 제외)
## 성공 기준
✅ 모든 테스트 통과 (`npm test`)
✅ 커버리지 리포트 생성 가능 (`npm run test:coverage`)
✅ 플래키 테스트 없음 (결정론적 결과)
✅ 테스트 실행 시간 <10초
✅ 명확한 테스트 설명 및 에러 메시지