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

daycry / jobs / 20370592183

19 Nov 2025 03:37PM UTC coverage: 60.163% (-2.3%) from 62.5%
20370592183

push

github

daycry
- Improvements

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

46 existing lines in 3 files now uncovered.

1104 of 1835 relevant lines covered (60.16%)

4.62 hits per line

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

0.0
/src/Loggers/DatabaseHandler.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\Loggers;
15

16
use CodeIgniter\I18n\Time;
17
use CodeIgniter\Log\Handlers\BaseHandler;
18
use Daycry\Jobs\Config\Jobs as JobsConfig;
19
use Daycry\Jobs\Models\JobsLogModel;
20

21
/**
22
 * Database-backed job execution history handler.
23
 * Persists each execution row into jobs log table defined by JobsLogModel.
24
 * Enforces maxLogsPerJob by deleting oldest rows beyond the limit.
25
 */
26
class DatabaseHandler extends BaseHandler
27
{
28
    private $table;
29
    private string $name;
30

31
    public function __construct(array $config = [])
32
    {
UNCOV
33
    }
×
34

35
    public function handle($level, $message): bool
36
    {
UNCOV
37
        $logModel = model(JobsLogModel::class);
×
38
        /** @var JobsConfig config */
UNCOV
39
        $config  = config('Jobs');
×
UNCOV
40
        $decoded = json_decode($message, true);
×
UNCOV
41
        if (! is_array($decoded)) {
×
42
            return true; // ignore malformed
×
43
        }
44
        // Fallback de nombre si no se definió vía setPath
UNCOV
45
        if (empty($this->name) && ! empty($decoded['name'])) {
×
46
            $this->name = (string) $decoded['name'];
×
47
        }
48

49
        // Pruning eficiente: contar y borrar excedente sin cargar todo
UNCOV
50
        if ($config->maxLogsPerJob && ! empty($this->name)) {
×
UNCOV
51
            $count = $logModel->where('name', $this->name)->countAllResults();
×
UNCOV
52
            if ($count >= $config->maxLogsPerJob) {
×
53
                // Borrar los más antiguos dejando (maxLogsPerJob - 1) espacio para el nuevo
54
                $excess = ($count - $config->maxLogsPerJob) + 1;
×
55
                if ($excess > 0) {
×
56
                    // Obtener IDs antiguos a eliminar
57
                    $oldIds = $logModel->select('id')
×
58
                        ->where('name', $this->name)
×
59
                        ->orderBy('id', 'ASC')
×
60
                        ->limit($excess)
×
61
                        ->findColumn('id');
×
62
                    if ($oldIds) {
×
63
                        foreach ($oldIds as $oid) {
×
64
                            $logModel->delete($oid);
×
65
                        }
66
                    }
67
                }
68
            }
69
        }
UNCOV
70
        $status = isset($decoded['error']) && $decoded['error'] !== null ? 'ERROR' : 'OK';
×
UNCOV
71
        $row    = [
×
UNCOV
72
            'name'          => $decoded['name'] ?? null,
×
UNCOV
73
            'job'           => $decoded['job'] ?? null,
×
UNCOV
74
            'executionId'   => $decoded['executionId'] ?? null,
×
UNCOV
75
            'attempt'       => $decoded['attempt'] ?? null,
×
UNCOV
76
            'queue'         => $decoded['queue'] ?? null,
×
UNCOV
77
            'source'        => $decoded['source'] ?? null,
×
UNCOV
78
            'retryStrategy' => $decoded['retryStrategy'] ?? null,
×
UNCOV
79
            'payload'       => $decoded['payload'] ?? null,
×
UNCOV
80
            'payloadHash'   => $decoded['payloadHash'] ?? null,
×
UNCOV
81
            'environment'   => $decoded['environment'] ?? null,
×
UNCOV
82
            'output'        => $decoded['output'] ?? null,
×
UNCOV
83
            'outputLength'  => $decoded['outputLength'] ?? null,
×
UNCOV
84
            'error'         => $decoded['error'] ?? null,
×
UNCOV
85
            'status'        => $status,
×
UNCOV
86
            'start_at'      => $decoded['start_at'] ?? null,
×
UNCOV
87
            'end_at'        => $decoded['end_at'] ?? null,
×
UNCOV
88
            'duration'      => $decoded['duration'] ?? null,
×
UNCOV
89
            'test_time'     => $decoded['test_time'] ?? null,
×
UNCOV
90
            'data'          => json_encode($decoded, JSON_UNESCAPED_UNICODE),
×
UNCOV
91
        ];
×
UNCOV
92
        $logModel->insert($row);
×
93

UNCOV
94
        return true;
×
95
    }
96

97
    public function lastRun(string $name): string|Time
98
    {
99
        $logModel = model(JobsLogModel::class);
×
100
        $log      = $logModel->where('name', $name)->orderBy('id', 'DESC')->first();
×
101

102
        if (empty($log)) {
×
103
            return '--';
×
104
        }
105

106
        return Time::parse($log->start_at);
×
107
    }
108

109
    public function setPath(string $name): self
110
    {
UNCOV
111
        $this->name = $name;
×
112

UNCOV
113
        return $this;
×
114
    }
115

116
    /**
117
     * Returns an array of recent executions for a job from database.
118
     *
119
     * @return array<int, object>
120
     */
121
    public function history(string $name, int $limit = 10): array
122
    {
UNCOV
123
        $logModel = model(JobsLogModel::class);
×
UNCOV
124
        $logs     = $logModel->where('name', $name)->orderBy('id', 'DESC')->limit($limit)->find();
×
UNCOV
125
        if (! is_array($logs)) {
×
126
            return [];
×
127
        }
128

129
        // Rows already have columns; data JSON retained for full fidelity
UNCOV
130
        return $logs;
×
131
    }
132
}
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