- 003_add_server_tables.sql: server_orders, server_instances tables - 003_server_sessions.sql: KV-based session tracking - 004_add_terminated_at.sql: track instance termination time Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
162 lines
5.2 KiB
Markdown
162 lines
5.2 KiB
Markdown
# Migration 003: Server Sessions from KV to D1
|
|
|
|
**Date**: 2026-01-28
|
|
**Type**: Session Storage Migration
|
|
**Status**: Ready to Deploy
|
|
|
|
## Overview
|
|
|
|
Migrated server consultation session management from KV Namespace to D1 Database for better consistency, reliability, and integrated data management.
|
|
|
|
## Changes Summary
|
|
|
|
### 1. Database Schema (`schema.sql` + `migrations/003_server_sessions_d1.sql`)
|
|
|
|
**New Table**: `server_sessions`
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS server_sessions (
|
|
user_id TEXT PRIMARY KEY,
|
|
status TEXT NOT NULL CHECK(status IN ('gathering', 'recommending', 'selecting', 'ordering', 'completed')),
|
|
collected_info TEXT,
|
|
last_recommendation TEXT,
|
|
messages TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
expires_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_server_sessions_expires ON server_sessions(expires_at);
|
|
```
|
|
|
|
### 2. Code Changes
|
|
|
|
**Updated Files**:
|
|
- `/src/server-agent.ts` - Session management functions (getServerSession, saveServerSession, deleteServerSession)
|
|
- `/src/openai-service.ts` - Session check in generateOpenAIResponse()
|
|
- `/src/tools/server-tool.ts` - start_consultation, continue_consultation, cancel_consultation actions
|
|
- `/src/routes/handlers/callback-handler.ts` - server_order and server_cancel callbacks
|
|
|
|
**Function Signature Changes**:
|
|
```typescript
|
|
// Before (KV)
|
|
export async function getServerSession(kv: KVNamespace, userId: string): Promise<ServerSession | null>
|
|
export async function saveServerSession(kv: KVNamespace, userId: string, session: ServerSession): Promise<void>
|
|
export async function deleteServerSession(kv: KVNamespace, userId: string): Promise<void>
|
|
|
|
// After (D1)
|
|
export async function getServerSession(db: D1Database, userId: string): Promise<ServerSession | null>
|
|
export async function saveServerSession(db: D1Database, userId: string, session: ServerSession): Promise<void>
|
|
export async function deleteServerSession(db: D1Database, userId: string): Promise<void>
|
|
|
|
// New
|
|
export async function cleanupExpiredSessions(db: D1Database): Promise<number>
|
|
```
|
|
|
|
**Removed**:
|
|
- All `[SESSION DEBUG]` logging (unnecessary with D1's strong consistency)
|
|
- KV constants: `SESSION_TTL`, `SESSION_KEY_PREFIX`
|
|
|
|
**Added**:
|
|
- `SESSION_TTL_MS` constant (3600 * 1000 = 1 hour)
|
|
- `cleanupExpiredSessions()` function for cron cleanup
|
|
- Automatic expiry checking in queries (`WHERE expires_at > ?`)
|
|
|
|
### 3. Key Implementation Details
|
|
|
|
**Session Storage**:
|
|
- JSON serialization for complex fields (collected_info, last_recommendation, messages)
|
|
- Automatic TTL management with expires_at column
|
|
- Strong consistency (no eventual consistency issues)
|
|
|
|
**Error Handling**:
|
|
- Graceful JSON parsing with try-catch
|
|
- Null checks for expired/missing sessions
|
|
- Proper logging without debug noise
|
|
|
|
**Performance**:
|
|
- Primary key on user_id for fast lookups
|
|
- Index on expires_at for efficient cleanup
|
|
- Single query for session retrieval
|
|
|
|
### 4. Migration Path
|
|
|
|
**Automatic Migration**:
|
|
- Old KV sessions will expire naturally (1 hour TTL)
|
|
- New sessions are created in D1 automatically
|
|
- No manual data migration needed
|
|
|
|
**Zero Downtime**:
|
|
- D1 table creation is idempotent (IF NOT EXISTS)
|
|
- Code handles missing sessions gracefully
|
|
- Users can restart consultation if session expires
|
|
|
|
### 5. Benefits
|
|
|
|
**Before (KV Namespace)**:
|
|
- Eventual consistency (delayed reads)
|
|
- Complex debugging (async replication)
|
|
- Separate data store (fragmented)
|
|
- Manual cleanup needed
|
|
|
|
**After (D1 Database)**:
|
|
- Strong consistency (immediate reads)
|
|
- Simple debugging (SQL queries)
|
|
- Integrated storage (single database)
|
|
- Automatic cleanup (expires_at + cron)
|
|
|
|
### 6. Deployment Steps
|
|
|
|
```bash
|
|
# 1. Apply migration (creates table)
|
|
wrangler d1 execute telegram-conversations --file=migrations/003_server_sessions_d1.sql
|
|
|
|
# 2. Verify table creation
|
|
wrangler d1 execute telegram-conversations --command "SELECT name FROM sqlite_master WHERE type='table' AND name='server_sessions'"
|
|
|
|
# 3. Deploy code changes
|
|
npm run deploy
|
|
|
|
# 4. Test server consultation flow
|
|
# Send message: "서버 추천"
|
|
# Verify session is created in D1
|
|
wrangler d1 execute telegram-conversations --command "SELECT * FROM server_sessions LIMIT 5"
|
|
```
|
|
|
|
### 7. Rollback Plan
|
|
|
|
If issues occur:
|
|
|
|
1. **Code Rollback**: Revert to previous commit (KV-based code)
|
|
2. **Database**: Drop table if needed
|
|
```sql
|
|
DROP TABLE IF EXISTS server_sessions;
|
|
DROP INDEX IF EXISTS idx_server_sessions_expires;
|
|
```
|
|
|
|
**Note**: Old KV sessions are unaffected (will expire naturally)
|
|
|
|
### 8. Testing Checklist
|
|
|
|
- [x] Migration SQL syntax validated
|
|
- [x] Schema.sql updated
|
|
- [x] All code references updated (env.SESSION_KV → env.DB)
|
|
- [x] Logging cleaned up (no debug noise)
|
|
- [ ] Local testing (`npm run dev`)
|
|
- [ ] Production deployment
|
|
- [ ] Session creation test
|
|
- [ ] Session retrieval test
|
|
- [ ] Session expiry test
|
|
- [ ] Concurrent session handling
|
|
|
|
### 9. Notes
|
|
|
|
**Important**:
|
|
- `server_order_confirm:` and `delete_confirm:` sessions remain in KV (not migrated, separate feature)
|
|
- Troubleshoot agent still uses KV (separate migration needed if required)
|
|
- D1 binding (`env.DB`) already exists in project
|
|
|
|
**Future Improvements**:
|
|
- Consider migrating troubleshoot sessions to D1
|
|
- Add session analytics (query D1 for session stats)
|
|
- Implement session history/audit log
|