Version 1.34.2 | Production Ready | Unreal Engine 5.5+
The Supabase UE5 Plugin provides a comprehensive event handling system that enables real-time database monitoring, asynchronous operation callbacks, and thread-safe event broadcasting throughout your Unreal Engine application.
The plugin’s event handling architecture consists of three main components:
The plugin monitors database changes in real-time through WebSocket connections and broadcasts events for:
Each database event contains:
FString EventType; // "INSERT", "UPDATE", or "DELETE"
FString PayloadString; // JSON payload with change details
Blueprint:
Use "Subscribe to Table Changes" node:
- Table Name: "your_table_name"
- Schema: "public" (or custom schema)
- Event Types: ["*"] for all events or specific types
C++:
// Subscribe to all changes on a table
UAsyncRealtime* RealtimeTask = UAsyncRealtime::AsyncRealtime(
this,
TEXT("your_table_name"),
TArray<FString>() // Empty = subscribe to all events
);
// Bind to specific event types
RealtimeTask->OnInsert.AddDynamic(this, &AYourActor::HandleInsert);
RealtimeTask->OnUpdate.AddDynamic(this, &AYourActor::HandleUpdate);
RealtimeTask->OnDelete.AddDynamic(this, &AYourActor::HandleDelete);
RealtimeTask->Activate();
You can filter events by specific types:
// Subscribe only to INSERT and UPDATE events
TArray<FString> EventTypes = { TEXT("INSERT"), TEXT("UPDATE") };
UAsyncRealtime* RealtimeTask = UAsyncRealtime::AsyncRealtime(
this,
TEXT("your_table_name"),
EventTypes
);
All async operations follow a consistent event structure:
Success Events:
OnSuccess: Triggered when operation completes successfullyFailure Events:
OnFailure: Triggered when operation encounters an error// Login Events
UAsyncLogin* LoginTask = UAsyncLogin::AsyncLogin(this, Email, Password);
LoginTask->OnSuccess.AddDynamic(this, &AYourActor::OnLoginSuccess);
LoginTask->OnFailure.AddDynamic(this, &AYourActor::OnLoginFailure);
// Event Handlers
UFUNCTION()
void OnLoginSuccess(FString Response, const FTokenResponse& TokenResponse);
UFUNCTION()
void OnLoginFailure(FString Error);
// Query Events
UAsyncQuery* QueryTask = UAsyncQuery::AsyncQuery(this, "users", "*", Filters);
QueryTask->OnSuccess.AddDynamic(this, &AYourActor::OnQuerySuccess);
QueryTask->OnFailure.AddDynamic(this, &AYourActor::OnQueryFailure);
// Event Handlers
UFUNCTION()
void OnQuerySuccess(FString Response);
UFUNCTION()
void OnQueryFailure(FString Error);
// Upload Events
UAsyncUploadFile* UploadTask = UAsyncUploadFile::AsyncUploadFile(
this, BucketName, FilePath, FileData
);
UploadTask->OnSuccess.AddDynamic(this, &AYourActor::OnUploadSuccess);
UploadTask->OnFailure.AddDynamic(this, &AYourActor::OnUploadFailure);
The USupabaseSubsystem provides centralized event broadcasting that can be accessed from anywhere in your application:
// Get subsystem instance
USupabaseSubsystem* Subsystem = USupabaseManager::GetSupabaseSubsystem(this);
// Bind to global events
Subsystem->OnLoginSuccessful.AddDynamic(this, &AYourActor::OnGlobalLoginSuccess);
Subsystem->OnLoginFailed.AddDynamic(this, &AYourActor::OnGlobalLoginFailure);
Subsystem->OnConnectionStateChanged.AddDynamic(this, &AYourActor::OnConnectionChanged);
| Event | Description | Parameters |
|---|---|---|
OnLoginSuccessful |
User authentication succeeded | FString Response, FTokenResponse Token |
OnLoginFailed |
User authentication failed | FString Error |
OnConnectionStateChanged |
Connection status changed | EConnectionState NewState |
OnTokenRefreshed |
Access token refreshed | FTokenResponse NewToken |
All event broadcasting is automatically handled on the game thread:
// Internal implementation ensures thread safety
void UAsyncRealtime::HandleMessage(const FString& Message)
{
// Process message on background thread
// ...
// Broadcast events on game thread
ExecuteOnGameThread([this, EventType, PayloadString]()
{
if (!bIsShuttingDown && IsValid(this))
{
OnInsert.Broadcast(EventType, PayloadString);
}
});
}
The plugin automatically handles event cleanup during object destruction:
// Automatic cleanup in async operations
void UAsyncOperation::SafeCleanup()
{
UnbindEvents();
// Clear references and sensitive data
}
virtual void BeginDestroy() override
{
SafeCleanup();
Super::BeginDestroy();
}
The plugin includes comprehensive error recovery for event handling:
Connection Recovery:
// Automatic reconnection with exponential backoff
void UAsyncRealtime::HandleConnectionError()
{
SetConnectionState(ERealtimeConnectionState::Error);
// Schedule reconnection attempt
GetWorld()->GetTimerManager().SetTimer(
ReconnectTimer,
this,
&UAsyncRealtime::AttemptReconnection,
CalculateBackoffDelay(),
false
);
}
Event Validation:
// Validate incoming events before processing
void UAsyncRealtime::HandleMessage(const FString& Message)
{
// Parse and validate JSON
if (!JsonObject->HasField(TEXT("event")))
{
UE_LOG(LogSupabaseRealtime, Warning,
TEXT("Message missing event field: %s"), *Message);
return;
}
// Process validated event
}
To prevent event flooding, the plugin includes rate limiting:
// Heartbeat rate limiting
const float MIN_HEARTBEAT_INTERVAL = 1.0f;
void UAsyncRealtime::SendHeartbeat()
{
float CurrentTime = FPlatformTime::Seconds();
if (CurrentTime - LastHeartbeatTime < MIN_HEARTBEAT_INTERVAL)
{
return; // Skip if too frequent
}
// Send heartbeat
}
Events are automatically cleaned up to prevent memory leaks:
// Automatic cleanup when operation completes
void UAsyncOperation::HandleSuccess()
{
OnSuccess.Broadcast(/* results */);
SafeCleanup();
SetReadyToDestroy();
}
// Correct order
UAsyncQuery* QueryTask = UAsyncQuery::AsyncQuery(this, "users", "*", Filters);
QueryTask->OnSuccess.AddDynamic(this, &AYourActor::OnQuerySuccess); // Bind first
QueryTask->OnFailure.AddDynamic(this, &AYourActor::OnQueryFailure);
QueryTask->Activate(); // Activate last
// Always implement both handlers
UFUNCTION()
void OnOperationSuccess(FString Response) { /* Handle success */ }
UFUNCTION()
void OnOperationFailure(FString Error) { /* Handle failure */ }
// Use subsystem for application-wide events
USupabaseSubsystem* Subsystem = USupabaseManager::GetSupabaseSubsystem(this);
if (Subsystem)
{
Subsystem->OnLoginSuccessful.AddDynamic(this, &AGameMode::OnUserLoggedIn);
}
// Override BeginDestroy for proper cleanup
virtual void BeginDestroy() override
{
// Unbind all events
if (USupabaseSubsystem* Subsystem = USupabaseManager::GetSupabaseSubsystem(this))
{
Subsystem->OnLoginSuccessful.RemoveDynamic(this, &AYourActor::OnLoginSuccess);
}
Super::BeginDestroy();
}
// In your project settings or code
UE_LOG(LogSupabaseRealtime, Verbose, TEXT("Event details: %s"), *EventData);
// Track event flow in your handlers
UFUNCTION()
void OnDatabaseChange(FString EventType, FString Payload)
{
UE_LOG(LogTemp, Log, TEXT("Database change received: %s"), *EventType);
UE_LOG(LogTemp, Verbose, TEXT("Change payload: %s"), *Payload);
}
Events Not Firing:
Memory Leaks:
Thread Safety Issues:
For additional help with event handling:
This documentation is maintained for Supabase UE5 Plugin version 1.34.2. For the latest updates and changes, please refer to the plugin release notes.