Real-time Subscriptions — Supabase
الاشتراكات في الوقت الحقيقي (Realtime)
بدل أن يسأل التطبيق الخادم كل ثانية "هل هناك جديد؟"، يفتح اتصالاً دائماً (WebSocket) ويستقبل التغييرات لحظة حدوثها: رسائل الدردشة، الإشعارات، لوحات المتابعة، التحرير المشترك.
ثلاثة أنواع
| النوع | ما ينقله | مثال |
|---|---|---|
| Postgres Changes | تغييرات الجداول (INSERT/UPDATE/DELETE) | رسالة جديدة حُفظت في قاعدة البيانات |
| Broadcast | رسائل بين العملاء دون حفظ | "فلان يكتب الآن..."، مؤشر الفأرة في تحرير مشترك |
| Presence | من متصل الآن | قائمة المتصلين في غرفة |
تغييرات الجداول
import { supabase } from "./supabaseClient.js";
export function subscribeToRoom(roomId, onMessage) {
const channel = supabase
.channel(`room-${roomId}`)
.on(
"postgres_changes",
{ event: "INSERT", schema: "public", table: "messages", filter: `room_id=eq.${roomId}` },
(payload) => onMessage(payload.new)
)
.subscribe();
return () => supabase.removeChannel(channel); // استدعها عند مغادرة الغرفة
}- فعّل الجدول للوقت الحقيقي أولاً: Database ← Publications ← supabase_realtime (أو ALTER PUBLICATION supabase_realtime ADD TABLE messages;).
- filter يقلل البيانات المرسلة (ويقلل الاستهلاك).
- payload.new الصف الجديد، و payload.old القديم (لـ UPDATE و DELETE؛ يحتاج REPLICA IDENTITY FULL للحصول على كل أعمدته).
الأمان
تغييرات الجداول تحترم RLS: المشترك يستقبل فقط الصفوف التي تسمح له سياسات SELECT برؤيتها. بدون RLS، أي شخص يستطيع الاستماع لكل التغييرات. قنوات Broadcast و Presence الخاصة تُحمى بتفعيل خيار القنوات الخاصة وسياسات على realtime.messages.
إلغاء الاشتراك
اشتراك لا يُلغى = تسرب اتصالات وذاكرة، وأحداث مكررة عند العودة للشاشة. في React:
// useEffect(() => subscribeToRoom(roomId, addMessage), [roomId]);
// الدالة المُعادة من subscribeToRoom تُستدعى تلقائياً عند التفكيك أو تغيير الغرفة
const cleanupPattern = "useEffect(() => subscribe(...), [deps])";
console.log(cleanupPattern);نمط شائع: الجلب ثم الاشتراك
1. اجلب آخر 50 رسالة بـ select.
2. اشترك في INSERT الجديدة وأضفها للقائمة.
3. احذر التكرار: رسالة أُرسلت بين الخطوتين قد تصل مرتين — ميّزها بالمعرّف.
تمرين
ابنِ غرفة دردشة: جلب آخر الرسائل، الاشتراك في الجديدة، مؤشر "يكتب الآن" بـ Broadcast، وقائمة المتصلين بـ Presence. تأكد من إلغاء الاشتراكات عند مغادرة الصفحة.
// ===== الاشتراك في تغييرات جدول =====
const subscription = supabase
.channel('public:messages')
.on('postgres_changes',
{ event: '*', schema: 'public', table: 'messages' },
(payload) => {
console.log('تغيير:', payload);
if (payload.eventType === 'INSERT') {
console.log('رسالة جديدة:', payload.new);
}
}
)
.subscribe();
// ===== الاشتراك في INSERT فقط =====
const messagesSubscription = supabase
.channel('new-messages')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'messages' },
(payload) => {
// أضف الرسالة الجديدة للقائمة
setMessages(prev => [...prev, payload.new]);
}
)
.subscribe();
// ===== مع فلتر =====
const myMessages = supabase
.channel('my-messages')
.on('postgres_changes',
{
event: '*',
schema: 'public',
table: 'messages',
filter: 'user_id=eq.123'
},
(payload) => {
console.log('رسالتي:', payload);
}
)
.subscribe();
// ===== إلغاء الاشتراك =====
supabase.removeChannel(subscription);اختبر فهمك