Erro ao salvar no supabase

This commit is contained in:
Lucas Santana 2024-12-27 15:56:41 -03:00
parent 34b93ddc3e
commit c50e28df01
4 changed files with 81 additions and 41 deletions

View File

@ -1,5 +1,6 @@
import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts' import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { createLogger } from './logger.ts'
const openai = new OpenAI({ const openai = new OpenAI({
apiKey: Deno.env.get('OPENAI_API_KEY') apiKey: Deno.env.get('OPENAI_API_KEY')
@ -22,10 +23,11 @@ interface ReadingAnalysis {
export async function analyzeReading( export async function analyzeReading(
transcription: string, transcription: string,
storyId: string storyId: string,
logger: Logger
): Promise<ReadingAnalysis> { ): Promise<ReadingAnalysis> {
try { try {
console.log('Analisando leitura para story_id:', storyId) logger.info('analysis_start', 'Iniciando análise', { storyId })
const supabase = createClient( const supabase = createClient(
Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_URL') ?? '',
@ -40,10 +42,14 @@ export async function analyzeReading(
.order('page_number', { ascending: true }) .order('page_number', { ascending: true })
if (storyError) { if (storyError) {
console.error('Erro ao buscar história:', storyError) logger.error('story_fetch', storyError)
throw storyError throw storyError
} }
logger.info('story_loaded', 'História carregada', {
pageCount: storyPages?.length
})
if (!storyPages || storyPages.length === 0) { if (!storyPages || storyPages.length === 0) {
console.error('Dados da história inválidos:', storyPages) console.error('Dados da história inválidos:', storyPages)
throw new Error('Texto da história não encontrado') throw new Error('Texto da história não encontrado')

View File

@ -2,6 +2,7 @@ import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { processAudioWithWhisper } from './whisper.ts' import { processAudioWithWhisper } from './whisper.ts'
import { analyzeReading } from './analyzer.ts' import { analyzeReading } from './analyzer.ts'
import { createLogger } from './logger.ts'
const corsHeaders = { const corsHeaders = {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
@ -37,56 +38,44 @@ serve(async (req) => {
return new Response('ok', { headers: corsHeaders }) return new Response('ok', { headers: corsHeaders })
} }
let data: any = null let logger: any = null
try { try {
// Log dos headers para debug const data = await req.json()
console.log('Headers:', Object.fromEntries(req.headers.entries())) logger = createLogger(data?.record?.id || 'unknown')
// Validação inicial do body logger.info('request_received', 'Iniciando processamento', {
const body = await req.text() headers: Object.fromEntries(req.headers.entries())
console.log('Raw body:', body) })
console.log('Body length:', body.length)
console.log('Body type:', typeof body)
data = JSON.parse(body) // Validação
if (!data?.record?.id || !data?.record?.audio_url) {
// Validação do record logger.error('validation', new Error('Payload inválido'))
if (!data.record || !data.record.id || !data.record.audio_url) { throw new Error('Dados inválidos')
return new Response(
JSON.stringify({
error: 'Payload inválido',
details: 'record, id e audio_url são obrigatórios',
receivedData: data
}),
{
status: 400,
headers: { ...corsHeaders, 'Content-Type': 'application/json' }
}
)
} }
const audioRecord = data.record as AudioRecord
logger.info('record_loaded', 'Registro carregado', audioRecord)
// Processamento
logger.info('processing_start', 'Iniciando processamento do áudio')
const transcription = await processAudioWithWhisper(audioRecord.audio_url, logger)
logger.info('transcription_complete', 'Transcrição concluída', { length: transcription.length })
const analysis = await analyzeReading(transcription, audioRecord.story_id, logger)
logger.info('analysis_complete', 'Análise concluída', { scores: analysis })
const supabase = createClient( const supabase = createClient(
Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
) )
const audioRecord = data.record as AudioRecord
console.log('AudioRecord', audioRecord)
// 1. Atualiza status para processing // 1. Atualiza status para processing
await supabase await supabase
.from('story_recordings') .from('story_recordings')
.update({ status: 'processing' }) .update({ status: 'processing' })
.eq('id', audioRecord.id) .eq('id', audioRecord.id)
// 2. Processa o áudio com Whisper
const transcription = await processAudioWithWhisper(audioRecord.audio_url)
// 3. Analisa a leitura
const analysis = await analyzeReading(transcription, audioRecord.story_id)
console.log('Análise concluída', analysis)
// 4. Atualiza o registro com os resultados // 4. Atualiza o registro com os resultados
const updateData = { const updateData = {
status: 'completed', status: 'completed',
@ -102,11 +91,11 @@ serve(async (req) => {
self_corrections: analysis.self_corrections || 0, self_corrections: analysis.self_corrections || 0,
strengths: Array.isArray(analysis.strengths) ? analysis.strengths : [], strengths: Array.isArray(analysis.strengths) ? analysis.strengths : [],
improvements: Array.isArray(analysis.improvements) ? analysis.improvements : [], improvements: Array.isArray(analysis.improvements) ? analysis.improvements : [],
suggestions: analysis.suggestions || '', suggestions: analysis.suggestions || ''
analysis: JSON.stringify(analysis.raw_data)
} }
console.log('Dados para atualização:', updateData) console.log('Dados para atualização:', updateData)
console.log('AudioRecord', audioRecord)
const { error: updateError } = await supabase const { error: updateError } = await supabase
.from('story_recordings') .from('story_recordings')

View File

@ -0,0 +1,37 @@
export interface LogContext {
requestId: string
recordId: string
step: string
timestamp: string
}
export function createLogger(recordId: string) {
const requestId = crypto.randomUUID()
return {
info: (step: string, message: string, data?: any) => {
console.log(JSON.stringify({
level: 'info',
requestId,
recordId,
step,
message,
data,
timestamp: new Date().toISOString()
}))
},
error: (step: string, error: Error, data?: any) => {
console.error(JSON.stringify({
level: 'error',
requestId,
recordId,
step,
message: error.message,
stack: error.stack,
data,
timestamp: new Date().toISOString()
}))
}
}
}

View File

@ -1,17 +1,25 @@
import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts' import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts'
import { createLogger } from './logger.ts'
const openai = new OpenAI({ const openai = new OpenAI({
apiKey: Deno.env.get('OPENAI_API_KEY') apiKey: Deno.env.get('OPENAI_API_KEY')
}) })
export async function processAudioWithWhisper(audioUrl: string): Promise<string> { export async function processAudioWithWhisper(audioUrl: string, logger: Logger): Promise<string> {
try { try {
// Download do áudio logger.info('whisper_start', 'Iniciando download do áudio', { url: audioUrl })
const audioResponse = await fetch(audioUrl) const audioResponse = await fetch(audioUrl)
if (!audioResponse.ok) { if (!audioResponse.ok) {
logger.error('whisper_download', new Error(`HTTP ${audioResponse.status}`))
throw new Error('Falha ao baixar áudio') throw new Error('Falha ao baixar áudio')
} }
const audioBlob = await audioResponse.blob() const audioBlob = await audioResponse.blob()
logger.info('whisper_download_complete', 'Download concluído', {
size: audioBlob.size,
type: audioBlob.type
})
// Debug do áudio // Debug do áudio
console.log('Audio blob:', { console.log('Audio blob:', {