|
6 | 6 |
|
7 | 7 | package org.elasticsearch.xpack.slm; |
8 | 8 |
|
| 9 | +import org.elasticsearch.ElasticsearchException; |
9 | 10 | import org.elasticsearch.action.ActionListener; |
| 11 | +import org.elasticsearch.action.ActionRequest; |
| 12 | +import org.elasticsearch.action.ActionResponse; |
| 13 | +import org.elasticsearch.action.ActionType; |
| 14 | +import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest; |
| 15 | +import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; |
| 16 | +import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse; |
10 | 17 | import org.elasticsearch.action.support.master.AcknowledgedResponse; |
11 | 18 | import org.elasticsearch.client.Client; |
12 | 19 | import org.elasticsearch.cluster.ClusterName; |
|
45 | 52 | import java.util.Arrays; |
46 | 53 | import java.util.Collection; |
47 | 54 | import java.util.Collections; |
| 55 | +import java.util.HashMap; |
48 | 56 | import java.util.List; |
49 | 57 | import java.util.Map; |
50 | 58 | import java.util.Set; |
|
53 | 61 | import java.util.concurrent.TimeUnit; |
54 | 62 | import java.util.concurrent.atomic.AtomicBoolean; |
55 | 63 | import java.util.concurrent.atomic.AtomicLong; |
| 64 | +import java.util.concurrent.atomic.AtomicReference; |
56 | 65 | import java.util.function.Consumer; |
57 | 66 | import java.util.function.Function; |
58 | 67 | import java.util.function.LongSupplier; |
@@ -375,6 +384,114 @@ public void testOkToDeleteSnapshots() { |
375 | 384 | assertThat(SnapshotRetentionTask.okayToDeleteSnapshots(state), equalTo(true)); |
376 | 385 | } |
377 | 386 |
|
| 387 | + public void testErrStillRunsFailureHandlerWhenRetrieving() throws Exception { |
| 388 | + ThreadPool threadPool = new TestThreadPool("slm-test"); |
| 389 | + final String policyId = "policy"; |
| 390 | + final String repoId = "repo"; |
| 391 | + try (ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); |
| 392 | + Client noOpClient = new NoOpClient("slm-test") { |
| 393 | + |
| 394 | + @Override |
| 395 | + @SuppressWarnings("unchecked") |
| 396 | + protected <Request extends ActionRequest, Response extends ActionResponse> |
| 397 | + void doExecute(ActionType<Response> action, Request request, ActionListener<Response> listener) { |
| 398 | + if (request instanceof GetSnapshotsRequest) { |
| 399 | + logger.info("--> called"); |
| 400 | + listener.onResponse((Response) new GetSnapshotsResponse( |
| 401 | + Collections.singleton(GetSnapshotsResponse.Response.snapshots(repoId, Collections.emptyList())))); |
| 402 | + } else { |
| 403 | + super.doExecute(action, request, listener); |
| 404 | + } |
| 405 | + } |
| 406 | + }) { |
| 407 | + SnapshotLifecyclePolicy policy = new SnapshotLifecyclePolicy(policyId, "snap", "1 * * * * ?", |
| 408 | + repoId, null, new SnapshotRetentionConfiguration(TimeValue.timeValueDays(30), null, null)); |
| 409 | + |
| 410 | + ClusterState state = createState(policy); |
| 411 | + ClusterServiceUtils.setState(clusterService, state); |
| 412 | + |
| 413 | + SnapshotRetentionTask task = new SnapshotRetentionTask(noOpClient, clusterService, |
| 414 | + System::nanoTime, |
| 415 | + new SnapshotLifecycleTaskTests.VerifyingHistoryStore(noOpClient, ZoneOffset.UTC, |
| 416 | + (historyItem) -> fail("should never write history")), |
| 417 | + threadPool); |
| 418 | + |
| 419 | + AtomicReference<Exception> errHandlerCalled = new AtomicReference<>(null); |
| 420 | + task.getAllRetainableSnapshots(Collections.singleton(repoId), new ActionListener<>() { |
| 421 | + @Override |
| 422 | + public void onResponse(Map<String, List<SnapshotInfo>> stringListMap) { |
| 423 | + logger.info("--> forcing failure"); |
| 424 | + throw new ElasticsearchException("forced failure"); |
| 425 | + } |
| 426 | + |
| 427 | + @Override |
| 428 | + public void onFailure(Exception e) { |
| 429 | + fail("we have another err handler that should have been called"); |
| 430 | + } |
| 431 | + }, errHandlerCalled::set); |
| 432 | + |
| 433 | + assertNotNull(errHandlerCalled.get()); |
| 434 | + assertThat(errHandlerCalled.get().getMessage(), equalTo("forced failure")); |
| 435 | + } finally { |
| 436 | + threadPool.shutdownNow(); |
| 437 | + threadPool.awaitTermination(10, TimeUnit.SECONDS); |
| 438 | + } |
| 439 | + } |
| 440 | + |
| 441 | + public void testErrStillRunsFailureHandlerWhenDeleting() throws Exception { |
| 442 | + ThreadPool threadPool = new TestThreadPool("slm-test"); |
| 443 | + try (ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); |
| 444 | + Client noOpClient = new NoOpClient("slm-test") { |
| 445 | + |
| 446 | + @Override |
| 447 | + @SuppressWarnings("unchecked") |
| 448 | + protected <Request extends ActionRequest, Response extends ActionResponse> |
| 449 | + void doExecute(ActionType<Response> action, Request request, ActionListener<Response> listener) { |
| 450 | + if (request instanceof DeleteSnapshotRequest) { |
| 451 | + logger.info("--> called"); |
| 452 | + listener.onResponse((Response) new AcknowledgedResponse(true)); |
| 453 | + } else { |
| 454 | + super.doExecute(action, request, listener); |
| 455 | + } |
| 456 | + } |
| 457 | + }) { |
| 458 | + final String policyId = "policy"; |
| 459 | + final String repoId = "repo"; |
| 460 | + SnapshotLifecyclePolicy policy = new SnapshotLifecyclePolicy(policyId, "snap", "1 * * * * ?", |
| 461 | + repoId, null, new SnapshotRetentionConfiguration(TimeValue.timeValueDays(30), null, null)); |
| 462 | + |
| 463 | + ClusterState state = createState(policy); |
| 464 | + ClusterServiceUtils.setState(clusterService, state); |
| 465 | + |
| 466 | + SnapshotRetentionTask task = new SnapshotRetentionTask(noOpClient, clusterService, |
| 467 | + System::nanoTime, |
| 468 | + new SnapshotLifecycleTaskTests.VerifyingHistoryStore(noOpClient, ZoneOffset.UTC, |
| 469 | + (historyItem) -> fail("should never write history")), |
| 470 | + threadPool); |
| 471 | + |
| 472 | + AtomicBoolean onFailureCalled = new AtomicBoolean(false); |
| 473 | + AtomicReference<Exception> errHandlerCalled = new AtomicReference<>(null); |
| 474 | + task.deleteSnapshot("policy", "foo", new SnapshotId("name", "uuid"), |
| 475 | + new SnapshotLifecycleStats(0, 0, 0, 0, new HashMap<>()), new ActionListener<>() { |
| 476 | + @Override |
| 477 | + public void onResponse(AcknowledgedResponse acknowledgedResponse) { |
| 478 | + logger.info("--> forcing failure"); |
| 479 | + throw new ElasticsearchException("forced failure"); |
| 480 | + } |
| 481 | + |
| 482 | + @Override |
| 483 | + public void onFailure(Exception e) { |
| 484 | + onFailureCalled.set(true); |
| 485 | + } |
| 486 | + }); |
| 487 | + |
| 488 | + assertThat(onFailureCalled.get(), equalTo(true)); |
| 489 | + } finally { |
| 490 | + threadPool.shutdownNow(); |
| 491 | + threadPool.awaitTermination(10, TimeUnit.SECONDS); |
| 492 | + } |
| 493 | + } |
| 494 | + |
378 | 495 | public void testSkipWhileStopping() throws Exception { |
379 | 496 | doTestSkipDuringMode(OperationMode.STOPPING); |
380 | 497 | } |
|
0 commit comments