• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daycry / jobs / 20486598223

19 Nov 2025 03:37PM UTC coverage: 62.616% (+0.1%) from 62.5%
20486598223

push

github

daycry
- Improvements

22 of 25 new or added lines in 12 files covered. (88.0%)

2 existing lines in 1 file now uncovered.

1149 of 1835 relevant lines covered (62.62%)

4.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.11
/src/Libraries/InstrumentedQueueDecorator.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of Daycry Queues.
7
 *
8
 * (c) Daycry <daycry9@proton.me>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace Daycry\Jobs\Libraries;
15

16
use Daycry\Jobs\Interfaces\QueueInterface;
17
use Daycry\Jobs\Interfaces\WorkerInterface;
18
use Daycry\Jobs\Job;
19
use Daycry\Jobs\Metrics\MetricsCollectorInterface;
20
use InvalidArgumentException;
21
use Throwable;
22

23
/**
24
 * Decorator transparente que instrumenta cualquier QueueInterface con métricas.
25
 *
26
 * Métricas capturadas:
27
 *  - queue_enqueue_total: Contador de jobs enqueued
28
 *  - queue_fetch_total: Contador de watch() exitosos
29
 *  - queue_fetch_empty_total: Contador de watch() sin jobs
30
 *  - queue_ack_total: Contador de removeJob success
31
 *  - queue_nack_total: Contador de removeJob con recreate
32
 *  - queue_enqueue_duration_seconds: Histograma de latencia de enqueue
33
 *  - queue_fetch_duration_seconds: Histograma de latencia de watch
34
 *
35
 * Uso:
36
 *   $redis = new RedisQueue();
37
 *   $instrumented = new InstrumentedQueueDecorator($redis, $metricsCollector, 'redis');
38
 *   $id = $instrumented->enqueue($data); // métricas capturadas automáticamente
39
 */
40
class InstrumentedQueueDecorator implements QueueInterface, WorkerInterface
41
{
42
    private QueueInterface $decorated;
43
    private MetricsCollectorInterface $metrics;
44
    private string $backendName;
45

46
    public function __construct(
47
        QueueInterface $decorated,
48
        MetricsCollectorInterface $metrics,
49
        string $backendName,
50
    ) {
51
        // Validar que también implementa WorkerInterface
52
        if (! $decorated instanceof WorkerInterface) {
9✔
NEW
53
            throw new InvalidArgumentException('Decorated queue must implement WorkerInterface');
×
54
        }
55
        $this->decorated   = $decorated;
9✔
56
        $this->metrics     = $metrics;
9✔
57
        $this->backendName = $backendName;
9✔
58
    }
59

60
    public function enqueue(object $data): string
61
    {
62
        $start = microtime(true);
3✔
63
        $queue = $data->queue ?? 'default';
3✔
64

65
        try {
66
            $id = $this->decorated->enqueue($data);
3✔
67
            $this->metrics->increment('queue_enqueue_total', 1, [
2✔
68
                'backend' => $this->backendName,
2✔
69
                'queue'   => $queue,
2✔
70
                'status'  => 'success',
2✔
71
            ]);
2✔
72

73
            return $id;
2✔
74
        } catch (Throwable $e) {
1✔
75
            $this->metrics->increment('queue_enqueue_total', 1, [
1✔
76
                'backend' => $this->backendName,
1✔
77
                'queue'   => $queue,
1✔
78
                'status'  => 'error',
1✔
79
            ]);
1✔
80

81
            throw $e;
1✔
82
        } finally {
83
            $duration = microtime(true) - $start;
3✔
84
            $this->metrics->observe('queue_enqueue_duration_seconds', $duration, [
3✔
85
                'backend' => $this->backendName,
3✔
86
                'queue'   => $queue,
3✔
87
            ]);
3✔
88
        }
89
    }
90

91
    public function watch(string $queue)
92
    {
93
        $start = microtime(true);
3✔
94

95
        try {
96
            /** @var WorkerInterface $worker */
97
            $worker   = $this->decorated;
3✔
98
            $envelope = $worker->watch($queue);
3✔
99

100
            if ($envelope !== null) {
3✔
101
                $this->metrics->increment('queue_fetch_total', 1, [
1✔
102
                    'backend' => $this->backendName,
1✔
103
                    'queue'   => $queue,
1✔
104
                ]);
1✔
105
            } else {
106
                $this->metrics->increment('queue_fetch_empty_total', 1, [
2✔
107
                    'backend' => $this->backendName,
2✔
108
                    'queue'   => $queue,
2✔
109
                ]);
2✔
110
            }
111

112
            return $envelope;
3✔
113
        } finally {
114
            $duration = microtime(true) - $start;
3✔
115
            $this->metrics->observe('queue_fetch_duration_seconds', $duration, [
3✔
116
                'backend' => $this->backendName,
3✔
117
                'queue'   => $queue,
3✔
118
            ]);
3✔
119
        }
120
    }
121

122
    public function removeJob(Job $job, bool $recreate = false): bool
123
    {
124
        /** @var WorkerInterface $worker */
125
        $worker = $this->decorated;
2✔
126
        $result = $worker->removeJob($job, $recreate);
2✔
127

128
        $metricName = $recreate ? 'queue_nack_total' : 'queue_ack_total';
2✔
129
        $this->metrics->increment($metricName, 1, [
2✔
130
            'backend' => $this->backendName,
2✔
131
            'queue'   => $job->getQueue() ?? 'unknown',
2✔
132
        ]);
2✔
133

134
        return $result;
2✔
135
    }
136

137
    /**
138
     * Acceso al backend decorado (útil para operaciones especializadas).
139
     */
140
    public function getDecorated(): QueueInterface
141
    {
142
        return $this->decorated;
1✔
143
    }
144
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc