Completed
Pull Request — master (#39)
by Anton
01:26
created

JobFileRepository::changeJobExitCode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
c 0
b 0
f 0
rs 9.8333
cc 3
nc 3
nop 2
1
<?php
2
3
/*
4
 * This file is part of Laravel Paket.
5
 *
6
 * (c) Anton Komarev <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cog\Laravel\Paket\Job\Repositories;
15
16
use Cog\Contracts\Paket\Job\Entities\Job as JobContract;
17
use Cog\Contracts\Paket\Job\Repositories\Job as JobRepositoryContract;
18
use Cog\Laravel\Paket\Job\Entities\Job;
19
use Illuminate\Contracts\Filesystem\FileNotFoundException;
20
use Illuminate\Filesystem\Filesystem;
21
use RuntimeException;
22
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
23
24
final class JobFileRepository implements JobRepositoryContract
25
{
26
    /**
27
     * The filesystem instance.
28
     *
29
     * @var \Illuminate\Filesystem\Filesystem
30
     */
31
    private $files;
32
33
    /**
34
     * The path to store jobs data.
35
     *
36
     * @var string
37
     */
38
    private $storagePath;
39
40
    /**
41
     * Create a new job file repository instance.
42
     *
43
     * @param \Illuminate\Filesystem\Filesystem $files
44
     * @param string $storagePath
45
     */
46
    public function __construct(Filesystem $files, string $storagePath)
47
    {
48
        $this->files = $files;
49
        $this->storagePath = $storagePath;
50
    }
51
52
    public function all(): iterable
53
    {
54
        $index = $this->getIndex();
55
56
        $jobs = [];
57
        foreach ($index as $job) {
58
            $jobs[] = Job::fromArray($job);
59
        }
60
61
        return $jobs;
62
    }
63
64
    public function getById(string $id): JobContract
65
    {
66
        $index = $this->getIndex();
67
68
        foreach ($index as $job) {
69
            if ($job['id'] === $id) {
70
                $job['process']['output'] = $this->getJobProcessOutput($job['id']);
71
72
                return Job::fromArray($job);
73
            }
74
        }
75
76
        throw new NotFoundHttpException("Job with id `{$id}` not found.");
77
    }
78
79
    public function deleteById(string $id): void
80
    {
81
        $index = $this->getIndex();
82
83
        foreach ($index as $key => $job) {
84
            if ($job['id'] === $id) {
85
                $jobKey = $key;
86
                break;
87
            }
88
        }
89
90
        if (!isset($jobKey)) {
91
            throw new NotFoundHttpException("Job with id `{$id}` not found.");
92
        }
93
94
        unset($index[$jobKey]);
95
        $index = array_values($index);
96
97
        $this->putIndex($index);
98
    }
99
100
    public function store(JobContract $job): void
101
    {
102
        $index = $this->getIndex();
103
104
        $index[] = $job->toArray();
105
106
        $this->putIndex($index);
107
    }
108
109
    public function changeJobStatus(JobContract $job, string $statusName): void
110
    {
111
        $names = [
112
            'Pending',
113
            'Running',
114
            'Success',
115
            'Failed',
116
        ];
117
118
        if (!in_array($statusName, $names)) {
119
            // TODO: Throw custom exception
120
            throw new RuntimeException('Unknown job status');
121
        }
122
123
        $index = $this->getIndex();
124
125
        foreach ($index as $key => $record) {
126
            if ($record['id'] === $job->getId()) {
127
                $index[$key]['status'] = $statusName;
128
                break;
129
            }
130
        }
131
132
        $this->putIndex($index);
133
    }
134
135
    public function changeJobExitCode(JobContract $job, int $exitCode): void
136
    {
137
        $index = $this->getIndex();
138
139
        foreach ($index as $key => $record) {
140
            if ($record['id'] === $job->getId()) {
141
                $index[$key]['process']['exitCode'] = $exitCode;
142
                break;
143
            }
144
        }
145
146
        $this->putIndex($index);
147
    }
148
149
    private function getIndex(): array
150
    {
151
        try {
152
            return json_decode($this->files->get($this->getIndexFilePath(), $isLocked = true), true);
153
        } catch (FileNotFoundException $exception) {
154
            return [];
155
        }
156
    }
157
158
    private function putIndex(iterable $index): void
159
    {
160
        $this->files->put($this->getIndexFilePath(), json_encode($index));
161
    }
162
163
    private function getJobProcessOutput(string $jobId): string
164
    {
165
        $path = sprintf('%s/jobs/%s.log', $this->storagePath, $jobId);
166
167
        try {
168
            return $this->files->get($path);
169
        } catch (FileNotFoundException $exception) {
170
            return '';
171
        }
172
    }
173
174
    private function getIndexFilePath(): string
175
    {
176
        return $this->storagePath . '/jobs.json';
177
    }
178
}
179