the browser-facing portion of osu!
at master 5.1 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Console\Commands; 7 8use App\Libraries\Elasticsearch\Es; 9use App\Libraries\Elasticsearch\Indexing; 10use App\Models\ArtistTrack; 11use App\Models\Beatmapset; 12use App\Models\Forum\Post; 13use App\Models\User; 14use Illuminate\Console\Command; 15 16class EsIndexDocuments extends Command 17{ 18 const ALLOWED_TYPES = [ 19 'artist_tracks' => [ArtistTrack::class], 20 'beatmapsets' => [Beatmapset::class], 21 'posts' => [Post::class], 22 'users' => [User::class], 23 ]; 24 25 /** 26 * The name and signature of the console command. 27 * 28 * @var string 29 */ 30 protected $signature = 'es:index-documents {--types=} {--inplace} {--cleanup}'; 31 32 /** 33 * The console command description. 34 * 35 * @var string 36 */ 37 protected $description = 'Indexes documents into Elasticsearch.'; 38 39 protected $cleanup; 40 protected $inplace; 41 protected $groups; 42 43 /** 44 * Execute the console command. 45 * 46 * @return mixed 47 */ 48 public function handle() 49 { 50 $this->readOptions(); 51 52 $oldIndices = []; 53 foreach ($this->groups as $name) { 54 $type = static::ALLOWED_TYPES[$name][0]; 55 $oldIndices[] = Indexing::getOldIndices($type::esIndexName()); 56 } 57 58 $oldIndices = array_flatten($oldIndices); 59 60 $continue = $this->starterMessage($oldIndices); 61 if (!$continue) { 62 $this->error('User aborted!'); 63 return; 64 } 65 66 $start = time(); 67 68 foreach ($this->groups as $name) { 69 $this->indexGroup($name); 70 } 71 72 $this->finish($oldIndices); 73 $this->warn("\nIndexing completed in ".(time() - $start).'s'); 74 } 75 76 protected function finish(array $oldIndices) 77 { 78 if (!$this->inplace && $this->cleanup) { 79 foreach ($oldIndices as $index) { 80 $this->warn("Removing '{$index}'..."); 81 Indexing::deleteIndex($index); 82 } 83 } 84 } 85 86 private function indexGroup($name) 87 { 88 $types = collect(static::ALLOWED_TYPES[$name]); 89 90 $allSame = $types->every(function ($type) use ($types) { 91 return $type::esIndexName() === $types->first()::esIndexName(); 92 }); 93 94 if (!$allSame) { 95 $this->error("All types in group {$name} must have the same index."); 96 97 return []; 98 } 99 100 $first = $types->first(); 101 $alias = $first::esIndexName(); 102 $indexName = $this->inplace ? $alias : $first::esTimestampedIndexName(); 103 $pretext = $this->inplace ? 'In-place indexing' : 'Indexing'; 104 105 foreach ($types as $type) { 106 $bar = $this->output->createProgressBar(); 107 108 $this->info("{$pretext} {$type} into {$indexName}"); 109 110 if (!$this->inplace && $type === $first) { 111 // create new index if the first type for this index, otherwise 112 // index in place. 113 $type::esIndexIntoNew(Es::CHUNK_SIZE, $indexName, function ($progress) use ($bar) { 114 $bar->setProgress($progress); 115 }); 116 } else { 117 $options = ['index' => $indexName]; 118 $type::esReindexAll(Es::CHUNK_SIZE, 0, $options, function ($progress) use ($bar) { 119 $bar->setProgress($progress); 120 }); 121 } 122 123 $bar->finish(); 124 $this->line("\n"); 125 } 126 127 if ($alias !== $indexName) { 128 $this->info("Aliasing {$alias} to {$indexName}"); 129 Indexing::updateAlias($alias, $indexName); 130 $this->line(''); 131 } 132 } 133 134 protected function readOptions() 135 { 136 $this->inplace = $this->option('inplace'); 137 $this->cleanup = $this->option('cleanup'); 138 139 if ($this->option('types')) { 140 $types = explode(',', $this->option('types')); 141 $this->groups = []; 142 foreach ($types as $type) { 143 if (array_key_exists($type, static::ALLOWED_TYPES)) { 144 $this->groups[] = $type; 145 } 146 } 147 } else { 148 $this->groups = array_keys(static::ALLOWED_TYPES); 149 } 150 } 151 152 protected function starterMessage(array $oldIndices) 153 { 154 if ($this->inplace) { 155 $this->warn('Running in-place reindex.'); 156 $confirmMessage = 'This will reindex in-place (schemas must match)'; 157 } else { 158 $this->warn('Running index transfer.'); 159 160 if ($this->cleanup) { 161 $this->warn( 162 "The following indices will be deleted on completion!\n" 163 .implode("\n", $oldIndices) 164 ); 165 } 166 167 $confirmMessage = 'This will create new indices'; 168 } 169 170 return $this->option('no-interaction') || $this->confirm("{$confirmMessage}, begin indexing?", true); 171 } 172}