diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 96ad2af0b610c..3f03268edb5ba 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -1272,6 +1272,10 @@ export const functions: NavMenuConstant = { name: 'Background Tasks', url: '/guides/functions/background-tasks', }, + { + name: 'Ephemeral Storage', + url: '/guides/functions/ephemeral-storage', + }, { name: 'Running AI Models', url: '/guides/functions/ai-models', diff --git a/apps/docs/content/guides/functions/background-tasks.mdx b/apps/docs/content/guides/functions/background-tasks.mdx index fbc1f2aebf827..6947f1a57608e 100644 --- a/apps/docs/content/guides/functions/background-tasks.mdx +++ b/apps/docs/content/guides/functions/background-tasks.mdx @@ -3,39 +3,59 @@ id: 'function-background-tasks' title: 'Background Tasks' description: 'How to run background tasks in an Edge Function outside of the request handler' subtitle: 'How to run background tasks in an Edge Function outside of the request handler' -tocVideo: 'rSKBTJxG9VA' --- 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. -### How long a background task can run +### How it works -A background task can run until the Edge Function instance hits its wall-clock limit or reaches CPU/Memory limit. Check [limits](/docs/guides/functions/limits) for current caps. +You can use `EdgeRuntime.waitUntil(promise)` to explicitly mark background tasks. The Function instance continues to run until the promise provided to `waitUntil` completes. + +The maximum duration is capped based on the wall-clock, CPU, and memory limits. The Function will shutdown when it reaches one of these [limits](/docs/guides/functions/limits). + +You can listen to the `beforeunload` event handler to be notified when Function invocation is about to be shut down. ### Example -Here's an example of defining a background task using a custom event. +Here's an example of using `EdgeRuntime.waitUntil` to run a background task and using `beforeunload` event to be notified when the instance is about to be shut down. ```ts -// Define a custom event type for the background task. -class MyBackgroundTaskEvent extends Event { - readonly taskPromise: Promise - - constructor(taskPromise: Promise) { - super('myBackgroundTask') - this.taskPromise = taskPromise - } +async function longRunningTask() { + // do work here } -globalThis.addEventListener('myBackgroundTask', async (event) => { - const res = await (event as MyBackgroundTaskEvent).taskPromise - console.log(await res.json()) +// Mark the longRunningTask's returned promise as a background task. +// note: we are not using await because we don't want it to block. +EdgeRuntime.waitUntil(longRunningTask()) + +// Use beforeunload event handler to be notified when function is about to shutdown +addEventListener('beforeunload', (ev) => { + console.log('Function will be shutdown due to', ev.detail?.reason) + + // save state or log the current progress +}) + +// Invoke the function using a HTTP request. +// This will start the background task +Deno.serve(async (req) => { + return new Response('ok') }) +``` + +### Starting a background task in the request handler + +You can call `EdgeRuntime.waitUntil` in the request handler too. This will not block the request. + +```ts +async function fetchAndLog(url: string) { + const response = await fetch('https://httpbin.org/json') + console.log(response) +} Deno.serve(async (req) => { - const fetchPromise = fetch('https://httpbin.org/json') - const event = new MyBackgroundTaskEvent(fetchPromise) - globalThis.dispatchEvent(event) + // this will not block the request, + // instead it will run in the background + EdgeRuntime.waitUntil(fetchAndLog('https://httpbin.org/json')) return new Response('ok') }) diff --git a/apps/docs/content/guides/functions/ephemeral-storage.mdx b/apps/docs/content/guides/functions/ephemeral-storage.mdx new file mode 100644 index 0000000000000..55bc58780ece9 --- /dev/null +++ b/apps/docs/content/guides/functions/ephemeral-storage.mdx @@ -0,0 +1,54 @@ +--- +id: 'function-ephemeral-storage' +title: 'Ephemeral Storage' +description: 'Read and write from temporary directory' +subtitle: 'Read and write from temporary directory' +--- + +Edge Functions provides ephemeral file storage. You can read and write files to the `/tmp` directory. + +Ephemeral storage will reset on each function invocation. This means the files you write during an invocation can only be read within the same invocation. + +### Use cases + +Here are some use cases where ephemeral storage can be useful: + +- Unzip an archive of CSVs and then add them as records to the DB +- Custom image manipulation workflows (using [MagickWasm](https://supabase.com/docs/guides/functions/examples/image-manipulation)) + +You can use [Background Tasks](https://supabase.com/docs/guides/functions/background-tasks) to handle slow file processing outside of a request. + +### How to use + +You can use [Deno File System APIs](https://docs.deno.com/api/deno/file-system) or the [`node:fs` module](https://docs.deno.com/api/node/fs/) to access the `/tmp` path. + +### Example + +Here is an example of how to write a user-uploaded zip file into temporary storage for further processing. + +```js +Deno.serve(async (req) => { + if (req.headers.get('content-type') !== 'application/zip') { + return new Response('file must be a zip file', { + status: 400, + }) + } + + const uploadId = crypto.randomUUID() + await Deno.writeFile('/tmp/' + uploadId, req.body) + + // do something with the written zip file + + return new Response('ok') +}) +``` + +### Unavailable APIs + +Currently, the synchronous APIs (eg: `Deno.writeFileSync` or `Deno.mkdirSync`) for creating or writing files are not supported. + +You can use sync variations of read APIs (eg: `Deno.readFileSync`). + +### Limits + +In the hosted platform, a free project can write up to 256MB of data to ephemeral storage. A paid project can write up to 512MB. diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx index 8ef51af2e0cef..816091fd880c8 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx @@ -56,7 +56,7 @@ export const CronjobsTab = () => { ) - const filteredCronJobs = (cronJobs ?? []).filter((cj) => cj.jobname.includes(searchQuery)) + const filteredCronJobs = (cronJobs ?? []).filter((cj) => cj?.jobname?.includes(searchQuery || '')) return ( <> diff --git a/apps/www/_blog/2024-12-01-orioledb-launch.mdx b/apps/www/_blog/2024-12-01-orioledb-launch.mdx index 63df6484446c0..54d0b26f736c0 100644 --- a/apps/www/_blog/2024-12-01-orioledb-launch.mdx +++ b/apps/www/_blog/2024-12-01-orioledb-launch.mdx @@ -2,7 +2,7 @@ title: 'OrioleDB Public Alpha' description: 'Launching OrioleDB Public Alpha' author: pavel -image: 2024-12-01-orioledb-release/thumb.png +image: 2024-12-01-orioledb-release/og.png thumb: 2024-12-01-orioledb-release/thumb.png categories: - engineering diff --git a/apps/www/components/LaunchWeek/13/Releases/data/lw13_build_stage.tsx b/apps/www/components/LaunchWeek/13/Releases/data/lw13_build_stage.tsx index 442ce1ee2c731..55b9b26b3a527 100644 --- a/apps/www/components/LaunchWeek/13/Releases/data/lw13_build_stage.tsx +++ b/apps/www/components/LaunchWeek/13/Releases/data/lw13_build_stage.tsx @@ -24,12 +24,39 @@ export interface AdventLink { export const days: AdventDay[] = [ { - title: '', - description: '', - id: '', - is_shipped: false, - links: [], - icon: null, + title: 'OrioleDB Public Alpha', + description: 'Postgres storage extension with better performance over default Heap storage', + id: 'orioledb', + is_shipped: true, + links: [ + { url: 'https://supabase.com/blog/orioledb-launch', label: 'Blog post', target: '_blank' }, + ], + icon: ( + + + + + + + ), }, { title: '', diff --git a/apps/www/public/images/blog/2024-12-01-orioledb-release/og.png b/apps/www/public/images/blog/2024-12-01-orioledb-release/og.png new file mode 100644 index 0000000000000..1aac642d1ac90 Binary files /dev/null and b/apps/www/public/images/blog/2024-12-01-orioledb-release/og.png differ diff --git a/apps/www/public/images/blog/2024-12-01-orioledb-release/thumb.png b/apps/www/public/images/blog/2024-12-01-orioledb-release/thumb.png index 8693d18b5017c..dc435e92bca4a 100644 Binary files a/apps/www/public/images/blog/2024-12-01-orioledb-release/thumb.png and b/apps/www/public/images/blog/2024-12-01-orioledb-release/thumb.png differ