mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 10:11:13 -05:00
8.1 KiB
8.1 KiB
Migrating from Legacy to Novu Notifications
This guide covers migrating from the old notification system to the new Novu-powered system.
Migration Overview
The new notification system:
- Uses Novu for multi-channel delivery
- Supports granular preferences per workflow
- Includes frequency controls
- Provides delivery tracking
- Backwards compatible with existing preferences
Data Migration
Step 1: Migrate Existing User Preferences
The system automatically migrates old preferences from user_preferences.email_notifications and user_preferences.push_notifications to the new user_notification_preferences table.
Run this migration script to batch migrate existing users:
-- Migrate existing users to new notification preferences
INSERT INTO user_notification_preferences (
user_id,
channel_preferences,
workflow_preferences,
frequency_settings
)
SELECT
user_id,
jsonb_build_object(
'in_app', true,
'email', COALESCE((email_notifications->>'system_announcements')::boolean, true),
'push', COALESCE((push_notifications->>'browser_enabled')::boolean, false),
'sms', false
),
jsonb_build_object(
'review-reply', COALESCE((email_notifications->>'review_replies')::boolean, true),
'new-follower', COALESCE((email_notifications->>'new_followers')::boolean, true),
'system-announcement', COALESCE((email_notifications->>'system_announcements')::boolean, true),
'weekly-digest', COALESCE((email_notifications->>'weekly_digest')::boolean, false),
'monthly-digest', COALESCE((email_notifications->>'monthly_digest')::boolean, true)
),
jsonb_build_object(
'digest', 'daily',
'max_per_hour', 10
)
FROM user_preferences
WHERE NOT EXISTS (
SELECT 1 FROM user_notification_preferences
WHERE user_notification_preferences.user_id = user_preferences.user_id
);
Step 2: Create Novu Subscribers for Existing Users
Create a batch script to register all existing users as Novu subscribers:
import { supabase } from '@/integrations/supabase/client';
import { notificationService } from '@/lib/notificationService';
async function migrateUsersToNovu() {
const { data: profiles, error } = await supabase
.from('profiles')
.select('user_id, username, display_name')
.is('banned', false);
if (error) {
console.error('Error fetching profiles:', error);
return;
}
for (const profile of profiles) {
// Get user's auth data for email
const { data: { user } } = await supabase.auth.admin.getUserById(profile.user_id);
if (user?.email) {
await notificationService.createSubscriber({
subscriberId: profile.user_id,
email: user.email,
firstName: profile.display_name?.split(' ')[0],
lastName: profile.display_name?.split(' ').slice(1).join(' '),
data: {
username: profile.username,
},
});
console.log(`Migrated user: ${profile.username}`);
// Rate limit to avoid overwhelming Novu API
await new Promise(resolve => setTimeout(resolve, 100));
}
}
console.log('Migration complete!');
}
Code Migration
Updating Notification Triggers
Old Way:
// Direct database insert (legacy)
await supabase
.from('notifications')
.insert({
user_id: userId,
type: 'review_reply',
content: 'Someone replied to your review',
});
New Way:
// Using Novu via notificationService
import { notificationService } from '@/lib/notificationService';
await notificationService.trigger({
workflowId: 'review-reply',
subscriberId: userId,
payload: {
reviewTitle: 'Great ride!',
replyAuthor: 'Jane Doe',
replyContent: 'Thanks for the review!',
reviewUrl: `/reviews/${reviewId}`,
},
});
Updating Preference Management
Old Way:
await supabase
.from('user_preferences')
.update({
email_notifications: {
review_replies: false,
},
})
.eq('user_id', userId);
New Way:
import { notificationService } from '@/lib/notificationService';
await notificationService.updatePreferences(userId, {
channelPreferences: {
in_app: true,
email: true,
push: false,
sms: false,
},
workflowPreferences: {
'review-reply': false,
},
frequencySettings: {
digest: 'daily',
max_per_hour: 10,
},
});
Rollback Plan
If you need to rollback to the old system:
- Keep Old Tables: Don't drop
user_preferences.email_notificationsorpush_notificationscolumns - Disable Novu: Clear
VITE_NOVU_APPLICATION_IDENTIFIERenvironment variable - Revert Code: The notification service gracefully handles missing Novu config
Testing the Migration
Test Checklist
- All existing users have entries in
user_notification_preferences - User preferences match their previous settings
- Test users receive notifications on all enabled channels
- Webhook is receiving delivery events
- Notification logs are being created
- User preference changes sync to Novu
- Unsubscribe links work correctly
- Email templates render correctly
- Push notifications work in supported browsers
- In-app notifications display correctly
Test Script
// Test notification delivery
import { notificationService } from '@/lib/notificationService';
async function testNotifications(testUserId: string) {
console.log('Testing notification delivery...');
// Test each workflow
const workflows = [
{
id: 'review-reply',
payload: {
reviewTitle: 'Test Review',
replyAuthor: 'Test User',
replyContent: 'Test reply content',
reviewUrl: '/test',
},
},
{
id: 'new-follower',
payload: {
followerName: 'Test Follower',
followerProfile: '/profile/test',
},
},
];
for (const workflow of workflows) {
const result = await notificationService.trigger({
workflowId: workflow.id,
subscriberId: testUserId,
payload: workflow.payload,
});
console.log(`${workflow.id}: ${result.success ? '✓' : '✗'}`);
if (!result.success) {
console.error(`Error: ${result.error}`);
}
}
}
Performance Considerations
Batch Operations
When migrating large numbers of users:
- Rate Limiting: Add delays between API calls
- Batch Size: Process in chunks of 100-500 users
- Error Handling: Log failures and retry
- Progress Tracking: Store migration state
Optimization Tips
- Cache Templates: Load notification templates once at startup
- Async Processing: Use edge functions for heavy operations
- Database Indexes: Already created on
user_notification_preferences - Connection Pooling: Supabase handles this automatically
Monitoring Post-Migration
Track these metrics after migration:
-- Delivery success rate
SELECT
DATE(created_at) as date,
COUNT(*) FILTER (WHERE status = 'delivered') * 100.0 / COUNT(*) as success_rate
FROM notification_logs
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY DATE(created_at)
ORDER BY date DESC;
-- Channel usage
SELECT
channel,
COUNT(*) as total_sent,
COUNT(*) FILTER (WHERE status = 'delivered') as delivered,
COUNT(*) FILTER (WHERE read_at IS NOT NULL) as read
FROM notification_logs
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY channel;
-- User engagement
SELECT
COUNT(DISTINCT user_id) as active_users,
AVG(EXTRACT(EPOCH FROM (read_at - delivered_at))) as avg_time_to_read_seconds
FROM notification_logs
WHERE read_at IS NOT NULL
AND created_at > NOW() - INTERVAL '7 days';
Support During Migration
- Backup Data: Export old notification preferences before migration
- Phased Rollout: Enable for a subset of users first
- Feature Flag: Use admin settings to control Novu enablement
- User Communication: Notify users of new notification features
- Monitor Logs: Watch edge function logs during migration
Timeline
Recommended migration timeline:
- Week 1: Test with internal users
- Week 2: Rollout to 10% of users
- Week 3: Rollout to 50% of users
- Week 4: Complete rollout
- Week 5: Remove legacy code (optional)