Real-time Subscriptions
PGRestify provides comprehensive real-time capabilities through WebSocket connections, enabling applications to receive live updates for database changes. The real-time system supports event subscriptions, filtering, automatic reconnection, and scaling considerations.
Basic Setup
WebSocket Connection
Configure real-time connections when creating your client:
typescript
import { createClient } from '@webcoded/pgrestify';
const client = createClient({
url: 'http://localhost:3000',
realtime: {
url: 'ws://localhost:3001', // WebSocket URL
heartbeatInterval: 30000, // 30 seconds
reconnect: {
enabled: true,
maxAttempts: 5,
delay: 1000
}
}
});
Connection Management
typescript
// Connect to real-time server
await client.realtime.connect();
// Check connection status
console.log('Connected:', client.realtime.isConnected);
// Listen for connection events
client.realtime.on('connect', () => {
console.log('Real-time connection established');
});
client.realtime.on('disconnect', () => {
console.log('Real-time connection lost');
});
client.realtime.on('reconnect', (attempt) => {
console.log(`Reconnecting... attempt ${attempt}`);
});
Event Subscriptions
Basic Table Subscriptions
Subscribe to changes on specific tables:
typescript
interface User {
id: string;
name: string;
email: string;
created_at: string;
}
// Subscribe to all changes on users table
const userSubscription = client.realtime
.channel('users')
.on('*', (payload) => {
console.log('User change:', payload);
switch (payload.eventType) {
case 'INSERT':
console.log('New user:', payload.new);
break;
case 'UPDATE':
console.log('Updated user:', payload.new);
console.log('Previous data:', payload.old);
break;
case 'DELETE':
console.log('Deleted user:', payload.old);
break;
}
})
.subscribe();
// Unsubscribe when done
// userSubscription.unsubscribe();
Event-Specific Subscriptions
Listen to specific types of database events:
typescript
// Listen only to new records
client.realtime
.channel('posts')
.on('INSERT', (payload) => {
console.log('New post created:', payload.new);
// Update UI with new post
addPostToList(payload.new);
})
.subscribe();
// Listen only to updates
client.realtime
.channel('users')
.on('UPDATE', (payload) => {
console.log('User updated:', payload.new);
// Update user profile in UI
updateUserProfile(payload.new);
})
.subscribe();
// Listen only to deletions
client.realtime
.channel('comments')
.on('DELETE', (payload) => {
console.log('Comment deleted:', payload.old);
// Remove comment from UI
removeCommentFromList(payload.old.id);
})
.subscribe();
React Integration
useRealtimeSubscription Hook
typescript
import { useEffect, useState } from 'react';
import { useRealtimeSubscription } from '@webcoded/pgrestify/react';
function LivePostList() {
const [posts, setPosts] = useState<Post[]>([]);
// Subscribe to real-time updates
useRealtimeSubscription('posts', {
event: '*',
onInsert: (post) => {
setPosts(prev => [post, ...prev]);
},
onUpdate: (post) => {
setPosts(prev => prev.map(p =>
p.id === post.id ? { ...p, ...post } : p
));
},
onDelete: (post) => {
setPosts(prev => prev.filter(p => p.id !== post.id));
}
});
return (
<div>
<h2>Live Posts ({posts.length})</h2>
{posts.map(post => (
<div key={post.id} className="post">
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
))}
</div>
);
}
Reconnection Handling
Automatic Reconnection
typescript
const client = createClient({
url: 'http://localhost:3000',
realtime: {
url: 'ws://localhost:3001',
reconnect: {
enabled: true,
maxAttempts: 10, // Try 10 times
delay: 1000, // Start with 1 second
delayMultiplier: 1.5, // Exponential backoff
maxDelay: 30000 // Max 30 seconds between attempts
}
}
});
Connection State Management
typescript
enum ConnectionState {
DISCONNECTED = 'disconnected',
CONNECTING = 'connecting',
CONNECTED = 'connected',
RECONNECTING = 'reconnecting',
ERROR = 'error'
}
function useConnectionState() {
const [state, setState] = useState<ConnectionState>(ConnectionState.DISCONNECTED);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const client = usePGRestifyClient();
client.realtime.on('connecting', () => {
setState(ConnectionState.CONNECTING);
setError(null);
});
client.realtime.on('connect', () => {
setState(ConnectionState.CONNECTED);
setError(null);
});
client.realtime.on('disconnect', () => {
setState(ConnectionState.DISCONNECTED);
});
client.realtime.on('reconnecting', () => {
setState(ConnectionState.RECONNECTING);
});
client.realtime.on('error', (err: Error) => {
setState(ConnectionState.ERROR);
setError(err.message);
});
}, []);
return { state, error };
}
Best Practices
1. Subscription Management
typescript
// Good: Use subscription managers
class SubscriptionManager {
private subscriptions = new Map<string, Function>();
add(key: string, unsubscribe: Function) {
// Clean up existing subscription
this.remove(key);
this.subscriptions.set(key, unsubscribe);
}
remove(key: string) {
const unsubscribe = this.subscriptions.get(key);
if (unsubscribe) {
unsubscribe();
this.subscriptions.delete(key);
}
}
removeAll() {
this.subscriptions.forEach(unsubscribe => unsubscribe());
this.subscriptions.clear();
}
}
2. Error Handling
typescript
// Robust error handling for real-time subscriptions
client.realtime
.channel('posts')
.on('*', (payload) => {
try {
handleRealtimeUpdate(payload);
} catch (error) {
console.error('Error handling real-time update:', error);
// Log error to monitoring service
logError('realtime_handler_error', error, payload);
// Optionally refresh data as fallback
refreshDataFromServer();
}
})
.on('error', (error) => {
console.error('Real-time channel error:', error);
// Handle channel-specific errors
})
.subscribe();
Summary
PGRestify's real-time system provides:
- WebSocket Connections: Persistent, low-latency real-time communication
- Event Subscriptions: Subscribe to INSERT, UPDATE, DELETE events on specific tables
- Automatic Reconnection: Robust reconnection handling with exponential backoff
- React Integration: Purpose-built hooks for React applications
- Error Resilience: Comprehensive error handling and fallback mechanisms
Real-time subscriptions enable building responsive, collaborative applications with live data updates and excellent user experiences.