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

daycry / jobs / 24850441053

23 Apr 2026 05:54PM UTC coverage: 52.404% (-1.5%) from 53.938%
24850441053

push

github

daycry
Fixes

104 of 219 new or added lines in 42 files covered. (47.49%)

14 existing lines in 9 files now uncovered.

1210 of 2309 relevant lines covered (52.4%)

4.37 hits per line

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

69.64
/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 string $name;
29

30
    public function __construct()
31
    {
32
    }
2✔
33

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

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

91
        return true;
2✔
92
    }
93

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

99
        if (empty($log)) {
×
100
            return '--';
×
101
        }
102

103
        return Time::parse($log->start_at);
×
104
    }
105

106
    public function setPath(string $name): self
107
    {
108
        $this->name = $name;
2✔
109

110
        return $this;
2✔
111
    }
112

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

126
        // Rows already have columns; data JSON retained for full fidelity
127
        return $logs;
2✔
128
    }
129
}
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