Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 46
BaseCommand
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 10
210
0.00% covered (danger)
0.00%
0 / 46
 __construct
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getJsData
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 4
 launch
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 5
 executeFile
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 4
 createExecutor
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 process
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 12
 sendChunk
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 8
 normalizeChunk
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 disable
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 5
 js
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
1<?php
2
3namespace Qmp\Laravel\Deduplication\Console\Commands;
4
5use Illuminate\Support\Collection;
6
7
8use Qmp\Laravel\Deduplication\Models\SessionData;
9use Qmp\Laravel\ToolsLaravel\Traits\Timer;
10use MongoDB\Driver\WriteConcern;
11use Qmp\Laravel\MongoJsExecutor\Executor;
12
13abstract class BaseCommand extends TryCatchCommand
14{
15    use Timer;
16
17    /**
18     * The chunk size to send to mongo
19     */
20    const CHUNK_SIZE = 25000;
21
22    /**
23     * Undocumented variable
24     *
25     * @var array
26     */
27    protected $falseMessage = [
28        'id' => 0,
29        'message' => ''
30    ];
31
32    /**
33     * The aggreagtion result
34     *
35     * @var mixed
36     */
37    protected $aggregationResult;
38
39    /**
40     * The chunk collection that holds hashs
41     *
42     * @var \Illuminate\Support\Collection
43     */
44    protected $chunk;
45
46    /**
47     * The count of all hashs
48     *
49     * @var integer
50     */
51    protected $count = 0;
52
53    /**
54     * If there is no process after aggregation.
55     *
56     * @var boolean
57     */
58    protected $onlyAggregation = false;
59
60    /**
61     * Undocumented variable
62     *
63     * @var array
64     */
65    protected $jsFiles = [];
66
67    /**
68     * Undocumented variable
69     *
70     * @var array
71     */
72    protected $extraJsData = [];
73
74    /**
75     * Undocumented variable
76     *
77     * @var array
78     */
79    protected $executorOptions = ['allowDiskUse' => true];
80
81    /**
82     * Create a new command instance.
83     *
84     * @return void
85     */
86    public function __construct()
87    {
88        parent::__construct();
89        $this->chunk = collect();
90    }
91
92
93    /**
94     * Undocumented function
95     *
96     * @return void
97     */
98    protected function getJsData()
99    {
100        return array_merge([
101            'sessionId' => $this->argument('sessionId'),
102            'outCollection' => 'sessions_data_temp_' .  $this->argument('sessionId')
103        ], $this->extraJsData);
104    }
105
106
107    /**
108     * The entry point of the command. 
109     * Aggregate and process
110     *
111     * @return void
112     */
113    protected function launch()
114    {
115        $this->info($this->falseMessage['message']);
116
117        foreach ($this->jsFiles as $key => $file) {
118            $this->info("Starting aggregation : $file");
119            $this->executeFile($file)->process();
120        }
121
122        //$this->info("TOTAL : $this->count duplicates found !");
123    }
124
125    /**
126     * Undocumented function
127     *
128     * @param [type] $file
129     * @return self
130     */
131    protected function executeFile($file): self
132    {
133        $this->startTimer('pass');
134        $this->aggregationResult = $this->createExecutor($file, $this->argument('sessionId'))->execute($this->executorOptions);
135        $this->info('Aggregation time : ' . $this->getTimer('pass'));
136        return $this;
137    }
138
139
140    /**
141     * Undocumented function
142     *
143     * @param [type] $file
144     * @return void
145     */
146    protected function createExecutor($file, $collectionSuffix = null)
147    {
148        $executor = Executor::fromJs($this->js($file), $collectionSuffix);
149        $executor->withData($this->getJsData());
150
151        return $executor;
152    }
153
154    /**
155     * Process the aggregation result
156     *
157     * @return void
158     */
159    protected function process(): void
160    {
161        if (!$this->onlyAggregation) {
162            if ($this->aggregationResult && $this->aggregationResult->count() > 0) {
163                $this->startTimer('processMain');
164                $count = 0;
165
166                $this->aggregationResult->chunk(self::CHUNK_SIZE)->each(function ($chunk) {
167                    $this->sendChunk($chunk);
168                });
169
170                $count = $this->aggregationResult->count();
171                $this->info($count . " duplicates found !");
172                $this->info('Php execution : ' . $this->getTimer('processMain'));
173            } else {
174                $this->info("No duplicates found !");
175            }
176        }
177    }
178
179
180    /**
181     * Disable the current chunk collection
182     *
183     * @param Collection $duplicate
184     * @return void
185     */
186    protected function sendChunk(Collection $duplicate): void
187    {
188        $duplicate = $this->normalizeChunk($duplicate);
189
190        $this->startTimer('sendChunk');
191        $this->info('sending chunk : ' . $duplicate->count() . ' entries');
192
193        $this->disable($duplicate->toArray());
194        $this->count += $duplicate->count();
195        $this->chunk = collect();
196
197        $this->info('Chunk sent in ' . $this->getTimer('sendChunk'));
198    }
199
200    /**
201     * Undocumented function
202     *
203     * @param Collection $chunk
204     * @return Collection
205     */
206    protected function normalizeChunk(Collection $chunk): Collection
207    {
208        return $chunk->pluck('duplicates');
209    }
210
211
212    // /**
213    //  * Add an array of hash to the chunk
214    //  *
215    //  * @param array $array
216    //  * @return void
217    //  */
218    // protected function addToChunk(array $array = []): void
219    // {
220    //     $this->chunk = $this->chunk->merge($array);
221
222    //     if ($this->chunk->count() >= self::CHUNK_SIZE) {
223    //         $this->sendChunk($this->chunk);
224    //     }
225    // }
226
227    /**
228     * Disable hash in mongo
229     *
230     * @param array $ids
231     * @return void
232     */
233    protected function disable(array $ids): void
234    {
235        SessionData::whereIn('_id', $ids)->update(
236            [
237                'active' => false,
238                'description_dedup_false' => $this->falseMessage['id']
239            ],
240            [
241                "writeConcern" => new WriteConcern(0)
242            ]
243        );
244    }
245
246    /**
247     * Undocumented function
248     *
249     * @param [type] $name
250     * @return string
251     */
252    protected function js($name): string
253    {
254        return realpath(__DIR__ . "/../../database/query/$name.js");
255    }
256}