Wenjun Ruan
6 months ago
committed by
GitHub
65 changed files with 1781 additions and 503 deletions
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="120 seconds"> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -1,143 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.plugin.registry.etcd; |
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.registry.api.Event; |
|
||||||
import org.apache.dolphinscheduler.registry.api.SubscribeListener; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.List; |
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.TimeUnit; |
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll; |
|
||||||
import org.junit.jupiter.api.Assertions; |
|
||||||
import org.junit.jupiter.api.BeforeAll; |
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
|
|
||||||
import io.etcd.jetcd.test.EtcdClusterExtension; |
|
||||||
|
|
||||||
public class EtcdRegistryTest { |
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(EtcdRegistryTest.class); |
|
||||||
|
|
||||||
public static EtcdRegistry registry; |
|
||||||
|
|
||||||
@BeforeAll |
|
||||||
public static void before() throws Exception { |
|
||||||
EtcdClusterExtension server = EtcdClusterExtension.builder() |
|
||||||
.withNodes(1) |
|
||||||
.withImage("ibmcom/etcd:3.2.24") |
|
||||||
.build(); |
|
||||||
EtcdRegistryProperties properties = new EtcdRegistryProperties(); |
|
||||||
server.restart(); |
|
||||||
properties.setEndpoints(String.valueOf(server.clientEndpoints().get(0))); |
|
||||||
registry = new EtcdRegistry(properties); |
|
||||||
registry.put("/sub", "sub", false); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void persistTest() { |
|
||||||
registry.put("/nodes/m1", "", false); |
|
||||||
registry.put("/nodes/m2", "", false); |
|
||||||
Assertions.assertEquals(Arrays.asList("m1", "m2"), registry.children("/nodes")); |
|
||||||
Assertions.assertTrue(registry.exists("/nodes/m1")); |
|
||||||
registry.delete("/nodes/m2"); |
|
||||||
Assertions.assertFalse(registry.exists("/nodes/m2")); |
|
||||||
registry.delete("/nodes"); |
|
||||||
Assertions.assertFalse(registry.exists("/nodes/m1")); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void lockTest() { |
|
||||||
CountDownLatch preCountDownLatch = new CountDownLatch(1); |
|
||||||
CountDownLatch allCountDownLatch = new CountDownLatch(2); |
|
||||||
List<String> testData = new ArrayList<>(); |
|
||||||
new Thread(() -> { |
|
||||||
registry.acquireLock("/lock"); |
|
||||||
preCountDownLatch.countDown(); |
|
||||||
logger.info(Thread.currentThread().getName() |
|
||||||
+ " :I got the lock, but I don't want to work. I want to rest for a while"); |
|
||||||
try { |
|
||||||
Thread.sleep(1000); |
|
||||||
logger.info(Thread.currentThread().getName() + " :I'm going to start working"); |
|
||||||
testData.add("thread1"); |
|
||||||
|
|
||||||
} catch (InterruptedException e) { |
|
||||||
Thread.currentThread().interrupt(); |
|
||||||
} finally { |
|
||||||
logger.info(Thread.currentThread().getName() + " :I have finished my work, now I release the lock"); |
|
||||||
registry.releaseLock("/lock"); |
|
||||||
allCountDownLatch.countDown(); |
|
||||||
} |
|
||||||
}).start(); |
|
||||||
try { |
|
||||||
preCountDownLatch.await(5, TimeUnit.SECONDS); |
|
||||||
} catch (InterruptedException e) { |
|
||||||
throw new RuntimeException(e); |
|
||||||
} |
|
||||||
new Thread(() -> { |
|
||||||
try { |
|
||||||
logger.info(Thread.currentThread().getName() + " :I am trying to acquire the lock"); |
|
||||||
registry.acquireLock("/lock"); |
|
||||||
logger.info(Thread.currentThread().getName() + " :I got the lock and I started working"); |
|
||||||
|
|
||||||
testData.add("thread2"); |
|
||||||
} finally { |
|
||||||
registry.releaseLock("/lock"); |
|
||||||
allCountDownLatch.countDown(); |
|
||||||
} |
|
||||||
|
|
||||||
}).start(); |
|
||||||
try { |
|
||||||
allCountDownLatch.await(5, TimeUnit.SECONDS); |
|
||||||
} catch (InterruptedException e) { |
|
||||||
throw new RuntimeException(e); |
|
||||||
} |
|
||||||
Assertions.assertEquals(testData, Arrays.asList("thread1", "thread2")); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void subscribeTest() { |
|
||||||
boolean status = registry.subscribe("/sub", new TestListener()); |
|
||||||
// The following add and delete operations are used for debugging
|
|
||||||
registry.put("/sub/m1", "tt", false); |
|
||||||
registry.put("/sub/m2", "tt", false); |
|
||||||
registry.delete("/sub/m2"); |
|
||||||
registry.delete("/sub"); |
|
||||||
Assertions.assertTrue(status); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static class TestListener implements SubscribeListener { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void notify(Event event) { |
|
||||||
logger.info("I'm test listener"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@AfterAll |
|
||||||
public static void after() throws IOException { |
|
||||||
registry.close(); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,70 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry.etcd; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.registry.RegistryTestCase; |
||||||
|
|
||||||
|
import java.net.URI; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import lombok.SneakyThrows; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll; |
||||||
|
import org.junit.jupiter.api.BeforeAll; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||||
|
import org.springframework.boot.test.context.SpringBootTest; |
||||||
|
|
||||||
|
import io.etcd.jetcd.launcher.EtcdCluster; |
||||||
|
import io.etcd.jetcd.test.EtcdClusterExtension; |
||||||
|
|
||||||
|
@SpringBootTest(classes = EtcdRegistryProperties.class) |
||||||
|
@SpringBootApplication(scanBasePackageClasses = EtcdRegistryProperties.class) |
||||||
|
public class EtcdRegistryTestCase extends RegistryTestCase<EtcdRegistry> { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private EtcdRegistryProperties etcdRegistryProperties; |
||||||
|
|
||||||
|
private static EtcdCluster etcdCluster; |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@BeforeAll |
||||||
|
public static void setUpTestingServer() { |
||||||
|
etcdCluster = EtcdClusterExtension.builder() |
||||||
|
.withNodes(1) |
||||||
|
.withImage("ibmcom/etcd:3.2.24") |
||||||
|
.build() |
||||||
|
.cluster(); |
||||||
|
etcdCluster.start(); |
||||||
|
System.setProperty("registry.endpoints", |
||||||
|
etcdCluster.clientEndpoints().stream().map(URI::toString).collect(Collectors.joining(","))); |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Override |
||||||
|
public EtcdRegistry createRegistry() { |
||||||
|
return new EtcdRegistry(etcdRegistryProperties); |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@AfterAll |
||||||
|
public static void tearDownTestingServer() { |
||||||
|
try (EtcdCluster cluster = etcdCluster) { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
# |
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
# contributor license agreements. See the NOTICE file distributed with |
||||||
|
# this work for additional information regarding copyright ownership. |
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
# (the "License"); you may not use this file except in compliance with |
||||||
|
# the License. You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
# |
||||||
|
|
||||||
|
registry: |
||||||
|
type: etcd |
||||||
|
ttl: 2s |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,60 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
<parent> |
||||||
|
<groupId>org.apache.dolphinscheduler</groupId> |
||||||
|
<artifactId>dolphinscheduler-registry-plugins</artifactId> |
||||||
|
<version>dev-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
|
||||||
|
<artifactId>dolphinscheduler-registry-it</artifactId> |
||||||
|
|
||||||
|
<dependencies> |
||||||
|
<dependency> |
||||||
|
<groupId>org.apache.dolphinscheduler</groupId> |
||||||
|
<artifactId>dolphinscheduler-registry-api</artifactId> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>org.springframework.boot</groupId> |
||||||
|
<artifactId>spring-boot-starter-test</artifactId> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
|
||||||
|
<build> |
||||||
|
<plugins> |
||||||
|
<plugin> |
||||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||||
|
<artifactId>maven-jar-plugin</artifactId> |
||||||
|
<configuration> |
||||||
|
<skip>false</skip> |
||||||
|
</configuration> |
||||||
|
<executions> |
||||||
|
<execution> |
||||||
|
<goals> |
||||||
|
<goal>test-jar</goal> |
||||||
|
</goals> |
||||||
|
</execution> |
||||||
|
</executions> |
||||||
|
</plugin> |
||||||
|
</plugins> |
||||||
|
</build> |
||||||
|
|
||||||
|
</project> |
@ -0,0 +1,290 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry; |
||||||
|
|
||||||
|
import static org.awaitility.Awaitility.await; |
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.registry.api.ConnectionState; |
||||||
|
import org.apache.dolphinscheduler.registry.api.Event; |
||||||
|
import org.apache.dolphinscheduler.registry.api.Registry; |
||||||
|
import org.apache.dolphinscheduler.registry.api.RegistryException; |
||||||
|
import org.apache.dolphinscheduler.registry.api.SubscribeListener; |
||||||
|
|
||||||
|
import java.time.Duration; |
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
import java.util.concurrent.TimeoutException; |
||||||
|
import java.util.concurrent.atomic.AtomicBoolean; |
||||||
|
import java.util.concurrent.atomic.AtomicReference; |
||||||
|
|
||||||
|
import lombok.SneakyThrows; |
||||||
|
|
||||||
|
import org.assertj.core.util.Lists; |
||||||
|
import org.junit.jupiter.api.AfterEach; |
||||||
|
import org.junit.jupiter.api.Assertions; |
||||||
|
import org.junit.jupiter.api.BeforeEach; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
|
||||||
|
import com.google.common.truth.Truth; |
||||||
|
|
||||||
|
public abstract class RegistryTestCase<R extends Registry> { |
||||||
|
|
||||||
|
protected R registry; |
||||||
|
|
||||||
|
@BeforeEach |
||||||
|
public void setupRegistry() { |
||||||
|
registry = createRegistry(); |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@AfterEach |
||||||
|
public void tearDownRegistry() { |
||||||
|
try (R registry = this.registry) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testIsConnected() { |
||||||
|
registry.start(); |
||||||
|
Truth.assertThat(registry.isConnected()).isTrue(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testConnectUntilTimeout() { |
||||||
|
registry.start(); |
||||||
|
await().atMost(Duration.ofSeconds(10)) |
||||||
|
.untilAsserted(() -> registry.connectUntilTimeout(Duration.ofSeconds(3))); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Test |
||||||
|
public void testSubscribe() { |
||||||
|
registry.start(); |
||||||
|
|
||||||
|
final AtomicBoolean subscribeAdded = new AtomicBoolean(false); |
||||||
|
final AtomicBoolean subscribeRemoved = new AtomicBoolean(false); |
||||||
|
final AtomicBoolean subscribeUpdated = new AtomicBoolean(false); |
||||||
|
|
||||||
|
SubscribeListener subscribeListener = event -> { |
||||||
|
System.out.println("Receive event: " + event); |
||||||
|
if (event.type() == Event.Type.ADD) { |
||||||
|
subscribeAdded.compareAndSet(false, true); |
||||||
|
} |
||||||
|
if (event.type() == Event.Type.REMOVE) { |
||||||
|
subscribeRemoved.compareAndSet(false, true); |
||||||
|
} |
||||||
|
if (event.type() == Event.Type.UPDATE) { |
||||||
|
subscribeUpdated.compareAndSet(false, true); |
||||||
|
} |
||||||
|
}; |
||||||
|
String key = "/nodes/master" + System.nanoTime(); |
||||||
|
registry.subscribe(key, subscribeListener); |
||||||
|
registry.put(key, String.valueOf(System.nanoTime()), true); |
||||||
|
// Sleep 3 seconds here since in mysql jdbc registry
|
||||||
|
// If multiple event occurs in a refresh time, only the last event will be triggered
|
||||||
|
Thread.sleep(3000); |
||||||
|
registry.put(key, String.valueOf(System.nanoTime()), true); |
||||||
|
Thread.sleep(3000); |
||||||
|
registry.delete(key); |
||||||
|
|
||||||
|
await().atMost(Duration.ofSeconds(10)) |
||||||
|
.untilAsserted(() -> { |
||||||
|
Assertions.assertTrue(subscribeAdded.get()); |
||||||
|
Assertions.assertTrue(subscribeUpdated.get()); |
||||||
|
Assertions.assertTrue(subscribeRemoved.get()); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Test |
||||||
|
public void testUnsubscribe() { |
||||||
|
registry.start(); |
||||||
|
|
||||||
|
final AtomicBoolean subscribeAdded = new AtomicBoolean(false); |
||||||
|
final AtomicBoolean subscribeRemoved = new AtomicBoolean(false); |
||||||
|
final AtomicBoolean subscribeUpdated = new AtomicBoolean(false); |
||||||
|
|
||||||
|
SubscribeListener subscribeListener = event -> { |
||||||
|
if (event.type() == Event.Type.ADD) { |
||||||
|
subscribeAdded.compareAndSet(false, true); |
||||||
|
} |
||||||
|
if (event.type() == Event.Type.REMOVE) { |
||||||
|
subscribeRemoved.compareAndSet(false, true); |
||||||
|
} |
||||||
|
if (event.type() == Event.Type.UPDATE) { |
||||||
|
subscribeUpdated.compareAndSet(false, true); |
||||||
|
} |
||||||
|
}; |
||||||
|
String key = "/nodes/master" + System.nanoTime(); |
||||||
|
String value = "127.0.0.1:8080"; |
||||||
|
registry.subscribe(key, subscribeListener); |
||||||
|
registry.unsubscribe(key); |
||||||
|
registry.put(key, value, true); |
||||||
|
registry.put(key, value, true); |
||||||
|
registry.delete(key); |
||||||
|
|
||||||
|
Thread.sleep(2000); |
||||||
|
Assertions.assertFalse(subscribeAdded.get()); |
||||||
|
Assertions.assertFalse(subscribeRemoved.get()); |
||||||
|
Assertions.assertFalse(subscribeUpdated.get()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Test |
||||||
|
public void testAddConnectionStateListener() { |
||||||
|
|
||||||
|
AtomicReference<ConnectionState> connectionState = new AtomicReference<>(); |
||||||
|
registry.addConnectionStateListener(connectionState::set); |
||||||
|
|
||||||
|
Truth.assertThat(connectionState.get()).isNull(); |
||||||
|
registry.start(); |
||||||
|
|
||||||
|
await().atMost(Duration.ofSeconds(2)) |
||||||
|
.until(() -> ConnectionState.CONNECTED == connectionState.get()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testGet() { |
||||||
|
registry.start(); |
||||||
|
String key = "/nodes/master" + System.nanoTime(); |
||||||
|
String value = "127.0.0.1:8080"; |
||||||
|
assertThrows(RegistryException.class, () -> registry.get(key)); |
||||||
|
registry.put(key, value, true); |
||||||
|
Truth.assertThat(registry.get(key)).isEqualTo(value); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testPut() { |
||||||
|
registry.start(); |
||||||
|
String key = "/nodes/master" + System.nanoTime(); |
||||||
|
String value = "127.0.0.1:8080"; |
||||||
|
registry.put(key, value, true); |
||||||
|
Truth.assertThat(registry.get(key)).isEqualTo(value); |
||||||
|
|
||||||
|
// Update the value
|
||||||
|
registry.put(key, "123", true); |
||||||
|
Truth.assertThat(registry.get(key)).isEqualTo("123"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDelete() { |
||||||
|
registry.start(); |
||||||
|
String key = "/nodes/master" + System.nanoTime(); |
||||||
|
String value = "127.0.0.1:8080"; |
||||||
|
// Delete a non-existent key
|
||||||
|
registry.delete(key); |
||||||
|
|
||||||
|
registry.put(key, value, true); |
||||||
|
Truth.assertThat(registry.get(key)).isEqualTo(value); |
||||||
|
registry.delete(key); |
||||||
|
Truth.assertThat(registry.exists(key)).isFalse(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testChildren() { |
||||||
|
registry.start(); |
||||||
|
String master1 = "/nodes/children/127.0.0.1:8080"; |
||||||
|
String master2 = "/nodes/children/127.0.0.2:8080"; |
||||||
|
String value = "123"; |
||||||
|
registry.put(master1, value, true); |
||||||
|
registry.put(master2, value, true); |
||||||
|
Truth.assertThat(registry.children("/nodes/children")) |
||||||
|
.containsAtLeastElementsIn(Lists.newArrayList("127.0.0.1:8080", "127.0.0.2:8080")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testExists() { |
||||||
|
registry.start(); |
||||||
|
String key = "/nodes/master" + System.nanoTime(); |
||||||
|
String value = "123"; |
||||||
|
Truth.assertThat(registry.exists(key)).isFalse(); |
||||||
|
registry.put(key, value, true); |
||||||
|
Truth.assertThat(registry.exists(key)).isTrue(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Test |
||||||
|
public void testAcquireLock() { |
||||||
|
registry.start(); |
||||||
|
String lockKey = "/lock" + System.nanoTime(); |
||||||
|
|
||||||
|
// 1. Acquire the lock at the main thread
|
||||||
|
Truth.assertThat(registry.acquireLock(lockKey)).isTrue(); |
||||||
|
// Acquire the lock at the main thread again
|
||||||
|
// It should acquire success
|
||||||
|
Truth.assertThat(registry.acquireLock(lockKey)).isTrue(); |
||||||
|
|
||||||
|
// Acquire the lock at another thread
|
||||||
|
// It should acquire failed
|
||||||
|
CompletableFuture<Boolean> acquireResult = CompletableFuture.supplyAsync(() -> registry.acquireLock(lockKey)); |
||||||
|
assertThrows(TimeoutException.class, () -> acquireResult.get(3000, TimeUnit.MILLISECONDS)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Test |
||||||
|
public void testAcquireLock_withTimeout() { |
||||||
|
registry.start(); |
||||||
|
String lockKey = "/lock" + System.nanoTime(); |
||||||
|
// 1. Acquire the lock in the main thread
|
||||||
|
Truth.assertThat(registry.acquireLock(lockKey, 3000)).isTrue(); |
||||||
|
|
||||||
|
// Acquire the lock in the main thread
|
||||||
|
// It should acquire success
|
||||||
|
Truth.assertThat(registry.acquireLock(lockKey, 3000)).isTrue(); |
||||||
|
|
||||||
|
// Acquire the lock at another thread
|
||||||
|
// It should acquire failed
|
||||||
|
CompletableFuture<Boolean> acquireResult = |
||||||
|
CompletableFuture.supplyAsync(() -> registry.acquireLock(lockKey, 3000)); |
||||||
|
Truth.assertThat(acquireResult.get()).isFalse(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Test |
||||||
|
public void testReleaseLock() { |
||||||
|
registry.start(); |
||||||
|
String lockKey = "/lock" + System.nanoTime(); |
||||||
|
// 1. Acquire the lock in the main thread
|
||||||
|
Truth.assertThat(registry.acquireLock(lockKey, 3000)).isTrue(); |
||||||
|
|
||||||
|
// Acquire the lock at another thread
|
||||||
|
// It should acquire failed
|
||||||
|
CompletableFuture<Boolean> acquireResult = |
||||||
|
CompletableFuture.supplyAsync(() -> registry.acquireLock(lockKey, 3000)); |
||||||
|
Truth.assertThat(acquireResult.get()).isFalse(); |
||||||
|
|
||||||
|
// 2. Release the lock in the main thread
|
||||||
|
Truth.assertThat(registry.releaseLock(lockKey)).isTrue(); |
||||||
|
|
||||||
|
// Acquire the lock at another thread
|
||||||
|
// It should acquire success
|
||||||
|
acquireResult = CompletableFuture.supplyAsync(() -> registry.acquireLock(lockKey, 3000)); |
||||||
|
Truth.assertThat(acquireResult.get()).isTrue(); |
||||||
|
} |
||||||
|
|
||||||
|
public abstract R createRegistry(); |
||||||
|
|
||||||
|
} |
10
dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/task/EphemeralDateManager.java → dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/EphemeralDateManager.java
10
dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/task/EphemeralDateManager.java → dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/EphemeralDateManager.java
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry.jdbc; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.common.utils.NetUtils; |
||||||
|
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass; |
||||||
|
|
||||||
|
@UtilityClass |
||||||
|
public class LockUtils { |
||||||
|
|
||||||
|
private static final String LOCK_OWNER_PREFIX = NetUtils.getHost() + "_" + OSUtils.getProcessID() + "_"; |
||||||
|
|
||||||
|
public static String getLockOwner() { |
||||||
|
return LOCK_OWNER_PREFIX + Thread.currentThread().getName(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
47
dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/task/RegistryLockManager.java → dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/RegistryLockManager.java
47
dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/task/RegistryLockManager.java → dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/RegistryLockManager.java
18
dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/task/SubscribeDataManager.java → dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/SubscribeDataManager.java
18
dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/task/SubscribeDataManager.java → dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/SubscribeDataManager.java
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry.jdbc; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.registry.RegistryTestCase; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||||
|
import org.springframework.boot.test.context.SpringBootTest; |
||||||
|
|
||||||
|
@SpringBootTest(classes = {JdbcRegistryProperties.class}) |
||||||
|
@SpringBootApplication(scanBasePackageClasses = JdbcRegistryProperties.class) |
||||||
|
public abstract class JdbcRegistryTestCase extends RegistryTestCase<JdbcRegistry> { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private JdbcRegistryProperties jdbcRegistryProperties; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private JdbcOperator jdbcOperator; |
||||||
|
|
||||||
|
@Override |
||||||
|
public JdbcRegistry createRegistry() { |
||||||
|
return new JdbcRegistry(jdbcRegistryProperties, jdbcOperator); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry.jdbc; |
||||||
|
|
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.DriverManager; |
||||||
|
import java.sql.Statement; |
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
import lombok.SneakyThrows; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll; |
||||||
|
import org.junit.jupiter.api.BeforeAll; |
||||||
|
import org.springframework.test.context.ActiveProfiles; |
||||||
|
import org.testcontainers.containers.GenericContainer; |
||||||
|
import org.testcontainers.containers.MySQLContainer; |
||||||
|
import org.testcontainers.containers.Network; |
||||||
|
import org.testcontainers.containers.wait.strategy.Wait; |
||||||
|
import org.testcontainers.lifecycle.Startables; |
||||||
|
import org.testcontainers.utility.DockerImageName; |
||||||
|
|
||||||
|
import com.google.common.collect.Lists; |
||||||
|
|
||||||
|
@ActiveProfiles("mysql") |
||||||
|
class MysqlJdbcRegistryTestCase extends JdbcRegistryTestCase { |
||||||
|
|
||||||
|
private static GenericContainer<?> mysqlContainer; |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@BeforeAll |
||||||
|
public static void setUpTestingServer() { |
||||||
|
mysqlContainer = new MySQLContainer(DockerImageName.parse("mysql:8.0")) |
||||||
|
.withUsername("root") |
||||||
|
.withPassword("root") |
||||||
|
.withDatabaseName("dolphinscheduler") |
||||||
|
.withNetwork(Network.newNetwork()) |
||||||
|
.withExposedPorts(3306) |
||||||
|
.waitingFor(Wait.forHealthcheck()); |
||||||
|
|
||||||
|
mysqlContainer.setPortBindings(Lists.newArrayList("3306:3306")); |
||||||
|
Startables.deepStart(Stream.of(mysqlContainer)).join(); |
||||||
|
|
||||||
|
try ( |
||||||
|
Connection connection = DriverManager.getConnection( |
||||||
|
"jdbc:mysql://localhost:3306/dolphinscheduler?useSSL=false&serverTimezone=UTC", "root", "root"); |
||||||
|
Statement statement = connection.createStatement();) { |
||||||
|
statement.execute( |
||||||
|
"CREATE TABLE `t_ds_jdbc_registry_data`\n" + |
||||||
|
"(\n" + |
||||||
|
" `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',\n" + |
||||||
|
" `data_key` varchar(256) NOT NULL COMMENT 'key, like zookeeper node path',\n" + |
||||||
|
" `data_value` text NOT NULL COMMENT 'data, like zookeeper node value',\n" |
||||||
|
+ |
||||||
|
" `data_type` tinyint(4) NOT NULL COMMENT '1: ephemeral node, 2: persistent node',\n" |
||||||
|
+ |
||||||
|
" `last_term` bigint NOT NULL COMMENT 'last term time',\n" + |
||||||
|
" `last_update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last update time',\n" |
||||||
|
+ |
||||||
|
" `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time',\n" |
||||||
|
+ |
||||||
|
" PRIMARY KEY (`id`),\n" + |
||||||
|
" unique (`data_key`)\n" + |
||||||
|
") ENGINE = InnoDB\n" + |
||||||
|
" DEFAULT CHARSET = utf8;"); |
||||||
|
statement.execute( |
||||||
|
"CREATE TABLE `t_ds_jdbc_registry_lock`\n" + |
||||||
|
"(\n" + |
||||||
|
" `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',\n" + |
||||||
|
" `lock_key` varchar(256) NOT NULL COMMENT 'lock path',\n" + |
||||||
|
" `lock_owner` varchar(256) NOT NULL COMMENT 'the lock owner, ip_processId',\n" + |
||||||
|
" `last_term` bigint NOT NULL COMMENT 'last term time',\n" + |
||||||
|
" `last_update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last update time',\n" |
||||||
|
+ |
||||||
|
" `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time',\n" |
||||||
|
+ |
||||||
|
" PRIMARY KEY (`id`),\n" + |
||||||
|
" unique (`lock_key`)\n" + |
||||||
|
") ENGINE = InnoDB\n" + |
||||||
|
" DEFAULT CHARSET = utf8;"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@AfterAll |
||||||
|
public static void tearDownTestingServer() { |
||||||
|
mysqlContainer.close(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry.jdbc; |
||||||
|
|
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.DriverManager; |
||||||
|
import java.sql.Statement; |
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
import lombok.SneakyThrows; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll; |
||||||
|
import org.junit.jupiter.api.BeforeAll; |
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||||
|
import org.springframework.boot.test.context.SpringBootTest; |
||||||
|
import org.springframework.test.context.ActiveProfiles; |
||||||
|
import org.testcontainers.containers.GenericContainer; |
||||||
|
import org.testcontainers.containers.Network; |
||||||
|
import org.testcontainers.containers.PostgreSQLContainer; |
||||||
|
import org.testcontainers.lifecycle.Startables; |
||||||
|
import org.testcontainers.utility.DockerImageName; |
||||||
|
|
||||||
|
import com.google.common.collect.Lists; |
||||||
|
|
||||||
|
@ActiveProfiles("postgresql") |
||||||
|
@SpringBootTest(classes = {JdbcRegistryProperties.class}) |
||||||
|
@SpringBootApplication(scanBasePackageClasses = JdbcRegistryProperties.class) |
||||||
|
public class PostgresqlJdbcRegistryTestCase extends JdbcRegistryTestCase { |
||||||
|
|
||||||
|
private static GenericContainer<?> postgresqlContainer; |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@BeforeAll |
||||||
|
public static void setUpTestingServer() { |
||||||
|
postgresqlContainer = new PostgreSQLContainer(DockerImageName.parse("postgres:16.0")) |
||||||
|
.withUsername("root") |
||||||
|
.withPassword("root") |
||||||
|
.withDatabaseName("dolphinscheduler") |
||||||
|
.withNetwork(Network.newNetwork()) |
||||||
|
.withExposedPorts(5432); |
||||||
|
postgresqlContainer.setPortBindings(Lists.newArrayList("5432:5432")); |
||||||
|
Startables.deepStart(Stream.of(postgresqlContainer)).join(); |
||||||
|
|
||||||
|
try ( |
||||||
|
Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/dolphinscheduler", |
||||||
|
"root", "root"); |
||||||
|
Statement statement = connection.createStatement();) { |
||||||
|
statement.execute( |
||||||
|
"create table t_ds_jdbc_registry_data\n" + |
||||||
|
"(\n" + |
||||||
|
" id serial\n" + |
||||||
|
" constraint t_ds_jdbc_registry_data_pk primary key,\n" + |
||||||
|
" data_key varchar not null,\n" + |
||||||
|
" data_value text not null,\n" + |
||||||
|
" data_type int4 not null,\n" + |
||||||
|
" last_term bigint not null,\n" + |
||||||
|
" last_update_time timestamp default current_timestamp not null,\n" + |
||||||
|
" create_time timestamp default current_timestamp not null\n" + |
||||||
|
");"); |
||||||
|
statement.execute( |
||||||
|
"create unique index t_ds_jdbc_registry_data_key_uindex on t_ds_jdbc_registry_data (data_key);"); |
||||||
|
statement.execute( |
||||||
|
"create table t_ds_jdbc_registry_lock\n" + |
||||||
|
"(\n" + |
||||||
|
" id serial\n" + |
||||||
|
" constraint t_ds_jdbc_registry_lock_pk primary key,\n" + |
||||||
|
" lock_key varchar not null,\n" + |
||||||
|
" lock_owner varchar not null,\n" + |
||||||
|
" last_term bigint not null,\n" + |
||||||
|
" last_update_time timestamp default current_timestamp not null,\n" + |
||||||
|
" create_time timestamp default current_timestamp not null\n" + |
||||||
|
");"); |
||||||
|
statement.execute( |
||||||
|
"create unique index t_ds_jdbc_registry_lock_key_uindex on t_ds_jdbc_registry_lock (lock_key);"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@AfterAll |
||||||
|
public static void tearDownTestingServer() { |
||||||
|
postgresqlContainer.close(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
# |
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
# contributor license agreements. See the NOTICE file distributed with |
||||||
|
# this work for additional information regarding copyright ownership. |
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
# (the "License"); you may not use this file except in compliance with |
||||||
|
# the License. You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
# |
||||||
|
spring: |
||||||
|
sql: |
||||||
|
init: |
||||||
|
schema-locations: classpath:mysql_registry_init.sql |
||||||
|
datasource: |
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver |
||||||
|
url: jdbc:mysql://localhost:3306/dolphinscheduler?useUnicode=true&characterEncoding=UTF-8 |
||||||
|
username: root |
||||||
|
password: root |
||||||
|
|
||||||
|
registry: |
||||||
|
type: jdbc |
||||||
|
term-refresh-interval: 1s |
||||||
|
term-expire-times: 1 |
||||||
|
|
@ -0,0 +1,28 @@ |
|||||||
|
# |
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
# contributor license agreements. See the NOTICE file distributed with |
||||||
|
# this work for additional information regarding copyright ownership. |
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
# (the "License"); you may not use this file except in compliance with |
||||||
|
# the License. You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
# |
||||||
|
spring: |
||||||
|
datasource: |
||||||
|
driver-class-name: org.postgresql.Driver |
||||||
|
url: jdbc:postgresql://localhost:5432/dolphinscheduler |
||||||
|
username: root |
||||||
|
password: root |
||||||
|
|
||||||
|
registry: |
||||||
|
type: jdbc |
||||||
|
term-refresh-interval: 1s |
||||||
|
term-expire-times: 1 |
||||||
|
|
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -1,131 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.apache.dolphinscheduler.plugin.registry.zookeeper; |
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.registry.api.Event; |
|
||||||
import org.apache.dolphinscheduler.registry.api.SubscribeListener; |
|
||||||
|
|
||||||
import org.apache.curator.test.TestingServer; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.List; |
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.TimeUnit; |
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach; |
|
||||||
import org.junit.jupiter.api.Assertions; |
|
||||||
import org.junit.jupiter.api.BeforeEach; |
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
|
|
||||||
public class ZookeeperRegistryTest { |
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ZookeeperRegistryTest.class); |
|
||||||
|
|
||||||
TestingServer server; |
|
||||||
|
|
||||||
ZookeeperRegistry registry; |
|
||||||
|
|
||||||
@BeforeEach |
|
||||||
public void before() throws Exception { |
|
||||||
server = new TestingServer(true); |
|
||||||
|
|
||||||
ZookeeperRegistryProperties p = new ZookeeperRegistryProperties(); |
|
||||||
p.getZookeeper().setConnectString(server.getConnectString()); |
|
||||||
registry = new ZookeeperRegistry(p); |
|
||||||
registry.start(); |
|
||||||
registry.put("/sub", "", false); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void persistTest() { |
|
||||||
registry.put("/nodes/m1", "", false); |
|
||||||
registry.put("/nodes/m2", "", false); |
|
||||||
Assertions.assertEquals(Arrays.asList("m2", "m1"), registry.children("/nodes")); |
|
||||||
Assertions.assertTrue(registry.exists("/nodes/m1")); |
|
||||||
registry.delete("/nodes/m2"); |
|
||||||
Assertions.assertFalse(registry.exists("/nodes/m2")); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void lockTest() throws InterruptedException { |
|
||||||
CountDownLatch preCountDownLatch = new CountDownLatch(1); |
|
||||||
CountDownLatch allCountDownLatch = new CountDownLatch(2); |
|
||||||
List<String> testData = new ArrayList<>(); |
|
||||||
new Thread(() -> { |
|
||||||
registry.acquireLock("/lock"); |
|
||||||
preCountDownLatch.countDown(); |
|
||||||
logger.info(Thread.currentThread().getName() |
|
||||||
+ " :I got the lock, but I don't want to work. I want to rest for a while"); |
|
||||||
try { |
|
||||||
Thread.sleep(1000); |
|
||||||
logger.info(Thread.currentThread().getName() + " :I'm going to start working"); |
|
||||||
testData.add("thread1"); |
|
||||||
|
|
||||||
} catch (InterruptedException e) { |
|
||||||
Thread.currentThread().interrupt(); |
|
||||||
} finally { |
|
||||||
logger.info(Thread.currentThread().getName() + " :I have finished my work, now I release the lock"); |
|
||||||
registry.releaseLock("/lock"); |
|
||||||
allCountDownLatch.countDown(); |
|
||||||
} |
|
||||||
}).start(); |
|
||||||
preCountDownLatch.await(5, TimeUnit.SECONDS); |
|
||||||
new Thread(() -> { |
|
||||||
try { |
|
||||||
logger.info(Thread.currentThread().getName() + " :I am trying to acquire the lock"); |
|
||||||
registry.acquireLock("/lock"); |
|
||||||
logger.info(Thread.currentThread().getName() + " :I got the lock and I started working"); |
|
||||||
|
|
||||||
testData.add("thread2"); |
|
||||||
} finally { |
|
||||||
registry.releaseLock("/lock"); |
|
||||||
allCountDownLatch.countDown(); |
|
||||||
} |
|
||||||
|
|
||||||
}).start(); |
|
||||||
allCountDownLatch.await(5, TimeUnit.SECONDS); |
|
||||||
Assertions.assertEquals(testData, Arrays.asList("thread1", "thread2")); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void subscribeTest() { |
|
||||||
boolean status = registry.subscribe("/sub", new TestListener()); |
|
||||||
Assertions.assertTrue(status); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static class TestListener implements SubscribeListener { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void notify(Event event) { |
|
||||||
logger.info("I'm test listener"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@AfterEach |
|
||||||
public void after() throws IOException { |
|
||||||
registry.close(); |
|
||||||
server.close(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
* (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.apache.dolphinscheduler.plugin.registry.zookeeper; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.registry.RegistryTestCase; |
||||||
|
|
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
import lombok.SneakyThrows; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll; |
||||||
|
import org.junit.jupiter.api.BeforeAll; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||||
|
import org.springframework.boot.test.context.SpringBootTest; |
||||||
|
import org.testcontainers.containers.GenericContainer; |
||||||
|
import org.testcontainers.containers.Network; |
||||||
|
import org.testcontainers.lifecycle.Startables; |
||||||
|
import org.testcontainers.utility.DockerImageName; |
||||||
|
|
||||||
|
import com.google.common.collect.Lists; |
||||||
|
|
||||||
|
@SpringBootTest(classes = ZookeeperRegistryProperties.class) |
||||||
|
@SpringBootApplication(scanBasePackageClasses = ZookeeperRegistryProperties.class) |
||||||
|
class ZookeeperRegistryTestCase extends RegistryTestCase<ZookeeperRegistry> { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private ZookeeperRegistryProperties zookeeperRegistryProperties; |
||||||
|
|
||||||
|
private static GenericContainer<?> zookeeperContainer; |
||||||
|
|
||||||
|
private static final Network NETWORK = Network.newNetwork(); |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@BeforeAll |
||||||
|
public static void setUpTestingServer() { |
||||||
|
zookeeperContainer = new GenericContainer<>(DockerImageName.parse("zookeeper:3.8")) |
||||||
|
.withNetwork(NETWORK); |
||||||
|
|
||||||
|
zookeeperContainer.setPortBindings(Lists.newArrayList("2181:2181")); |
||||||
|
Startables.deepStart(Stream.of(zookeeperContainer)).join(); |
||||||
|
System.setProperty("registry.zookeeper.connect-string", "localhost:2181"); |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@Override |
||||||
|
public ZookeeperRegistry createRegistry() { |
||||||
|
return new ZookeeperRegistry(zookeeperRegistryProperties); |
||||||
|
} |
||||||
|
|
||||||
|
@SneakyThrows |
||||||
|
@AfterAll |
||||||
|
public static void tearDownTestingServer() { |
||||||
|
zookeeperContainer.close(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
# |
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
# contributor license agreements. See the NOTICE file distributed with |
||||||
|
# this work for additional information regarding copyright ownership. |
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
# (the "License"); you may not use this file except in compliance with |
||||||
|
# the License. You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
# |
||||||
|
|
||||||
|
registry: |
||||||
|
type: zookeeper |
||||||
|
zookeeper: |
||||||
|
namespace: dolphinscheduler |
||||||
|
connect-string: 127.0.0.1:2181 |
||||||
|
retry-policy: |
||||||
|
base-sleep-time: 60ms |
||||||
|
max-sleep: 300ms |
||||||
|
max-retries: 5 |
||||||
|
session-timeout: 30s |
||||||
|
connection-timeout: 9s |
||||||
|
block-until-connected: 600ms |
||||||
|
digest: ~ |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
~ contributor license agreements. See the NOTICE file distributed with |
||||||
|
~ this work for additional information regarding copyright ownership. |
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||||
|
~ (the "License"); you may not use this file except in compliance with |
||||||
|
~ the License. You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<configuration> |
||||||
|
<logger name="*" level="ERROR"/> |
||||||
|
</configuration> |
Loading…
Reference in new issue