v1.51.0 — Larawag
Larawag — Notification subsystem refinement
A five-part refinement of the core notification subsystem. Mostly additive, with two deliberate breaking changes in channel registration/dispatch — see Upgrade Notes.
✨ Highlights
- Real in-app
databasechannel.DatabaseChannelis registered by default, so the framework's default['database']channel resolves end-to-end instead of failing as
channel_not_found. It's an acknowledge-only channel —NotificationServicestill owns the notification and delivery records — and its availability tracks thenotifications
persistence capability. - Dispatch-time channel validation. Channel names are no longer validated against a hardcoded list at construction; they're normalized structurally (trimmed, de-duplicated,
non-empty, case preserved) and unknown channels surface at dispatch viachannel_not_found/channel_unavailable. TheChannelManagerregistry is the single source of
truth — custom channels work without core changes. - Optional, safe persistence (
NOTIFICATIONS_DATABASE_STORE=false). NewNotificationStoreInterface;NotificationRepositoryimplements it, and aNullNotificationStore
binds when the capability is off. Reads return empty/null/zero, transient writes no-op, and durability-implying operations throwNotificationPersistenceDisabledException
rather than silently losing state. - Injectable async-queue dispatch.
NotificationQueueDispatcherInterface(defaultQueueManagerNotificationDispatcher) abstracts async dispatch sosend()never requires
a queue and queueing stays unit-testable. - Structured channel results. Channels may opt into
sendNotification(): NotificationResult(provider message id, error code/message, retryability, latency) via
RichNotificationChannel; the dispatcher prefers it and falls back to adapting legacysend(): bool. - Extension-driven channel registration. Channels/hooks register through
ServiceProvider::boot()viaregisterNotificationChannel()/registerNotificationExtension()—
one path, no per-job glue.
⚠️ Upgrade Notes (breaking)
ChannelManagerrename (no aliases):getAvailableChannels()→getRegisteredChannelNames(); for available-only names use the newgetActiveChannelNames().
getActiveChannels()(objects) is unchanged.- Notification jobs/commands require an
ApplicationContext:DispatchNotificationChannels,SendNotification,ProcessRetriesCommand,NotificationRetryTaskthrow
NotificationContextRequiredExceptionif constructed without a context. The queue worker and console kernel already provide one. - No hardcoded
EmailNotificationprovider: channel packages must register from theirServiceProvider::boot(). - Retry config key moved:
emailnotification.*→ channel-agnosticnotifications.retry. - No new env vars, no migrations. The
notificationscapability default staystrue.
composer update glueful/framework