This is an automated email from the ASF dual-hosted git repository.
apkhmv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 4da2b8ec59 IGNITE-19316 Fix ItIgnitePicocliCommandsTest (#2008)
4da2b8ec59 is described below
commit 4da2b8ec5905641a61ecf45a11658939ef2391ca
Author: Aleksandr Pakhomov <[email protected]>
AuthorDate: Wed May 3 16:02:10 2023 +0400
IGNITE-19316 Fix ItIgnitePicocliCommandsTest (#2008)
---------
Co-authored-by: Vadim Pakhnushev <[email protected]>
---
.../repl/executor/ItIgnitePicocliCommandsTest.java | 2 -
.../registry/impl/ClusterConfigRegistryImpl.java | 28 ++++-----
.../repl/registry/impl/JdbcUrlRegistryImpl.java | 4 +-
.../cli/core/repl/registry/impl/LazyObjectRef.java | 69 ++++++++++++++++++++++
.../repl/registry/impl/MetricRegistryImpl.java | 33 +++++------
.../repl/registry/impl/NodeConfigRegistryImpl.java | 29 ++++-----
.../repl/registry/impl/NodeNameRegistryImpl.java | 4 +-
.../core/repl/registry/impl/UnitsRegistryImpl.java | 37 +++++++-----
.../core/repl/registry/impl/LazyObjectRefTest.java | 61 +++++++++++++++++++
9 files changed, 196 insertions(+), 71 deletions(-)
diff --git
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
index 4d256fc364..2586a36d0e 100644
---
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
+++
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
@@ -52,7 +52,6 @@ import org.jline.reader.ParsedLine;
import org.jline.reader.impl.DefaultParser;
import org.jline.reader.impl.completer.SystemCompleter;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
@@ -63,7 +62,6 @@ import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mockito;
/** Integration test for all completions in interactive mode. */
-@Disabled("IGNITE-19351")
public class ItIgnitePicocliCommandsTest extends
CliCommandTestInitializedIntegrationBase {
private static final String DEFAULT_REST_URL = "http://localhost:10300";
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java
index 292ac24148..e6034c5d86 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java
@@ -20,8 +20,6 @@ package
org.apache.ignite.internal.cli.core.repl.registry.impl;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import jakarta.inject.Singleton;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.ignite.internal.cli.call.configuration.ClusterConfigShowCall;
import
org.apache.ignite.internal.cli.call.configuration.ClusterConfigShowCallInput;
import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
@@ -34,7 +32,7 @@ public class ClusterConfigRegistryImpl implements
ClusterConfigRegistry, AsyncSe
private final ClusterConfigShowCall clusterConfigShowCall;
- private final AtomicReference<Config> config = new AtomicReference<>(null);
+ private LazyObjectRef<Config> configRef;
public ClusterConfigRegistryImpl(ClusterConfigShowCall
clusterConfigShowCall) {
this.clusterConfigShowCall = clusterConfigShowCall;
@@ -42,27 +40,25 @@ public class ClusterConfigRegistryImpl implements
ClusterConfigRegistry, AsyncSe
@Override
public void onConnect(SessionInfo sessionInfo) {
- CompletableFuture.runAsync(() -> {
- try {
- config.set(ConfigFactory.parseString(
- clusterConfigShowCall.execute(
-
ClusterConfigShowCallInput.builder().clusterUrl(sessionInfo.nodeUrl()).build()
- ).body().getValue()
- ));
- } catch (Exception ignored) {
- // no-op
- }
- });
+ configRef = new LazyObjectRef<>(() -> fetchConfig(sessionInfo));
+ }
+
+ private Config fetchConfig(SessionInfo sessionInfo) {
+ return ConfigFactory.parseString(
+ clusterConfigShowCall.execute(
+
ClusterConfigShowCallInput.builder().clusterUrl(sessionInfo.nodeUrl()).build()
+ ).body().getValue()
+ );
}
@Override
public void onDisconnect() {
-
+ configRef = null;
}
/** {@inheritDoc} */
@Override
public Config config() {
- return config.get();
+ return configRef == null ? null : configRef.get();
}
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java
index 80b6fc3d15..aa3711fab3 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java
@@ -91,7 +91,7 @@ public class JdbcUrlRegistryImpl implements JdbcUrlRegistry,
AsyncSessionEventLi
}
@Override
- public void onConnect(SessionInfo sessionInfo) {
+ public synchronized void onConnect(SessionInfo sessionInfo) {
if (executor == null) {
executor = Executors.newSingleThreadScheduledExecutor(new
NamedThreadFactory("JdbcUrlRegistry", log));
executor.scheduleWithFixedDelay(this::fetchJdbcUrls, 0, 5,
TimeUnit.SECONDS);
@@ -99,7 +99,7 @@ public class JdbcUrlRegistryImpl implements JdbcUrlRegistry,
AsyncSessionEventLi
}
@Override
- public void onDisconnect() {
+ public synchronized void onDisconnect() {
if (executor != null) {
shutdownAndAwaitTermination(executor, 3, TimeUnit.SECONDS);
executor = null;
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/LazyObjectRef.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/LazyObjectRef.java
new file mode 100644
index 0000000000..52df897149
--- /dev/null
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/LazyObjectRef.java
@@ -0,0 +1,69 @@
+/*
+ * 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.ignite.internal.cli.core.repl.registry.impl;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+import org.apache.ignite.internal.cli.logger.CliLoggers;
+import org.apache.ignite.internal.logger.IgniteLogger;
+import org.jetbrains.annotations.Nullable;
+
+/** Lazy async reference that will fetch the value from the source until the
value is not null. */
+public final class LazyObjectRef<R> {
+
+ private static final IgniteLogger LOG =
CliLoggers.forClass(LazyObjectRef.class);
+
+ private final Supplier<R> source;
+
+ private final AtomicReference<R> ref = new AtomicReference<>(null);
+
+ private final AtomicReference<Boolean> execInProgress = new
AtomicReference<>(false);
+
+ public LazyObjectRef(Supplier<R> source) {
+ this.source = source;
+ fetchFrom(source);
+ }
+
+ private void fetchFrom(Supplier<R> source) {
+ execInProgress.set(true);
+
+ CompletableFuture.supplyAsync(source)
+ .thenAccept(ref::set)
+ .whenComplete((v, t) -> {
+ if (t != null) {
+ LOG.warn("Got exception when fetch from source", t);
+ }
+ execInProgress.set(false);
+ });
+ }
+
+ /** Returns {@code null} if the fetching is in progress or the value
returned from the source is {@code null}. */
+ @Nullable
+ public R get() {
+ if (ref.get() == null && execInProgress.get()) {
+ return null;
+ }
+
+ if (ref.get() == null && !execInProgress.get()) {
+ fetchFrom(source);
+ }
+
+ return ref.get();
+ }
+}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/MetricRegistryImpl.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/MetricRegistryImpl.java
index f194120215..72422a16dc 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/MetricRegistryImpl.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/MetricRegistryImpl.java
@@ -20,13 +20,13 @@ package
org.apache.ignite.internal.cli.core.repl.registry.impl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
import
org.apache.ignite.internal.cli.call.node.metric.NodeMetricSourceListCall;
import org.apache.ignite.internal.cli.core.call.UrlCallInput;
import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
import org.apache.ignite.internal.cli.core.repl.SessionInfo;
import org.apache.ignite.internal.cli.core.repl.registry.MetricRegistry;
+import org.apache.ignite.rest.client.model.MetricSource;
/** Implementation of {@link MetricRegistry}. */
@Singleton
@@ -35,11 +35,13 @@ public class MetricRegistryImpl implements MetricRegistry,
AsyncSessionEventList
@Inject
private NodeMetricSourceListCall metricSourceListCall;
- private final Set<String> metricSources = ConcurrentHashMap.newKeySet();
+ private LazyObjectRef<Set<String>> metricSourcesRef;
@Override
public Set<String> metricSources() {
- return metricSources;
+ return (metricSourcesRef == null || metricSourcesRef.get() == null)
+ ? Set.of()
+ : metricSourcesRef.get();
}
/**
@@ -49,23 +51,18 @@ public class MetricRegistryImpl implements MetricRegistry,
AsyncSessionEventList
*/
@Override
public void onConnect(SessionInfo sessionInfo) {
- CompletableFuture.runAsync(() -> {
- try {
- //TODO https://issues.apache.org/jira/browse/IGNITE-17416
- metricSourceListCall.execute(new
UrlCallInput(sessionInfo.nodeUrl()))
- .body()
- .forEach(source ->
metricSources.add(source.getName()));
- } catch (Exception ignored) {
- // no-op
- }
- });
+ metricSourcesRef = new LazyObjectRef<>(() ->
fetchMetricSources(sessionInfo));
+ }
+
+ private Set<String> fetchMetricSources(SessionInfo sessionInfo) {
+ return metricSourceListCall.execute(new
UrlCallInput(sessionInfo.nodeUrl()))
+ .body().stream()
+ .map(MetricSource::getName)
+ .collect(Collectors.toSet());
}
- /**
- * Clears metric sources list.
- */
@Override
public void onDisconnect() {
- metricSources.clear();
+ metricSourcesRef = null;
}
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java
index 1f97fb22b1..b50f09790c 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java
@@ -20,8 +20,6 @@ package
org.apache.ignite.internal.cli.core.repl.registry.impl;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import jakarta.inject.Singleton;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.ignite.internal.cli.call.configuration.NodeConfigShowCall;
import
org.apache.ignite.internal.cli.call.configuration.NodeConfigShowCallInput;
import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
@@ -34,7 +32,7 @@ public class NodeConfigRegistryImpl implements
NodeConfigRegistry, AsyncSessionE
private final NodeConfigShowCall nodeConfigShowCall;
- private final AtomicReference<Config> config = new AtomicReference<>(null);
+ private LazyObjectRef<Config> configRef;
public NodeConfigRegistryImpl(NodeConfigShowCall nodeConfigShowCall) {
this.nodeConfigShowCall = nodeConfigShowCall;
@@ -42,28 +40,25 @@ public class NodeConfigRegistryImpl implements
NodeConfigRegistry, AsyncSessionE
@Override
public void onConnect(SessionInfo sessionInfo) {
- CompletableFuture.runAsync(() -> {
- try {
- config.set(ConfigFactory.parseString(
- nodeConfigShowCall.execute(
- // todo
https://issues.apache.org/jira/browse/IGNITE-17416
-
NodeConfigShowCallInput.builder().nodeUrl(sessionInfo.nodeUrl()).build()
- ).body().getValue())
- );
- } catch (Exception ignored) {
- // no-op
- }
- });
+ configRef = new LazyObjectRef<>(() -> fetchConfig(sessionInfo));
+ }
+
+ private Config fetchConfig(SessionInfo sessionInfo) {
+ return ConfigFactory.parseString(
+ nodeConfigShowCall.execute(
+ // todo
https://issues.apache.org/jira/browse/IGNITE-17416
+
NodeConfigShowCallInput.builder().nodeUrl(sessionInfo.nodeUrl()).build()
+ ).body().getValue());
}
@Override
public void onDisconnect() {
-
+ configRef = null;
}
/** {@inheritDoc} */
@Override
public Config config() {
- return this.config.get();
+ return configRef == null ? null : configRef.get();
}
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
index e0de828d6a..a38b3a7193 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
@@ -108,7 +108,7 @@ public class NodeNameRegistryImpl implements
NodeNameRegistry, AsyncSessionEvent
*/
@Override
- public void onConnect(SessionInfo sessionInfo) {
+ public synchronized void onConnect(SessionInfo sessionInfo) {
if (executor == null) {
executor = Executors.newSingleThreadScheduledExecutor(new
NamedThreadFactory("NodeNameRegistry", log));
executor.scheduleWithFixedDelay(() ->
@@ -120,7 +120,7 @@ public class NodeNameRegistryImpl implements
NodeNameRegistry, AsyncSessionEvent
* Stops pulling updates.
*/
@Override
- public void onDisconnect() {
+ public synchronized void onDisconnect() {
if (executor != null) {
shutdownAndAwaitTermination(executor, 3, TimeUnit.SECONDS);
executor = null;
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/UnitsRegistryImpl.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/UnitsRegistryImpl.java
index 8067077112..b72eadf527 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/UnitsRegistryImpl.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/UnitsRegistryImpl.java
@@ -19,11 +19,10 @@ package
org.apache.ignite.internal.cli.core.repl.registry.impl;
import jakarta.inject.Singleton;
import java.util.List;
+import java.util.Map;
import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
import org.apache.ignite.internal.cli.call.unit.ListUnitCall;
import org.apache.ignite.internal.cli.call.unit.UnitStatusRecord;
import org.apache.ignite.internal.cli.core.call.CallOutput;
@@ -40,7 +39,7 @@ public class UnitsRegistryImpl implements UnitsRegistry,
AsyncSessionEventListen
private final ListUnitCall call;
- private final ConcurrentMap<String, Set<String>> idToVersions = new
ConcurrentHashMap<>();
+ private LazyObjectRef<Map<String, Set<String>>> idToVersionsRef;
public UnitsRegistryImpl(ListUnitCall call) {
this.call = call;
@@ -48,34 +47,44 @@ public class UnitsRegistryImpl implements UnitsRegistry,
AsyncSessionEventListen
@Override
public void onConnect(SessionInfo sessionInfo) {
- CompletableFuture.runAsync(() -> updateState(sessionInfo.nodeUrl()));
+ updateState(sessionInfo.nodeUrl());
}
private void updateState(String url) {
- try {
- lastKnownUrl.set(url);
+ lastKnownUrl.set(url);
+
+ idToVersionsRef = new LazyObjectRef<>(() -> {
CallOutput<List<UnitStatusRecord>> output = call.execute(new
UrlCallInput(url));
if (!output.hasError() && !output.isEmpty()) {
- output.body().forEach(record -> idToVersions.put(record.id(),
record.versionToDeploymentInfo().keySet()));
+
+ return output.body().stream()
+ .collect(Collectors.toMap(
+ UnitStatusRecord::id,
+ record ->
record.versionToDeploymentInfo().keySet())
+ );
+ } else {
+ return null;
}
- } catch (Exception ignored) {
- // no-op
- }
+ });
}
@Override
public void onDisconnect() {
- idToVersions.clear();
+ idToVersionsRef = null;
}
@Override
public Set<String> versions(String unitId) {
- return idToVersions.get(unitId);
+ return (idToVersionsRef == null || idToVersionsRef.get() == null)
+ ? Set.of()
+ : idToVersionsRef.get().get(unitId);
}
@Override
public Set<String> ids() {
- return idToVersions.keySet();
+ return (idToVersionsRef == null || idToVersionsRef.get() == null)
+ ? Set.of()
+ : idToVersionsRef.get().keySet();
}
@Override
diff --git
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/registry/impl/LazyObjectRefTest.java
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/registry/impl/LazyObjectRefTest.java
new file mode 100644
index 0000000000..972f37fa1c
--- /dev/null
+++
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/registry/impl/LazyObjectRefTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ignite.internal.cli.core.repl.registry.impl;
+
+import static org.awaitility.Awaitility.await;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+import java.util.concurrent.CountDownLatch;
+import org.junit.jupiter.api.Test;
+
+class LazyObjectRefTest {
+
+ @Test
+ void returnsOk() {
+ // Given not throwing supplier
+ LazyObjectRef<String> ref = new LazyObjectRef<>(() -> "Hi");
+
+ // Expect returns value from supplier
+ await().untilAsserted(
+ () -> assertThat(ref.get(), equalTo("Hi"))
+ );
+ }
+
+ @Test
+ void returnsOkLazy() {
+ // Given supplier that returns a value only on a second call
+ CountDownLatch latch = new CountDownLatch(1);
+ LazyObjectRef<String> ref = new LazyObjectRef<>(() -> {
+ if (latch.getCount() == 1L) {
+ latch.countDown();
+ throw new RuntimeException();
+ } else {
+ return "Hi from the second attempt";
+ }
+ });
+
+ // When
+ await().untilAsserted(
+ () -> assertThat(ref.get(), equalTo("Hi from the second
attempt"))
+ );
+ // And the latch is counted down
+ assertThat(latch.getCount(), is(0L));
+ }
+}