Queue Simplification & Modernization - Migration Guide
Overview
The queue subsystem has been refactored to improve maintainability, testability, and observability. This guide summarizes the changes and provides migration steps.
Changes Summary
Phase 1-4: Core Simplifications (v2.0)
1. ID Generation (IdGeneratorInterface)
What: Centralized ID generation via
RandomIdGeneratorWhy: Testability, determinism, consistency across backends
Where:
BaseQueue::generateId(), all queue implementationsBC: No breaking changes (internal only)
2. JobEnvelope Factory (JobEnvelope::fromBackend())
What: Unified envelope creation with normalized metadata
Why: Reduces duplication, standardizes meta keys (
backend,rawId,status)Where: All
watch()methods in Redis, Database, Beanstalk, ServiceBusBC: Backward compatible (existing
fromDecoded()still works)
3. QueueManager (Registry/Factory)
What: Singleton registry for queue backend instances
Why: Eliminates scattered
new XxxQueue(), enables mocking, caches instancesUsage:
QueueManager::instance()->get('redis')or->getDefault()Where:
QueueRunCommand,EnqueuableTraitBC: Internal change, no API breakage
4. DelayResult, Priority
DelayResult: Value object for delay calculation (seconds + scheduledAt)
Priority: Enum for symbolic priorities (LOW/MEDIUM/HIGH → numeric)
Why: Eliminates 20+ lines of duplicated delay logic, prepares for advanced scheduling
Where:
BaseQueue::calculateDelay()returnsDelayResultBC: Fully compatible
Phase 5: Serialization & Observability
5. PayloadSerializer (JsonPayloadSerializer)
What: Centralized JSON serialization with schema versioning
Features:
Automatic
_schemaVersioninjectionMigration support for legacy payloads
Validation of required fields
Why: Future-proof schema evolution, centralized encoding/decoding
Where: All
enqueue()andwatch()methodsBC: Fully compatible (version field optional)
6. InstrumentedQueueDecorator
What: Transparent metrics wrapper for any queue backend
Metrics:
queue_enqueue_total(counter: success/error)queue_fetch_total/queue_fetch_empty_totalqueue_ack_total/queue_nack_totalqueue_enqueue_duration_seconds(histogram)queue_fetch_duration_seconds(histogram)
Usage:
new InstrumentedQueueDecorator($queue, $metrics, 'redis')Why: Unified observability without per-backend code changes
BC: Optional decorator, no breaking changes
Migration Steps
For Library Users
No action required for typical usage. All changes are backward compatible.
Optional Enhancements:
Enable Metrics Instrumentation:
use Daycry\Jobs\Libraries\QueueManager;
use Daycry\Jobs\Libraries\InstrumentedQueueDecorator;
use Daycry\Jobs\Metrics\Metrics;
$queue = QueueManager::instance()->get('redis');
$instrumented = new InstrumentedQueueDecorator($queue, Metrics::get(), 'redis');
// Use $instrumented instead of $queue
Schema Versioning (optional):
use Daycry\Jobs\Libraries\JsonPayloadSerializer;
$serializer = new JsonPayloadSerializer(schemaVersion: 2);
$queue->setSerializer($serializer);
Custom ID Generator (testing):
use Daycry\Jobs\Interfaces\IdGeneratorInterface;
class SequentialIdGenerator implements IdGeneratorInterface {
private int $counter = 0;
public function generate(int $bytes = 8, ?string $prefix = null): string {
return ($prefix ?? '') . '-' . ++$this->counter;
}
}
$queue->setIdGenerator(new SequentialIdGenerator());
For Contributors
Removed Code
RedisQueue::failedKey()– unused method removed (failed job tracking will be reimplemented)Direct
json_encode/json_decodein queue enqueue/watch – replaced with serializer
Behavior Changes
removeJob($job, $recreate = true)in all backends now re-enqueues directly to the same backend instance instead of calling$job->push()which could route to a different worker viaQueueManager. This ensures requeued jobs stay in the same queue backend (important for tests and multi-backend setups).
New Extension Points
PayloadSerializerInterface::migrate()– override for custom schema migrationsPriority::parse()– symbolic → numeric priority mappingQueueManager::register()– runtime worker registration
Testing
All 90 existing tests pass with the refactored code. New abstractions are validated through:
Existing queue cycle tests (Redis, Database, Beanstalk)
Envelope normalization tests
Services helper tests
Performance Impact
Positive: Singleton QueueManager caches instances (no repeated instantiation)
Neutral: Serializer adds ~5% overhead vs raw
json_encode(negligible)Positive: Delay calculation simplified (fewer branches)
Rollback
If issues arise, revert to previous version. No database schema changes; all changes are code-level.
Future Enhancements
Prepared groundwork for:
Ack/Nack settlement model (FetchedJob abstraction)
Delayed promotion interface standardization
Advanced priority scheduling
Payload schema versioning for smooth upgrades