mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
This PR migrates the whole monorepo to use Tailwind v4: - Removed `@tailwindcss/container-queries` plugin since it's included by default in v4, - Bump all instances of Tailwind to v4. Made minimal changes to the shared config to remove non-supported features (`alpha` mentions), - Migrate all apps to be compatible with v4 configs, - Fix the `typography.css` import in 3 apps, - Add missing rules which were included by default in v3, - Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot of classes - Rename all misnamed classes according to https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all apps. --------- Co-authored-by: Jordi Enric <jordi.err@gmail.com>
335 lines
9.4 KiB
Plaintext
335 lines
9.4 KiB
Plaintext
---
|
||
title: Quickstart
|
||
subtitle: 'Learn how to use Supabase Queues to add and read messages'
|
||
---
|
||
|
||
{/* <!-- vale off --> */}
|
||
This guide is an introduction to interacting with Supabase Queues via the Dashboard and official client library. Check out [Queues API Reference](/docs/guides/queues/api) for more details on our API.
|
||
|
||
## Concepts
|
||
|
||
Supabase Queues is a pull-based Message Queue consisting of three main components: Queues, Messages, and Queue Types.
|
||
|
||
### Pull-Based Queue
|
||
|
||
A pull-based Queue is a Message storage and delivery system where consumers actively fetch Messages when they're ready to process them - similar to constantly refreshing a webpage to display the latest updates. Our pull-based Queues process Messages in a First-In-First-Out (FIFO) manner without priority levels.
|
||
|
||
### Message
|
||
|
||
A Message in a Queue is a JSON object that is stored until a consumer explicitly processes and removes it, like a task waiting in a to-do list until someone checks and completes it.
|
||
|
||
### Queue types
|
||
|
||
Supabase Queues offers three types of Queues:
|
||
|
||
- **Basic Queue**: A durable Queue that stores Messages in a logged table.
|
||
- **Unlogged Queue**: A transient Queue that stores Messages in an unlogged table for better performance but may result in loss of Queue Messages.
|
||
|
||
- **Partitioned Queue** (_Coming Soon_): A durable and scalable Queue that stores Messages in multiple table partitions for better performance.
|
||
|
||
## Create Queues
|
||
|
||
To get started, navigate to the [Supabase Queues](/dashboard/project/_/integrations/queues/overview) Postgres Module under Integrations in the Dashboard and enable the `pgmq` extension.
|
||
|
||
<Admonition type="note">
|
||
|
||
`pgmq` extension is available in Postgres version 15.6.1.143 or later.
|
||
|
||
</Admonition>
|
||
|
||
<Image
|
||
alt="Supabase Dashboard Integrations page, showing the Queues Postgres Module"
|
||
src={{
|
||
dark: '/docs/img/queues-quickstart-install.png',
|
||
light: '/docs/img/queues-quickstart-install.png',
|
||
}}
|
||
|
||
width={2064}
|
||
height={1720}
|
||
/>
|
||
|
||
On the [Queues page](/dashboard/project/_/integrations/queues/queues):
|
||
|
||
- Click **Add a new queue** button
|
||
|
||
<Admonition type="note">
|
||
|
||
If you've already created a Queue click the **Create a queue** button instead.
|
||
|
||
</Admonition>
|
||
|
||
- Name your queue
|
||
|
||
<Admonition type="note">
|
||
|
||
Queue names can only be lowercase and hyphens and underscores are permitted.
|
||
|
||
</Admonition>
|
||
|
||
- Select your [Queue Type](#queue-types)
|
||
|
||
<Image
|
||
alt="Create a Queue from the Supabase Dashboard"
|
||
src={{
|
||
dark: '/docs/img/queues-quickstart-create.png',
|
||
light: '/docs/img/queues-quickstart-create.png',
|
||
}}
|
||
|
||
className="max-w-lg mx-auto!"
|
||
|
||
width={1456}
|
||
height={1420}
|
||
/>
|
||
|
||
### What happens when you create a queue?
|
||
|
||
Every new Queue creates two tables in the `pgmq` schema. These tables are `pgmq.q_<queue_name>` to store and process active messages and `pgmq.a_<queue_name>` to store any archived messages.
|
||
|
||
A "Basic Queue" will create `pgmq.q_<queue_name>` and `pgmq.a_<queue_name>` tables as logged tables.
|
||
|
||
However, an "Unlogged Queue" will create `pgmq.q_<queue_name>` as an unlogged table for better performance while sacrificing durability. The `pgmq.a_<queue_name>` table will still be created as a logged table so your archived messages remain safe and secure.
|
||
|
||
## Expose Queues to client-side consumers
|
||
|
||
Queues, by default, are not exposed over Supabase Data API and are only accessible via Postgres clients.
|
||
|
||
However, you may grant client-side consumers access to your Queues by enabling the Supabase Data API and granting permissions to the Queues API, which is a collection of database functions in the `pgmq_public` schema that wraps the database functions in the `pgmq` schema.
|
||
|
||
This is to prevent direct access to the `pgmq` schema and its tables (RLS is not enabled by default on any tables) and database functions.
|
||
|
||
To get started, navigate to the Queues [Settings page](/dashboard/project/_/integrations/queues/settings) and toggle on “Expose Queues via PostgREST”. Once enabled, Supabase creates and exposes a `pgmq_public` schema containing database function wrappers to a subset of `pgmq`'s database functions.
|
||
|
||
<Image
|
||
alt="Screenshot of Queues settings with toggle to expose to PostgREST"
|
||
src={{
|
||
dark: '/docs/img/queues-quickstart-settings.png',
|
||
light: '/docs/img/queues-quickstart-settings.png',
|
||
}}
|
||
|
||
width={2140}
|
||
height={1642}
|
||
/>
|
||
|
||
### Enable RLS on your tables in `pgmq` schema
|
||
|
||
For security purposes, you must enable Row Level Security (RLS) on all Queue tables (all tables in `pgmq` schema that begin with `q_`) if the Data API is enabled.
|
||
|
||
You’ll want to create RLS policies for any Queues you want your client-side consumers to interact with.
|
||
|
||
<Image
|
||
alt="Screenshot of creating an RLS policy from the Queues settings"
|
||
src={{
|
||
dark: '/docs/img/queues-quickstart-rls.png',
|
||
light: '/docs/img/queues-quickstart-rls.png',
|
||
}}
|
||
|
||
width={2130}
|
||
height={1508}
|
||
/>
|
||
|
||
### Grant permissions to `pgmq_public` database functions
|
||
|
||
On top of enabling RLS and writing RLS policies on the underlying Queue tables, you must grant the correct permissions to the `pgmq_public` database functions for each Data API role.
|
||
|
||
The permissions required for each Queue API database function:
|
||
|
||
| **Operations** | **Permissions Required** |
|
||
| ------------------- | ------------------------ |
|
||
| `send` `send_batch` | `Select` `Insert` |
|
||
| `read` `pop` | `Select` `Update` |
|
||
| `archive` `delete` | `Select` `Delete` |
|
||
|
||
To manage your queue permissions, click on the Queue Settings button.
|
||
|
||
<Image
|
||
alt="Screenshot of accessing queue settings"
|
||
src={{
|
||
dark: '/docs/img/queues-quickstart-queue-settings.png',
|
||
light: '/docs/img/queues-quickstart-queue-settings.png',
|
||
}}
|
||
|
||
width={2150}
|
||
height={1192}
|
||
/>
|
||
|
||
Then enable the required roles permissions.
|
||
|
||
<Image
|
||
alt="Screenshot of configuring API access for roles from the Queues settings"
|
||
src={{
|
||
dark: '/docs/img/queues-quickstart-roles.png',
|
||
light: '/docs/img/queues-quickstart-roles-light.png',
|
||
}}
|
||
|
||
width={1271}
|
||
height={1315}
|
||
/>
|
||
|
||
<Admonition type="note">
|
||
|
||
`postgres` and `service_role` roles should never be exposed client-side.
|
||
|
||
</Admonition>
|
||
|
||
### Enqueueing and dequeueing messages
|
||
|
||
Once your Queue has been created, you can begin enqueueing and dequeueing Messages.
|
||
|
||
<Tabs
|
||
scrollable
|
||
size="small"
|
||
type="underlined"
|
||
defaultActiveId="js"
|
||
queryGroup="language"
|
||
>
|
||
<TabPanel id="js" label="JavaScript">
|
||
|
||
```tsx
|
||
import { createClient } from '@supabase/supabase-js'
|
||
|
||
const supabaseUrl = 'supabaseURL'
|
||
const supabaseKey = 'supabaseKey'
|
||
|
||
const supabase = createClient(supabaseUrl, supabaseKey)
|
||
|
||
const QueuesTest: React.FC = () => {
|
||
//Add a Message
|
||
const sendToQueue = async () => {
|
||
const result = await supabase.schema('pgmq_public').rpc('send', {
|
||
queue_name: 'foo',
|
||
message: { hello: 'world' },
|
||
sleep_seconds: 30,
|
||
})
|
||
console.log(result)
|
||
}
|
||
|
||
//Dequeue Message
|
||
const popFromQueue = async () => {
|
||
const result = await supabase.schema('pgmq_public').rpc('pop', { queue_name: 'foo' })
|
||
console.log(result)
|
||
}
|
||
|
||
return (
|
||
<div className="p-6">
|
||
<h2 className="text-2xl font-bold mb-4">Queue Test Component</h2>
|
||
<button
|
||
onClick={sendToQueue}
|
||
className="bg-blue-500 text-white px-4 py-2 rounded-sm hover:bg-blue-600 mr-4"
|
||
>
|
||
Add Message
|
||
</button>
|
||
<button
|
||
onClick={popFromQueue}
|
||
className="bg-blue-500 text-white px-4 py-2 rounded-sm hover:bg-blue-600"
|
||
>
|
||
Pop Message
|
||
</button>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default QueuesTest
|
||
```
|
||
|
||
</TabPanel>
|
||
<$Show if="sdk:dart">
|
||
<TabPanel id="dart" label="Dart">
|
||
|
||
```dart
|
||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||
|
||
final supabase = Supabase.instance.client;
|
||
|
||
// Add a Message
|
||
Future<void> sendToQueue() async {
|
||
final result = await supabase.schema('pgmq_public').rpc('send', params: {
|
||
'queue_name': 'foo',
|
||
'message': {'hello': 'world'},
|
||
'sleep_seconds': 30,
|
||
});
|
||
print(result);
|
||
}
|
||
|
||
// Dequeue Message
|
||
Future<void> popFromQueue() async {
|
||
final result = await supabase.schema('pgmq_public').rpc('pop', params: {
|
||
'queue_name': 'foo',
|
||
});
|
||
print(result);
|
||
}
|
||
```
|
||
|
||
</TabPanel>
|
||
</$Show>
|
||
<$Show if="sdk:swift">
|
||
<TabPanel id="swift" label="Swift">
|
||
|
||
```swift
|
||
import Supabase
|
||
|
||
let supabase = SupabaseClient(
|
||
supabaseURL: URL(string: "supabaseURL")!,
|
||
supabaseKey: "supabaseKey"
|
||
)
|
||
|
||
// Add a Message
|
||
func sendToQueue() async throws {
|
||
let result = try await supabase
|
||
.schema("pgmq_public")
|
||
.rpc("send", params: [
|
||
"queue_name": AnyJSON.string("foo"),
|
||
"message": AnyJSON.object(["hello": "world"]),
|
||
"sleep_seconds": AnyJSON.integer(30)
|
||
])
|
||
.execute()
|
||
print(result)
|
||
}
|
||
|
||
// Dequeue Message
|
||
func popFromQueue() async throws {
|
||
let result = try await supabase
|
||
.schema("pgmq_public")
|
||
.rpc("pop", params: ["queue_name": "foo"])
|
||
.execute()
|
||
print(result)
|
||
}
|
||
```
|
||
|
||
</TabPanel>
|
||
</$Show>
|
||
<$Show if="sdk:python">
|
||
<TabPanel id="python" label="Python">
|
||
|
||
```python
|
||
from supabase import create_client, Client
|
||
|
||
supabase_url = "supabaseURL"
|
||
supabase_key = "supabaseKey"
|
||
|
||
supabase: Client = create_client(supabase_url, supabase_key)
|
||
|
||
# Add a Message
|
||
def send_to_queue():
|
||
result = supabase.schema("pgmq_public").rpc(
|
||
"send",
|
||
{
|
||
"queue_name": "foo",
|
||
"message": {"hello": "world"},
|
||
"sleep_seconds": 30,
|
||
}
|
||
).execute()
|
||
print(result)
|
||
|
||
# Dequeue Message
|
||
def pop_from_queue():
|
||
result = supabase.schema("pgmq_public").rpc(
|
||
"pop",
|
||
{"queue_name": "foo"}
|
||
).execute()
|
||
print(result)
|
||
```
|
||
|
||
</TabPanel>
|
||
</$Show>
|
||
</Tabs>
|