fix: Add idempotency checks to all Elasticsearch migrations
Problem: - Running elastic:rebuild --model=X failed when indexes already existed - Migrations threw "index already exists" errors in production - Command runs ALL migrations even when rebuilding single model Solution: - Added existence checks to all 12 migration files - Migrations now skip creation if index already exists - Safe to run multiple times without errors Changes: - Added ClientBuilder import to all migrations - Check indices()->exists() before creating - Return early if index already exists - Removed force drop from recurring_invoices migration Benefits: - Production-safe partial rebuilds - No "already exists" errors - Idempotent migrations - Clean log output Files modified: - All 12 files in elastic/migrations/*.php
This commit is contained in:
parent
04722bae9f
commit
d27b3ffc47
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateInvoicesIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateInvoicesIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'invoices_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core invoice fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateQuotesIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateQuotesIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'quotes_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core quote fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateCreditsIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateCreditsIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'credits_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core credit fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateRecurringInvoicesIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,9 +14,11 @@ final class CreateRecurringInvoicesIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Force drop any existing indices to avoid mapping conflicts
|
||||
Index::dropIfExists('recurring_invoices_v2');
|
||||
Index::dropIfExists('recurring_invoices');
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'recurring_invoices_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreatePurchaseOrdersIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreatePurchaseOrdersIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'purchase_orders_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core purchase order fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateVendorsIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateVendorsIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'vendors_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core vendor fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateExpensesIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateExpensesIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'expenses_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core expense fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateProjectsIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateProjectsIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'projects_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core project fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateTasksIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateTasksIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'tasks_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core task fields
|
||||
|
|
@ -68,4 +75,3 @@ final class CreateTasksIndex implements MigrationInterface
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateClientContactsIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateClientContactsIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'client_contacts_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core client contact fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateVendorContactsIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateVendorContactsIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'vendor_contacts_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core vendor contact fields
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Elastic\Adapter\Indices\Mapping;
|
|||
use Elastic\Adapter\Indices\Settings;
|
||||
use Elastic\Migrations\Facades\Index;
|
||||
use Elastic\Migrations\MigrationInterface;
|
||||
use Elastic\Elasticsearch\ClientBuilder;
|
||||
|
||||
final class CreateClientsIndex implements MigrationInterface
|
||||
{
|
||||
|
|
@ -13,6 +14,12 @@ final class CreateClientsIndex implements MigrationInterface
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Check if index already exists (idempotency)
|
||||
$client = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
|
||||
if ($client->indices()->exists(['index' => 'clients_v2'])) {
|
||||
return; // Index already exists, skip creation
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
'properties' => [
|
||||
// Core client fields
|
||||
|
|
@ -143,4 +150,3 @@ final class CreateClientsIndex implements MigrationInterface
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue