Implementation:TobikoData Sqlmesh NotificationCenter
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, Error_Management, State_Management |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
Centralized error notification system providing global error state management and categorization for the SQLMesh web UI.
Description
NotificationCenterProvider implements a React context-based notification system for managing application-wide errors. It maintains a Set of ErrorIDE objects with unique IDs, timestamps, and categorization by error keys (API, internal, plan operations, etc.). The system provides methods for adding, removing, and clearing errors with automatic ID generation and metadata enrichment.
Key features include EnumErrorKey enum defining 25+ error categories (API, RunPlan, ApplyPlan, Environments, Models, FileExplorer, etc.), addError() method that returns both the error object and a cleanup function, removeError() supporting removal by error object or key, clearErrors() for bulk deletion, and error enrichment with unique IDs, timestamps, and full ApiExceptionPayload data.
The context uses React useState with Set for efficient error collection management and automatic re-rendering on updates.
Usage
Wrap your application with NotificationCenterProvider and use the useNotificationCenter hook to add, remove, and display errors throughout the UI.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/library/pages/root/context/notificationCenter.tsx
Signature
export default function NotificationCenterProvider({
children
}: {
children: ReactNode
}): JSX.Element
export function useNotificationCenter(): NotificationCenter
export interface NotificationCenter {
errors: Set<ErrorIDE>
addError: (
key: ErrorKey,
error: ApiExceptionPayload
) => {
removeError: () => void
error: ErrorIDE
}
removeError: (error: ErrorIDE | ErrorKey) => void
clearErrors: () => void
}
export interface ErrorIDE extends ApiExceptionPayload {
key: ErrorKey
id: ID
solution?: string
tip?: string
}
export const EnumErrorKey = {
Internal: 'internal',
API: 'api',
General: 'general',
RunPlan: 'run-plan',
ApplyPlan: 'apply-plan',
CancelPlan: 'cancel-plan',
Environments: 'environments',
Models: 'models',
Fetchdf: 'fetchdf',
EvaluateModel: 'evaluate-model',
RenderQuery: 'render-query',
ColumnLineage: 'column-lineage',
ModelLineage: 'model-lineage',
Meta: 'meta',
Modules: 'modules',
FileExplorer: 'file-explorer',
Table: 'table',
TableDiff: 'table-diff',
SaveFile: 'save-file',
} as const
Import
import NotificationCenterProvider, {
useNotificationCenter,
EnumErrorKey,
type ErrorIDE
} from '@library/pages/root/context/notificationCenter'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| key | ErrorKey | Yes | Error category from EnumErrorKey |
| error | ApiExceptionPayload | Yes | Error details from API or internal source |
Outputs
| Property | Type | Description |
|---|---|---|
| errors | Set<ErrorIDE> | Current collection of errors |
| addError | Function | Adds error and returns cleanup function |
| removeError | Function | Removes error by object or key |
| clearErrors | Function | Removes all errors |
Usage Examples
// Application setup
import NotificationCenterProvider from './context/notificationCenter'
function App() {
return (
<NotificationCenterProvider>
<YourApp />
</NotificationCenterProvider>
)
}
// Using in components
import { useNotificationCenter, EnumErrorKey } from './context/notificationCenter'
function MyComponent() {
const { errors, addError, removeError, clearErrors } = useNotificationCenter()
// Add error with automatic cleanup
async function fetchData() {
try {
const response = await api.getData()
} catch (error) {
const { removeError, error: errorObj } = addError(
EnumErrorKey.API,
{
status: 'error',
message: 'Failed to fetch data',
description: error.message,
timestamp: Date.now(),
type: 'ApiError',
origin: 'MyComponent',
trigger: 'fetchData'
}
)
// Auto-remove after 5 seconds
setTimeout(() => removeError(), 5000)
}
}
// Display errors
return (
<div>
{Array.from(errors).map(error => (
<div key={error.id}>
<h4>{error.key}</h4>
<p>{error.message}</p>
<button onClick={() => removeError(error)}>Dismiss</button>
</div>
))}
{errors.size > 0 && (
<button onClick={clearErrors}>Clear All</button>
)}
</div>
)
}
// Error categories
EnumErrorKey.API // API communication errors
EnumErrorKey.RunPlan // Plan execution errors
EnumErrorKey.ApplyPlan // Plan application errors
EnumErrorKey.CancelPlan // Plan cancellation errors
EnumErrorKey.Models // Model loading errors
EnumErrorKey.FileExplorer // File system errors
EnumErrorKey.ColumnLineage // Lineage computation errors
EnumErrorKey.SaveFile // File save errors
// Remove by key (removes all errors with that key)
removeError(EnumErrorKey.ColumnLineage)
// Remove specific error
const error = Array.from(errors)[0]
removeError(error)
// Error IDE structure
interface ErrorIDE {
id: string // Unique ID (generated)
key: ErrorKey // Category
status: string // Error status
timestamp: number // When error occurred
message: string // Primary error message
description?: string // Detailed description
type?: string // Error type (e.g., "ApiError")
origin?: string // Where error originated
trigger?: string // What triggered the error
stack?: string // Stack trace
traceback?: string // Python traceback (if applicable)
solution?: string // Suggested solution
tip?: string // User tip
}
// Integration with error page
function handleError(error: ErrorIDE): void {
addError(EnumErrorKey.ColumnLineage, error)
}
// Lineage error handling
<LineageFlowProvider
handleError={handleError}
>
{/* Components */}
</LineageFlowProvider>
Error Categories
| Key | Usage |
|---|---|
| Internal | Internal application errors |
| API | API communication failures |
| General | Uncategorized errors |
| RunPlan | Plan execution failures |
| ApplyPlan | Plan application failures |
| CancelPlan | Plan cancellation failures |
| Environments | Environment management errors |
| Models | Model loading/parsing errors |
| Fetchdf | DataFrame fetch errors |
| EvaluateModel | Model evaluation errors |
| RenderQuery | Query rendering errors |
| ColumnLineage | Column lineage computation errors |
| ModelLineage | Model lineage computation errors |
| Meta | Metadata errors |
| Modules | Module loading errors |
| FileExplorer | File system operation errors |
| Table | Table operation errors |
| TableDiff | Table diff computation errors |
| SaveFile | File save operation errors |
Design Patterns
Automatic Cleanup
The addError() method returns a removeError function bound to the specific error, enabling easy cleanup:
const { removeError, error } = addError(key, errorData)
// Later...
removeError() // Removes this specific error
Bulk Operations
Remove all errors of a specific category:
removeError(EnumErrorKey.ColumnLineage)
// Removes ALL column lineage errors
Set-based Storage
Using Set instead of Array provides:
- Automatic deduplication
- Efficient add/remove operations
- Preserves insertion order
- React re-renders on Set updates