From 7402af0a6496169d968c39ee54540427ab5b4b1f Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sat, 3 May 2025 00:32:46 -0700 Subject: [PATCH] feat: fallback to normal stream if cannot resume stream (#980) --- .env.example | 7 +++++- app/(chat)/api/chat/route.ts | 47 ++++++++++++++++++++++++++++++------ package.json | 2 +- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 5d1199b..6a40fdd 100644 --- a/.env.example +++ b/.env.example @@ -10,5 +10,10 @@ XAI_API_KEY=**** # Instructions to create a Vercel Blob Store here: https://vercel.com/docs/storage/vercel-blob BLOB_READ_WRITE_TOKEN=**** -# Instructions to create a database here: https://vercel.com/docs/storage/vercel-postgres/quickstart +# Instructions to create a PostgreSQL database here: https://vercel.com/docs/storage/vercel-postgres/quickstart POSTGRES_URL=**** + + +# Instructions to create a Redis store here: +# https://vercel.com/docs/redis +REDIS_URL=**** diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index a6f6a48..4fe241b 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -28,15 +28,36 @@ import { myProvider } from '@/lib/ai/providers'; import { entitlementsByUserType } from '@/lib/ai/entitlements'; import { postRequestBodySchema, type PostRequestBody } from './schema'; import { geolocation } from '@vercel/functions'; -import { createResumableStreamContext } from 'resumable-stream'; +import { + createResumableStreamContext, + type ResumableStreamContext, +} from 'resumable-stream'; import { after } from 'next/server'; import type { Chat } from '@/lib/db/schema'; export const maxDuration = 60; -const streamContext = createResumableStreamContext({ - waitUntil: after, -}); +let globalStreamContext: ResumableStreamContext | null = null; + +function getStreamContext() { + if (!globalStreamContext) { + try { + globalStreamContext = createResumableStreamContext({ + waitUntil: after, + }); + } catch (error: any) { + if (error.message.includes('REDIS_URL')) { + console.log( + ' > Resumable streams are disabled due to missing REDIS_URL', + ); + } else { + console.error(error); + } + } + } + + return globalStreamContext; +} export async function POST(request: Request) { let requestBody: PostRequestBody; @@ -206,9 +227,15 @@ export async function POST(request: Request) { }, }); - return new Response( - await streamContext.resumableStream(streamId, () => stream), - ); + const streamContext = getStreamContext(); + + if (streamContext) { + return new Response( + await streamContext.resumableStream(streamId, () => stream), + ); + } else { + return new Response(stream); + } } catch (_) { return new Response('An error occurred while processing your request!', { status: 500, @@ -217,6 +244,12 @@ export async function POST(request: Request) { } export async function GET(request: Request) { + const streamContext = getStreamContext(); + + if (!streamContext) { + return new Response(null, { status: 204 }); + } + const { searchParams } = new URL(request.url); const chatId = searchParams.get('chatId'); diff --git a/package.json b/package.json index d1a961b..5bd9757 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ai-chatbot", - "version": "3.0.18", + "version": "3.0.19", "private": true, "scripts": { "dev": "next dev --turbo",