feat: fallback to normal stream if cannot resume stream (#980)

This commit is contained in:
Jeremy 2025-05-03 00:32:46 -07:00 committed by GitHub
parent e529d99974
commit 7402af0a64
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 9 deletions

View file

@ -10,5 +10,10 @@ XAI_API_KEY=****
# Instructions to create a Vercel Blob Store here: https://vercel.com/docs/storage/vercel-blob # Instructions to create a Vercel Blob Store here: https://vercel.com/docs/storage/vercel-blob
BLOB_READ_WRITE_TOKEN=**** 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=**** POSTGRES_URL=****
# Instructions to create a Redis store here:
# https://vercel.com/docs/redis
REDIS_URL=****

View file

@ -28,15 +28,36 @@ import { myProvider } from '@/lib/ai/providers';
import { entitlementsByUserType } from '@/lib/ai/entitlements'; import { entitlementsByUserType } from '@/lib/ai/entitlements';
import { postRequestBodySchema, type PostRequestBody } from './schema'; import { postRequestBodySchema, type PostRequestBody } from './schema';
import { geolocation } from '@vercel/functions'; import { geolocation } from '@vercel/functions';
import { createResumableStreamContext } from 'resumable-stream'; import {
createResumableStreamContext,
type ResumableStreamContext,
} from 'resumable-stream';
import { after } from 'next/server'; import { after } from 'next/server';
import type { Chat } from '@/lib/db/schema'; import type { Chat } from '@/lib/db/schema';
export const maxDuration = 60; export const maxDuration = 60;
const streamContext = createResumableStreamContext({ let globalStreamContext: ResumableStreamContext | null = null;
waitUntil: after,
}); 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) { export async function POST(request: Request) {
let requestBody: PostRequestBody; let requestBody: PostRequestBody;
@ -206,9 +227,15 @@ export async function POST(request: Request) {
}, },
}); });
return new Response( const streamContext = getStreamContext();
await streamContext.resumableStream(streamId, () => stream),
); if (streamContext) {
return new Response(
await streamContext.resumableStream(streamId, () => stream),
);
} else {
return new Response(stream);
}
} catch (_) { } catch (_) {
return new Response('An error occurred while processing your request!', { return new Response('An error occurred while processing your request!', {
status: 500, status: 500,
@ -217,6 +244,12 @@ export async function POST(request: Request) {
} }
export async function GET(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 { searchParams } = new URL(request.url);
const chatId = searchParams.get('chatId'); const chatId = searchParams.get('chatId');

View file

@ -1,6 +1,6 @@
{ {
"name": "ai-chatbot", "name": "ai-chatbot",
"version": "3.0.18", "version": "3.0.19",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev --turbo", "dev": "next dev --turbo",