/** * 기존 message_buffer 데이터를 새 conversation 테이블로 마이그레이션 * * 사용법: * 1. Worker 내부에서 1회성 호출 * 2. 또는 wrangler dev에서 수동 트리거 */ import type { Env } from '../src/types'; export async function migrateExistingConversations(env: Env): Promise<{ migrated_users: number; migrated_messages: number; errors: string[]; }> { const db = env.DB; const result = { migrated_users: 0, migrated_messages: 0, errors: [] as string[], }; // 1. 기존 message_buffer에서 사용자 목록 조회 const { results: users } = await db .prepare(` SELECT DISTINCT u.telegram_id, mb.user_id FROM message_buffer mb JOIN users u ON mb.user_id = u.id `) .all<{ telegram_id: string; user_id: number }>(); if (!users || users.length === 0) { console.log('마이그레이션 대상 없음'); return result; } console.log(`마이그레이션 대상 사용자: ${users.length}명`); // 2. 각 사용자별 마이그레이션 for (const user of users) { try { const tableName = `conv_${user.telegram_id}`; // 테이블 생성 await db.exec(` CREATE TABLE IF NOT EXISTS ${tableName} ( id INTEGER PRIMARY KEY AUTOINCREMENT, role TEXT NOT NULL CHECK(role IN ('user', 'assistant')), content TEXT NOT NULL, tool_calls TEXT, tool_results TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); await db.exec(` CREATE INDEX IF NOT EXISTS idx_${tableName}_created ON ${tableName}(created_at DESC) `); // 메시지 복사 const { results: messages } = await db .prepare(` SELECT role, message as content, created_at FROM message_buffer WHERE user_id = ? ORDER BY created_at ASC `) .bind(user.user_id) .all<{ role: string; content: string; created_at: string }>(); if (messages && messages.length > 0) { for (const msg of messages) { // role 변환: bot -> assistant const role = msg.role === 'bot' ? 'assistant' : 'user'; await db .prepare(`INSERT INTO ${tableName} (role, content, created_at) VALUES (?, ?, ?)`) .bind(role, msg.content, msg.created_at) .run(); } result.migrated_messages += messages.length; } // 메타 테이블에 등록 (이미 존재하면 업데이트) await db .prepare(` INSERT INTO conversation_tables (telegram_id, table_name, message_count, last_message_at) VALUES (?, ?, ?, (SELECT MAX(created_at) FROM ${tableName})) ON CONFLICT(telegram_id) DO UPDATE SET message_count = excluded.message_count, last_message_at = excluded.last_message_at `) .bind(user.telegram_id, tableName, messages?.length || 0) .run(); result.migrated_users++; console.log(`✓ ${user.telegram_id}: ${messages?.length || 0}개 메시지 마이그레이션 완료`); } catch (error) { const errMsg = error instanceof Error ? error.message : String(error); result.errors.push(`${user.telegram_id}: ${errMsg}`); console.error(`✗ ${user.telegram_id}: 마이그레이션 실패 - ${errMsg}`); } } console.log('\n=== 마이그레이션 결과 ==='); console.log(`사용자: ${result.migrated_users}명`); console.log(`메시지: ${result.migrated_messages}개`); console.log(`에러: ${result.errors.length}건`); return result; }