Skip to content

Commit f7518c2

Browse files
authored
chore: background tasks updates (supabase#30454)
* chore: bacground task docs and example. * chore: add video.
1 parent 91523a7 commit f7518c2

File tree

2 files changed

+82
-5
lines changed

2 files changed

+82
-5
lines changed

apps/docs/content/guides/functions/background-tasks.mdx

+6-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ id: 'function-background-tasks'
33
title: 'Background Tasks'
44
description: 'How to run background tasks in an Edge Function outside of the request handler'
55
subtitle: 'How to run background tasks in an Edge Function outside of the request handler'
6+
tocVideo: 'rSKBTJxG9VA'
67
---
78

89
Edge Function instances can process background tasks outside of the request handler. Background tasks are useful for asynchronous operations like uploading a file to Storage, updating a database, or sending events to a logging service. You can respond to the request immediately and leave the task running in the background.
@@ -12,18 +13,18 @@ A background task can run until the Edge Function instance hits its [wall-clock
1213
Here's an example of defining a background task using a custom event.
1314

1415
```ts
15-
// define a custom event
16+
// Define a custom event type for the background task.
1617
class MyBackgroundTaskEvent extends Event {
17-
readonly taskPromise: Promise<string>
18+
readonly taskPromise: Promise<Response>
1819

19-
constructor(taskPromise) {
20+
constructor(taskPromise: Promise<Response>) {
2021
super('myBackgroundTask')
2122
this.taskPromise = taskPromise
2223
}
2324
}
2425

25-
globalThis.addEventListener('myBackgroundTask', async (event: MyBackgroundTaskEvent) => {
26-
const res = await event.taskPromise
26+
globalThis.addEventListener('myBackgroundTask', async (event) => {
27+
const res = await (event as MyBackgroundTaskEvent).taskPromise
2728
console.log(await res.json())
2829
})
2930

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { createClient } from 'jsr:@supabase/[email protected]'
2+
import OpenAI from 'https://deno.land/x/[email protected]/mod.ts'
3+
4+
const client = new OpenAI({ apiKey: Deno.env.get('OPENAI_API_KEY')! })
5+
6+
const supabase = createClient(
7+
Deno.env.get('SUPABASE_URL')!,
8+
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
9+
)
10+
11+
type StorageFileApi = ReturnType<typeof supabase.storage.from>
12+
type StorageUploadPromise = ReturnType<StorageFileApi['upload']>
13+
14+
class MyBackgroundTaskEvent extends Event {
15+
readonly taskPromise: StorageUploadPromise
16+
17+
constructor(taskPromise: StorageUploadPromise) {
18+
super('myBackgroundTask')
19+
this.taskPromise = taskPromise
20+
}
21+
}
22+
23+
globalThis.addEventListener('myBackgroundTask', async (event) => {
24+
const { data, error } = await (event as MyBackgroundTaskEvent).taskPromise
25+
console.log({ data, error })
26+
})
27+
28+
Deno.serve(async (req) => {
29+
const url = new URL(req.url)
30+
const params = new URLSearchParams(url.search)
31+
const text = params.get('text')
32+
33+
if (!text) {
34+
return new Response(JSON.stringify({ error: 'Text parameter is required' }), {
35+
status: 400,
36+
headers: { 'Content-Type': 'application/json' },
37+
})
38+
}
39+
40+
try {
41+
const response = await client.audio.speech.create({
42+
model: 'tts-1',
43+
voice: 'nova',
44+
input: text,
45+
})
46+
47+
const stream = response.body
48+
if (!stream) {
49+
throw new Error('No stream')
50+
}
51+
52+
// Branch stream to Supabase Storage
53+
const [browserStream, storageStream] = stream.tee()
54+
55+
// Upload to Supabase Storage
56+
const storageUploadPromise = supabase.storage
57+
.from('videos')
58+
.upload(`audio-stream_${Date.now()}.mp3`, storageStream, {
59+
contentType: 'audio/mp3',
60+
})
61+
const event = new MyBackgroundTaskEvent(storageUploadPromise)
62+
globalThis.dispatchEvent(event)
63+
64+
return new Response(browserStream, {
65+
headers: {
66+
'Content-Type': 'audio/mp3',
67+
},
68+
})
69+
} catch (error) {
70+
console.log('error', { error })
71+
return new Response(JSON.stringify({ error: error.message }), {
72+
status: 500,
73+
headers: { 'Content-Type': 'application/json' },
74+
})
75+
}
76+
})

0 commit comments

Comments
 (0)