- 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>
5.2 KiB
5.2 KiB
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
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:
// 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_MSconstant (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
# 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:
- Code Rollback: Revert to previous commit (KV-based code)
- Database: Drop table if needed
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
- Migration SQL syntax validated
- Schema.sql updated
- All code references updated (env.SESSION_KV → env.DB)
- 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:anddelete_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