[2.5.0] - Storage & Queue Overhaul
Added
- BullMQ event worker — replaced the custom Postgres+Redis polling event system with BullMQ. All event handlers are now static
HandlerMapobjects dispatched by a BullMQ worker. In development the worker runs in-process automatically; in production it runs as a separate process viabun run worker. Controlled by theEMBERLY_RUN_EVENT_WORKERenvironment variable (true/false/ unset). - Bull Board queue monitor — admin queue dashboard available at
/api/admin/queues. Requires an active admin session. Built with a custom Next.js App Router adapter for@bull-board/api— no custom server or external process needed. Displays live job counts, retry/promote/clean controls, job payloads, logs, and metrics for theemberly-eventsqueue. - Standalone worker entry point —
scripts/worker.tscan be run as a dedicated process (bun run worker) for production deployments that want a separate worker process, Docker sidecar, or systemd service. - Deterministic file-expiry job IDs — file expiration jobs use the stable ID
file-expiry-<fileId>so they can be cancelled or inspected directly via BullMQ's job store.cancelFileExpirationandgetFileExpirationInfouse these IDs instead of querying a PostgresEventHandlertable. - Periodic storage sync via BullMQ —
storage.sync-bucketsis now a recurring BullMQ job (repeat: { pattern: '0 * * * *' }) scheduled at startup rather than through the old event system. - Linode Object Storage provider — new
LinodeStorageProviderinpackages/lib/storage/providers/linode.tsimplements the Linode Object Storage management API (cluster listing, bucket creation/deletion, key management). Fully integrated with theObjectStoragePoolmodel and admin provisioning flow. - OVHcloud Object Storage provider — new
OVHcloudStorageProviderinpackages/lib/storage/providers/ovhcloud.tsimplements the OVHcloud Public Cloud Object Storage API (project listing, region listing, S3 credential management). Integrated withObjectStoragePooland admin provisioning flow. - Admin pool manager UI — Linode —
packages/components/admin/settings/linode-pool-manager.tsxprovides a full CRUD interface for Linode Object Storage pools: list clusters, create/delete pools, view credentials. - Admin pool manager UI — OVHcloud —
packages/components/admin/settings/ovhcloud-pool-manager.tsxprovides a full CRUD interface for OVHcloud Object Storage pools. - Linode admin API routes —
POST /api/admin/storage/linode(create pool) andDELETE /api/admin/storage/linode/[id](delete pool). - OVHcloud admin API routes —
POST /api/admin/storage/ovhcloud(create pool) andDELETE /api/admin/storage/ovhcloud/[id](delete pool). ObjectStoragePoolPrisma migration — unified storage pool model supportingvultr,linode, andovhcloudproviders. ReplacesVultrObjectStorageas the single table for all provisioned storage pools. Provider-specific metadata stored asJson(clusterIdfor Vultr,keyId + linodeClusterIdfor Linode,projectId + regionName + credentialAccessfor OVHcloud).
Fixed
- Bucket provisioning — corrected key mapping and credential lookup issues that caused provisioning to fail for newly created pools.
- Storage key issues — fixed S3 key derivation errors that caused reads and deletes to target the wrong object on certain pool configurations.
Changed
- Event handler pattern — all handler files now export a
HandlerMapstatic object instead of callingevents.on()at registration time. Theevents.emit()call signature is unchanged across all 31+ call sites — the compat shim inevents/index.tsmaintains backward compatibility. EventHandlermodel removed — theEventHandlerPrisma model (used by the old polling worker) has been dropped. Apply withbun run db:migrate.- Redis is now required — previously optional for some configurations; BullMQ and rate limiting both require a live Redis connection. See README Event Worker for setup.
- Vultr instance manager — updated to work with the unified
ObjectStoragePoolmodel. - Settings manager — admin settings panel updated to include Linode and OVHcloud pool manager tabs.
What's Changed
- Dev by @CodeMeAPixel in #108
- Dev by @CodeMeAPixel in #109
- Dev by @CodeMeAPixel in #110
- Dev by @CodeMeAPixel in #111
- Dev by @CodeMeAPixel in #112
Full Changelog: v2.4.7...2.5.0