|
6 | 6 | package logic |
7 | 7 |
|
8 | 8 | import ( |
| 9 | + "bytes" |
9 | 10 | "context" |
10 | 11 | gosql "database/sql" |
11 | 12 | "errors" |
12 | 13 | "fmt" |
| 14 | + "io" |
13 | 15 | "os" |
14 | 16 | "path/filepath" |
15 | 17 | "strings" |
@@ -325,6 +327,8 @@ func (suite *MigratorTestSuite) SetupTest() { |
325 | 327 |
|
326 | 328 | _, err := suite.db.ExecContext(ctx, "CREATE DATABASE IF NOT EXISTS "+testMysqlDatabase) |
327 | 329 | suite.Require().NoError(err) |
| 330 | + |
| 331 | + os.Remove("/tmp/gh-ost.sock") |
328 | 332 | } |
329 | 333 |
|
330 | 334 | func (suite *MigratorTestSuite) TearDownTest() { |
@@ -384,6 +388,126 @@ func (suite *MigratorTestSuite) TestMigrateEmpty() { |
384 | 388 | suite.Require().Equal("_testing_del", tableName) |
385 | 389 | } |
386 | 390 |
|
| 391 | +func (suite *MigratorTestSuite) TestRetryBatchCopyWithHooks() { |
| 392 | + ctx := context.Background() |
| 393 | + |
| 394 | + _, err := suite.db.ExecContext(ctx, "CREATE TABLE test.test_retry_batch (id INT PRIMARY KEY AUTO_INCREMENT, name TEXT)") |
| 395 | + suite.Require().NoError(err) |
| 396 | + |
| 397 | + const initStride = 1000 |
| 398 | + const totalBatches = 3 |
| 399 | + for i := 0; i < totalBatches; i++ { |
| 400 | + dataSize := 50 * i |
| 401 | + for j := 0; j < initStride; j++ { |
| 402 | + _, err = suite.db.ExecContext(ctx, fmt.Sprintf("INSERT INTO test.test_retry_batch (name) VALUES ('%s')", strings.Repeat("a", dataSize))) |
| 403 | + suite.Require().NoError(err) |
| 404 | + } |
| 405 | + } |
| 406 | + |
| 407 | + _, err = suite.db.ExecContext(ctx, fmt.Sprintf("SET GLOBAL max_binlog_cache_size = %d", 1024*8)) |
| 408 | + suite.Require().NoError(err) |
| 409 | + defer func() { |
| 410 | + _, err = suite.db.ExecContext(ctx, fmt.Sprintf("SET GLOBAL max_binlog_cache_size = %d", 1024*1024*1024)) |
| 411 | + suite.Require().NoError(err) |
| 412 | + }() |
| 413 | + |
| 414 | + tmpDir, err := os.MkdirTemp("", "gh-ost-hooks") |
| 415 | + suite.Require().NoError(err) |
| 416 | + defer os.RemoveAll(tmpDir) |
| 417 | + |
| 418 | + hookScript := filepath.Join(tmpDir, "gh-ost-on-batch-copy-retry") |
| 419 | + hookContent := `#!/bin/bash |
| 420 | +# Mock hook that reduces chunk size on binlog cache error |
| 421 | +ERROR_MSG="$GH_OST_LAST_BATCH_COPY_ERROR" |
| 422 | +SOCKET_PATH="/tmp/gh-ost.sock" |
| 423 | +
|
| 424 | +if ! [[ "$ERROR_MSG" =~ "max_binlog_cache_size" ]]; then |
| 425 | + echo "Nothing to do for error: $ERROR_MSG" |
| 426 | + exit 0 |
| 427 | +fi |
| 428 | +
|
| 429 | +CHUNK_SIZE=$(echo "chunk-size=?" | nc -U $SOCKET_PATH | tr -d '\n') |
| 430 | +
|
| 431 | +MIN_CHUNK_SIZE=10 |
| 432 | +NEW_CHUNK_SIZE=$(( CHUNK_SIZE * 8 / 10 )) |
| 433 | +if [ $NEW_CHUNK_SIZE -lt $MIN_CHUNK_SIZE ]; then |
| 434 | + NEW_CHUNK_SIZE=$MIN_CHUNK_SIZE |
| 435 | +fi |
| 436 | +
|
| 437 | +if [ $CHUNK_SIZE -eq $NEW_CHUNK_SIZE ]; then |
| 438 | + echo "Chunk size unchanged: $CHUNK_SIZE" |
| 439 | + exit 0 |
| 440 | +fi |
| 441 | +
|
| 442 | +echo "[gh-ost-on-batch-copy-retry]: Changing chunk size from $CHUNK_SIZE to $NEW_CHUNK_SIZE" |
| 443 | +echo "chunk-size=$NEW_CHUNK_SIZE" | nc -U $SOCKET_PATH |
| 444 | +echo "[gh-ost-on-batch-copy-retry]: Done, exiting..." |
| 445 | +` |
| 446 | + err = os.WriteFile(hookScript, []byte(hookContent), 0755) |
| 447 | + suite.Require().NoError(err) |
| 448 | + |
| 449 | + origStdout := os.Stdout |
| 450 | + origStderr := os.Stderr |
| 451 | + |
| 452 | + rOut, wOut, _ := os.Pipe() |
| 453 | + rErr, wErr, _ := os.Pipe() |
| 454 | + os.Stdout = wOut |
| 455 | + os.Stderr = wErr |
| 456 | + |
| 457 | + connectionConfig, err := getTestConnectionConfig(ctx, suite.mysqlContainer) |
| 458 | + suite.Require().NoError(err) |
| 459 | + |
| 460 | + migrationContext := base.NewMigrationContext() |
| 461 | + migrationContext.AllowedRunningOnMaster = true |
| 462 | + migrationContext.ApplierConnectionConfig = connectionConfig |
| 463 | + migrationContext.InspectorConnectionConfig = connectionConfig |
| 464 | + migrationContext.DatabaseName = "test" |
| 465 | + migrationContext.SkipPortValidation = true |
| 466 | + migrationContext.OriginalTableName = "test_retry_batch" |
| 467 | + migrationContext.SetConnectionConfig("innodb") |
| 468 | + migrationContext.AlterStatementOptions = "MODIFY name LONGTEXT, ENGINE=InnoDB" |
| 469 | + migrationContext.ReplicaServerId = 99999 |
| 470 | + migrationContext.HeartbeatIntervalMilliseconds = 100 |
| 471 | + migrationContext.ThrottleHTTPIntervalMillis = 100 |
| 472 | + migrationContext.ThrottleHTTPTimeoutMillis = 1000 |
| 473 | + migrationContext.HooksPath = tmpDir |
| 474 | + migrationContext.ChunkSize = 1000 |
| 475 | + migrationContext.SetDefaultNumRetries(10) |
| 476 | + migrationContext.ServeSocketFile = "/tmp/gh-ost.sock" |
| 477 | + |
| 478 | + migrator := NewMigrator(migrationContext, "0.0.0") |
| 479 | + |
| 480 | + err = migrator.Migrate() |
| 481 | + suite.Require().NoError(err) |
| 482 | + |
| 483 | + wOut.Close() |
| 484 | + wErr.Close() |
| 485 | + os.Stdout = origStdout |
| 486 | + os.Stderr = origStderr |
| 487 | + |
| 488 | + var bufOut, bufErr bytes.Buffer |
| 489 | + io.Copy(&bufOut, rOut) |
| 490 | + io.Copy(&bufErr, rErr) |
| 491 | + |
| 492 | + outStr := bufOut.String() |
| 493 | + errStr := bufErr.String() |
| 494 | + |
| 495 | + suite.Assert().Contains(outStr, "chunk-size: 1000") |
| 496 | + suite.Assert().Contains(errStr, "[gh-ost-on-batch-copy-retry]: Changing chunk size from 1000 to 800") |
| 497 | + suite.Assert().Contains(outStr, "chunk-size: 800") |
| 498 | + |
| 499 | + suite.Assert().Contains(errStr, "[gh-ost-on-batch-copy-retry]: Changing chunk size from 800 to 640") |
| 500 | + suite.Assert().Contains(outStr, "chunk-size: 640") |
| 501 | + |
| 502 | + suite.Assert().Contains(errStr, "[gh-ost-on-batch-copy-retry]: Changing chunk size from 640 to 512") |
| 503 | + suite.Assert().Contains(outStr, "chunk-size: 512") |
| 504 | + |
| 505 | + var count int |
| 506 | + err = suite.db.QueryRowContext(ctx, "SELECT COUNT(*) FROM test.test_retry_batch").Scan(&count) |
| 507 | + suite.Require().NoError(err) |
| 508 | + suite.Assert().Equal(3000, count) |
| 509 | +} |
| 510 | + |
387 | 511 | func (suite *MigratorTestSuite) TestCopierIntPK() { |
388 | 512 | ctx := context.Background() |
389 | 513 |
|
|
0 commit comments