AntWorker::collectIteration()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 48
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 48
rs 9.504
cc 3
nc 3
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Veslo project <https://github.com/symfony-doge/veslo>.
5
 *
6
 * (C) 2019 Pavel Petrov <[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
 * @license https://opensource.org/licenses/GPL-3.0 GPL-3.0
12
 */
13
14
declare(strict_types=1);
15
16
namespace Veslo\AnthillBundle\Vacancy\Collector;
17
18
use Closure;
19
use Psr\Log\LoggerInterface;
20
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
21
use Veslo\AnthillBundle\Dto\Vacancy\Collector\AcceptanceDto;
22
use Veslo\AnthillBundle\Dto\Vacancy\Parser\ParsedDto;
23
use Veslo\AnthillBundle\Vacancy\Creator;
24
use Veslo\AnthillBundle\Vacancy\DecisionInterface;
25
use Veslo\AppBundle\Workflow\Vacancy\PitInterface;
26
use Veslo\AppBundle\Workflow\Vacancy\Worker\Iteration;
27
use Veslo\AppBundle\Workflow\Vacancy\WorkerInterface;
28
29
/**
30
 * Collects dung (vacancies) from queue and persists in local storage
31
 *
32
 *              |     |
33
 *               \   /
34
 *                \_/
35
 *           __   /^\   __
36
 *          '  `. \_/ ,'  `
37
 *               \/ \/
38
 *          _,--./| |\.--._
39
 *       _,'   _.-\_/-._   `._
40
 *            |   / \   |
41
 *            |  /   \  |
42
 *           /   |   |   \
43
 *         -'    \___/    `-
44
 */
45
class AntWorker implements WorkerInterface
46
{
47
    /**
48
     * Logger as it is
49
     *
50
     * @var LoggerInterface
51
     */
52
    private $logger;
53
54
    /**
55
     * Converts an object into a set of arrays/scalars
56
     *
57
     * @var NormalizerInterface
58
     */
59
    private $normalizer;
60
61
    /**
62
     * Decision that should be checked for raw vacancy data if it can be collected or not
63
     *
64
     * @var DecisionInterface
65
     */
66
    private $decision;
67
68
    /**
69
     * Creates and persists a new vacancy instance in local storage
70
     *
71
     * @var Creator
72
     */
73
    private $vacancyCreator;
74
75
    /**
76
     * Storage for collected vacancy from website-provider
77
     * Destination place in which result of worker action will be persisted
78
     *
79
     * @var PitInterface
80
     */
81
    private $destination;
82
83
    /**
84
     * AntWorker constructor.
85
     *
86
     * @param LoggerInterface     $logger         Logger as it is
87
     * @param NormalizerInterface $normalizer     Converts an object into a set of arrays/scalars
88
     * @param DecisionInterface   $decision       Decision that should be applied to vacancy data for collecting
89
     * @param Creator             $vacancyCreator Creates and persists a new vacancy instance in local storage
90
     * @param PitInterface        $destination    Storage for collected vacancy from website-provider (workflow queue)
91
     */
92
    public function __construct(
93
        LoggerInterface $logger,
94
        NormalizerInterface $normalizer,
95
        DecisionInterface $decision,
96
        Creator $vacancyCreator,
97
        PitInterface $destination
98
    ) {
99
        $this->logger         = $logger;
100
        $this->normalizer     = $normalizer;
101
        $this->decision       = $decision;
102
        $this->vacancyCreator = $vacancyCreator;
103
        $this->destination    = $destination;
104
    }
105
106
    /**
107
     * Performs dung (vacancies) collecting from specified source {$iterations} times
108
     *
109
     * @param PitInterface $pit        Parsed vacancy data storage
110
     * @param int          $iterations Collecting iterations count, at least one expected
111
     *
112
     * @return int Successful collect iterations count
113
     */
114
    public function collect(PitInterface $pit, int $iterations = 1): int
115
    {
116
        $sourceName = get_class($pit);
117
118
        $this->logger->debug('Collecting started.', ['source' => $sourceName, 'iterations' => $iterations]);
119
120
        $iteration     = Closure::fromCallable([$this, 'collectIteration']);
121
        $iterationLoop = new Iteration\Loop($this, $iteration, 'An error has been occurred during vacancy collecting.');
122
123
        $successfulIterations = $iterationLoop->execute($pit, $iterations);
124
125
        $this->logger->debug(
126
            'Collecting completed.',
127
            [
128
                'source'     => $sourceName,
129
                'iterations' => $iterations,
130
                'successful' => $successfulIterations,
131
            ]
132
        );
133
134
        return $successfulIterations;
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140
    public function getLogger(): ?LoggerInterface
141
    {
142
        return $this->logger;
143
    }
144
145
    /**
146
     * Returns positive if vacancy is successfully collected
147
     * Builds and sends a payload to conveyor for further processing according to configured workflow
148
     *
149
     * @param PitInterface $pit Parsed vacancy data storage
150
     *
151
     * @return bool Positive, if vacancy data has been successfully collected, negative otherwise
152
     */
153
    private function collectIteration(PitInterface $pit): bool
154
    {
155
        $sourceName = get_class($pit);
156
157
        /** @var ParsedDto $scanResult */
158
        $scanResult = $pit->poll();
159
160
        if (!$scanResult instanceof ParsedDto) {
0 ignored issues
show
introduced by
$scanResult is always a sub-type of Veslo\AnthillBundle\Dto\Vacancy\Parser\ParsedDto.
Loading history...
161
            $this->logger->debug(
162
                'No more vacancies to collect.',
163
                [
164
                    'source' => $sourceName,
165
                    'input'  => gettype($scanResult),
166
                ]
167
            );
168
169
            return false;
170
        }
171
172
        $acceptance = new AcceptanceDto();
173
        $conditions = $this->decision->getConditions();
174
        $acceptance->setConditions($conditions);
175
        $acceptance->setData($scanResult);
176
177
        $acceptanceNormalized = $this->normalizer->normalize($acceptance);
178
179
        if (!$this->decision->isApplied($scanResult)) {
180
            $this->logger->debug('Vacancy rejected.', ['source' => $sourceName, 'denial' => $acceptanceNormalized]);
181
182
            return false;
183
        }
184
185
        $vacancy   = $this->vacancyCreator->createByParsedDto($scanResult);
186
        $vacancyId = $vacancy->getId();
187
        $acceptance->setVacancyId($vacancyId);
188
189
        $this->logger->info(
190
            'Vacancy accepted.',
191
            [
192
                'source'     => $sourceName,
193
                'vacancyId'  => $vacancyId,
194
                'acceptance' => $acceptanceNormalized,
195
            ]
196
        );
197
198
        $this->destination->offer($acceptance);
199
200
        return true;
201
    }
202
}
203