|
25 | 25 | import com.google.common.collect.ImmutableMap; |
26 | 26 | import com.google.common.collect.ImmutableSet; |
27 | 27 | import com.google.common.util.concurrent.SettableFuture; |
| 28 | +import org.apache.druid.data.input.impl.ByteEntity; |
28 | 29 | import org.apache.druid.error.DruidException; |
29 | 30 | import org.apache.druid.error.DruidExceptionMatcher; |
30 | 31 | import org.apache.druid.error.InvalidInput; |
31 | 32 | import org.apache.druid.indexing.common.TaskLockType; |
32 | 33 | import org.apache.druid.indexing.common.task.Tasks; |
33 | 34 | import org.apache.druid.indexing.overlord.DataSourceMetadata; |
| 35 | +import org.apache.druid.indexing.overlord.ObjectMetadata; |
34 | 36 | import org.apache.druid.indexing.seekablestream.SeekableStreamStartSequenceNumbers; |
35 | 37 | import org.apache.druid.indexing.seekablestream.TestSeekableStreamDataSourceMetadata; |
36 | 38 | import org.apache.druid.indexing.seekablestream.supervisor.SeekableStreamSupervisor; |
@@ -796,6 +798,154 @@ public void testRegisterUpgradedPendingSegmentOnSupervisor() |
796 | 798 | verifyAll(); |
797 | 799 | } |
798 | 800 |
|
| 801 | + @Test |
| 802 | + public void test_isAnotherTaskGroupPublishingToPartitions_throwsException_ifSupervisorIdIsNull() |
| 803 | + { |
| 804 | + MatcherAssert.assertThat( |
| 805 | + Assert.assertThrows( |
| 806 | + DruidException.class, |
| 807 | + () -> manager.isAnotherTaskGroupPublishingToPartitions(null, "task1", null) |
| 808 | + ), |
| 809 | + DruidExceptionMatcher.invalidInput().expectMessageIs("'supervisorId' cannot be null") |
| 810 | + ); |
| 811 | + } |
| 812 | + |
| 813 | + @Test |
| 814 | + public void test_isAnotherTaskGroupPublishingToPartitions_throwsException_ifSupervisorNotFound() |
| 815 | + { |
| 816 | + MatcherAssert.assertThat( |
| 817 | + Assert.assertThrows( |
| 818 | + DruidException.class, |
| 819 | + () -> manager.isAnotherTaskGroupPublishingToPartitions("supervisor1", "task1", null) |
| 820 | + ), |
| 821 | + DruidExceptionMatcher.notFound().expectMessageIs("Could not find supervisor[supervisor1]") |
| 822 | + ); |
| 823 | + } |
| 824 | + |
| 825 | + @Test |
| 826 | + public void test_isAnotherTaskGroupPublishingToPartitions_returnsFalse_forNonStreamingSupervisor() |
| 827 | + { |
| 828 | + final String supervisorId = "supervisor1"; |
| 829 | + EasyMock.expect(metadataSupervisorManager.getLatest()).andReturn( |
| 830 | + Map.of(supervisorId, new TestSupervisorSpec(supervisorId, supervisor1)) |
| 831 | + ); |
| 832 | + |
| 833 | + supervisor1.start(); |
| 834 | + EasyMock.expect(supervisor1.createAutoscaler(EasyMock.anyObject())).andReturn(null).anyTimes(); |
| 835 | + replayAll(); |
| 836 | + |
| 837 | + manager.start(); |
| 838 | + |
| 839 | + Assert.assertFalse( |
| 840 | + manager.isAnotherTaskGroupPublishingToPartitions(supervisorId, "task1", null) |
| 841 | + ); |
| 842 | + } |
| 843 | + |
| 844 | + @Test |
| 845 | + public void test_isAnotherTaskGroupPublishingToPartitions_throwsException_ifMetadataIsNull() |
| 846 | + { |
| 847 | + final String supervisorId = "supervisor1"; |
| 848 | + final SeekableStreamSupervisor<Integer, String, ByteEntity> seekableStreamSupervisor = |
| 849 | + EasyMock.createMock(SeekableStreamSupervisor.class); |
| 850 | + EasyMock.expect(metadataSupervisorManager.getLatest()).andReturn( |
| 851 | + Map.of(supervisorId, new TestSupervisorSpec(supervisorId, seekableStreamSupervisor)) |
| 852 | + ); |
| 853 | + |
| 854 | + seekableStreamSupervisor.start(); |
| 855 | + EasyMock.expect(seekableStreamSupervisor.createAutoscaler(EasyMock.anyObject())).andReturn(null).anyTimes(); |
| 856 | + replayAll(); |
| 857 | + EasyMock.replay(seekableStreamSupervisor); |
| 858 | + |
| 859 | + manager.start(); |
| 860 | + |
| 861 | + MatcherAssert.assertThat( |
| 862 | + Assert.assertThrows( |
| 863 | + DruidException.class, |
| 864 | + () -> manager.isAnotherTaskGroupPublishingToPartitions(supervisorId, "task1", null) |
| 865 | + ), |
| 866 | + DruidExceptionMatcher.invalidInput().expectMessageIs( |
| 867 | + "Start metadata[null] of type[null] is not valid streaming metadata" |
| 868 | + ) |
| 869 | + ); |
| 870 | + } |
| 871 | + |
| 872 | + @Test |
| 873 | + public void test_isAnotherTaskGroupPublishingToPartitions_throwsException_ifMetadataIsInvalid() |
| 874 | + { |
| 875 | + final String supervisorId = "supervisor1"; |
| 876 | + final SeekableStreamSupervisor<Integer, String, ByteEntity> seekableStreamSupervisor = |
| 877 | + EasyMock.createMock(SeekableStreamSupervisor.class); |
| 878 | + EasyMock.expect(metadataSupervisorManager.getLatest()).andReturn( |
| 879 | + Map.of(supervisorId, new TestSupervisorSpec(supervisorId, seekableStreamSupervisor)) |
| 880 | + ); |
| 881 | + |
| 882 | + seekableStreamSupervisor.start(); |
| 883 | + EasyMock.expect(seekableStreamSupervisor.createAutoscaler(EasyMock.anyObject())).andReturn(null).anyTimes(); |
| 884 | + replayAll(); |
| 885 | + EasyMock.replay(seekableStreamSupervisor); |
| 886 | + |
| 887 | + manager.start(); |
| 888 | + |
| 889 | + MatcherAssert.assertThat( |
| 890 | + Assert.assertThrows( |
| 891 | + DruidException.class, |
| 892 | + () -> manager.isAnotherTaskGroupPublishingToPartitions(supervisorId, "task1", new ObjectMetadata("abc")) |
| 893 | + ), |
| 894 | + DruidExceptionMatcher.invalidInput().expectMessageIs( |
| 895 | + "Start metadata[ObjectMetadata{theObject=abc}] of" |
| 896 | + + " type[class org.apache.druid.indexing.overlord.ObjectMetadata]" |
| 897 | + + " is not valid streaming metadata" |
| 898 | + ) |
| 899 | + ); |
| 900 | + } |
| 901 | + |
| 902 | + @Test |
| 903 | + public void test_isAnotherTaskGroupPublishingToPartitions() |
| 904 | + { |
| 905 | + final String supervisorId = "supervisor1"; |
| 906 | + final SeekableStreamSupervisor<Integer, String, ByteEntity> seekableStreamSupervisor = |
| 907 | + EasyMock.createMock(SeekableStreamSupervisor.class); |
| 908 | + EasyMock.expect(metadataSupervisorManager.getLatest()).andReturn( |
| 909 | + Map.of(supervisorId, new TestSupervisorSpec(supervisorId, seekableStreamSupervisor)) |
| 910 | + ); |
| 911 | + |
| 912 | + seekableStreamSupervisor.start(); |
| 913 | + EasyMock.expect(seekableStreamSupervisor.createAutoscaler(EasyMock.anyObject())).andReturn(null).anyTimes(); |
| 914 | + |
| 915 | + // Expect a readyTaskId for which no other group is currently publishing |
| 916 | + final String readyTaskId = "task1"; |
| 917 | + EasyMock.expect( |
| 918 | + seekableStreamSupervisor.isAnotherTaskGroupPublishingToPartitions( |
| 919 | + EasyMock.eq(readyTaskId), |
| 920 | + EasyMock.anyObject() |
| 921 | + ) |
| 922 | + ).andReturn(false).atLeastOnce(); |
| 923 | + |
| 924 | + // Expect a conflictingTaskId for which another group is currently publishing |
| 925 | + final String conflictingTaskId = "task2"; |
| 926 | + EasyMock.expect( |
| 927 | + seekableStreamSupervisor.isAnotherTaskGroupPublishingToPartitions( |
| 928 | + EasyMock.eq(conflictingTaskId), |
| 929 | + EasyMock.anyObject() |
| 930 | + ) |
| 931 | + ).andReturn(true).atLeastOnce(); |
| 932 | + |
| 933 | + replayAll(); |
| 934 | + EasyMock.replay(seekableStreamSupervisor); |
| 935 | + manager.start(); |
| 936 | + |
| 937 | + final DataSourceMetadata startMetadata = TestSeekableStreamDataSourceMetadata.start( |
| 938 | + "topic", |
| 939 | + Map.of("0", "10") |
| 940 | + ); |
| 941 | + Assert.assertTrue( |
| 942 | + manager.isAnotherTaskGroupPublishingToPartitions(supervisorId, conflictingTaskId, startMetadata) |
| 943 | + ); |
| 944 | + Assert.assertFalse( |
| 945 | + manager.isAnotherTaskGroupPublishingToPartitions(supervisorId, readyTaskId, startMetadata) |
| 946 | + ); |
| 947 | + } |
| 948 | + |
799 | 949 | private static class TestSupervisorSpec implements SupervisorSpec |
800 | 950 | { |
801 | 951 | private final String id; |
|
0 commit comments