Blazor et Supabase, Temps réel - Part 3
Suite de l'article sur Blazor et Supabase, dans cette partie nous allons découvrir et mettre en place le temps réel
Banner Image
Part 1 : Base de données
Part 2 : Authentification
Part 3 : Temps réel
Supabase gère également le temps réel. Dans cet article nous verrons deux façons d'utiliser le temps réel :
- Un évenement est emmis lors d'une modification ou création dans une table de la base de données
- Utilisation du temps réel via un broadcast, similaire à un outil comme SignalR
Je vous invite à coner le repo GitHub pour avoir le code complet avec vous : https://github.com/phnogues/Blazor.Supabase/
Prérequis:
- Un compte Supabase (gratuit suffit)
- Avoir paramétré Supabase, vu dans la partie 1 de mes articles sur Supabase
Cas 1 - trigger depuis la base de données
1- Autoriser la table à utiliser le temps réel :
Depuis la table concernée, dans l'interface de Supabase, activer le temps réel avec le bouton "Realtime Off/On" (Table Editor / La table / bouton en haut à droite)
2- Code c# :
- Pour s'abonner à un évenement de la table, dans la méthode OnInitializedAsync :
[Inject]
Supabase.Client _supabase { get; set; }
private RealtimeChannel? _crepesChannel;
protected override async Task OnInitializedAsync()
{
await _supabase.Realtime.ConnectAsync();
// channel for crepes changes
_crepesChannel = _supabase.Realtime.Channel("public:crepes");
if (!_crepesChannel.IsJoined)
{
_crepesChannel.Register(new PostgresChangesOptions("public", "crepes"));
}
_crepesChannel.AddPostgresChangeHandler(PostgresChangesOptions.ListenType.Inserts, CrepeInsertedHandler);
_crepesChannel.AddPostgresChangeHandler(PostgresChangesOptions.ListenType.Updates, CrepeUpdatedHandler);
await _crepesChannel.Subscribe();
}
- Les Handlers seront appelés lors de l'ajout ou la suppression d'une crêpe :
private void CrepeInsertedHandler(IRealtimeChannel _, PostgresChangesResponse change)
{
var crepe = change.Model<Crepe>();
_notificationService.Notify(NotificationSeverity.Success, "New crepe inserted", $"{crepe.Name}");
Events.Add($"New crepe inserted: {crepe.Name}");
this.InvokeAsync(() => this.StateHasChanged());
}
private void CrepeUpdatedHandler(IRealtimeChannel _, PostgresChangesResponse change)
{
var crepe = change.Model<Crepe>();
_notificationService.Notify(NotificationSeverity.Success, "Crepe updated", $"{crepe.Name}");
Events.Add($"Crepe updated: {crepe.Name}");
this.InvokeAsync(() => this.StateHasChanged());
}
Cas 2 : Utilisation d'un broadcast de messages
- Rien à faire côté Supabase (mais on peut surveiller les événements depuis l'onglet Realtime)
- Pour émettre un évenement :
private RealtimeChannel? _kitchenChannel;
protected override async Task OnInitializedAsync()
{
// Realtime
await _supabase.Realtime.ConnectAsync();
_kitchenChannel = _supabase.Realtime.Channel("order");
if (!_kitchenChannel.IsJoined)
{
_kitchenChannel.Register<Order>(true, true);
}
await _kitchenChannel.Subscribe();
}
// Méthode à appeler depuis un bouton ou autre
private async Task Order(CrepeDto crepe)
{
_kitchenChannel?.Broadcast<Order>()?.Send("order", new Order { Name = crepe.Name, Price = crepe.Price, Date = DateTime.UtcNow }); ;
}
- Pour écouter le message :
[Inject]
Supabase.Client _supabase { get; set; }
private RealtimeChannel? _orderChannel;
protected override async Task OnInitializedAsync()
{
await _supabase.Realtime.ConnectAsync();
// channel for orders
_orderChannel = _supabase.Realtime.Channel("order");
if (!_orderChannel.IsJoined)
{
_orderChannel.Register<Order>(true, true);
_orderChannel?.Broadcast<Order>()?.AddBroadcastEventHandler(HandleOrderBroadcastReceived);
}
await _orderChannel.Subscribe();
}
public class Order : BaseBroadcast
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("price")]
public float Price { get; set; }
[JsonProperty("date")]
public DateTime Date { get; set; }
}
- Le Handler associé
private void HandleOrderBroadcastReceived(IRealtimeBroadcast sender, BaseBroadcast? args)
{
var order = _orderChannel?.Broadcast<Order>()?.Current();
if (order == null) return;
_notificationService.Notify(NotificationSeverity.Warning, "New order ! ", $"{order.Name}");
Events.Add($"New order: {order.Name} {order.Price}€ {order.Date}");
this.InvokeAsync(() => this.StateHasChanged());
}