This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 6721ab9d020 IGNITE-22464 Java thin client: Add events for client start
and stop - Fixes #11387.
6721ab9d020 is described below
commit 6721ab9d020a606a6fd5405dcbbc36909271526b
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu Jun 13 16:30:15 2024 +0500
IGNITE-22464 Java thin client: Add events for client start and stop - Fixes
#11387.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../ignite/client/events/ClientFailEvent.java | 54 +++++++++++++
.../ignite/client/events/ClientLifecycleEvent.java | 25 ++++++
.../events/ClientLifecycleEventListener.java | 44 ++++++++++
.../ignite/client/events/ClientStartEvent.java | 55 +++++++++++++
.../ignite/client/events/ClientStopEvent.java | 42 ++++++++++
.../internal/client/thin/TcpIgniteClient.java | 56 ++++++++++++-
.../IgniteClientLifecycleEventListenerTest.java | 94 ++++++++++++++++++++++
.../org/apache/ignite/client/ClientTestSuite.java | 2 +
8 files changed, 371 insertions(+), 1 deletion(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/client/events/ClientFailEvent.java
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientFailEvent.java
new file mode 100644
index 00000000000..a6e1592cee6
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientFailEvent.java
@@ -0,0 +1,54 @@
+/*
+ * 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.client.events;
+
+import org.apache.ignite.configuration.ClientConfiguration;
+
+/**
+ * Event, triggered when Ignite client is failed to start.
+ */
+public class ClientFailEvent implements ClientLifecycleEvent {
+ /** */
+ private final ClientConfiguration cfg;
+
+ /** */
+ private final Throwable throwable;
+
+ /**
+ * @param cfg Client configuration.
+ * @param throwable Throwable that caused the failure.
+ */
+ public ClientFailEvent(ClientConfiguration cfg, Throwable throwable) {
+ this.cfg = cfg;
+ this.throwable = throwable;
+ }
+
+ /**
+ * @return Client configuration.
+ */
+ public ClientConfiguration configuration() {
+ return cfg;
+ }
+
+ /**
+ * @return A cause of the failure.
+ */
+ public Throwable throwable() {
+ return throwable;
+ }
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/client/events/ClientLifecycleEvent.java
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientLifecycleEvent.java
new file mode 100644
index 00000000000..ffc277157c1
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientLifecycleEvent.java
@@ -0,0 +1,25 @@
+/*
+ * 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.client.events;
+
+/**
+ * Marker interface for all client's lifecycle events.
+ */
+public interface ClientLifecycleEvent {
+ // No-op.
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/client/events/ClientLifecycleEventListener.java
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientLifecycleEventListener.java
new file mode 100644
index 00000000000..98fe8080ac3
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientLifecycleEventListener.java
@@ -0,0 +1,44 @@
+/*
+ * 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.client.events;
+
+import java.util.EventListener;
+
+/** */
+public interface ClientLifecycleEventListener extends EventListener {
+ /**
+ * @param evt Client start event.
+ */
+ public default void onClientStart(ClientStartEvent evt) {
+ // No-op.
+ }
+
+ /**
+ * @param evt Client fail event.
+ */
+ public default void onClientFail(ClientFailEvent evt) {
+ // No-op.
+ }
+
+ /**
+ * @param evt Client stop event.
+ */
+ public default void onClientStop(ClientStopEvent evt) {
+ // No-op.
+ }
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/client/events/ClientStartEvent.java
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientStartEvent.java
new file mode 100644
index 00000000000..9aa71d55d6e
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientStartEvent.java
@@ -0,0 +1,55 @@
+/*
+ * 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.client.events;
+
+import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.configuration.ClientConfiguration;
+
+/**
+ * Event, triggered when Ignite client is started.
+ */
+public class ClientStartEvent implements ClientLifecycleEvent {
+ /** */
+ private final IgniteClient client;
+
+ /** */
+ private final ClientConfiguration cfg;
+
+ /**
+ * @param client Ignite client instance.
+ * @param cfg Client configuration.
+ */
+ public ClientStartEvent(IgniteClient client, ClientConfiguration cfg) {
+ this.client = client;
+ this.cfg = cfg;
+ }
+
+ /**
+ * @return Client configuration.
+ */
+ public ClientConfiguration configuration() {
+ return cfg;
+ }
+
+ /**
+ * @return Ignite client instance.
+ */
+ public IgniteClient client() {
+ return client;
+ }
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/client/events/ClientStopEvent.java
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientStopEvent.java
new file mode 100644
index 00000000000..5293f172556
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/client/events/ClientStopEvent.java
@@ -0,0 +1,42 @@
+/*
+ * 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.client.events;
+
+import org.apache.ignite.client.IgniteClient;
+
+/**
+ * Event, triggered when Ignite client is stopped.
+ */
+public class ClientStopEvent implements ClientLifecycleEvent {
+ /** */
+ private final IgniteClient client;
+
+ /**
+ * @param client Ignite client instance.
+ */
+ public ClientStopEvent(IgniteClient client) {
+ this.client = client;
+ }
+
+ /**
+ * @return Ignite client instance.
+ */
+ public IgniteClient client() {
+ return client;
+ }
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
index a4d9922143f..48c490198cb 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.client.thin;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.EventListener;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -50,6 +51,10 @@ import org.apache.ignite.client.ClientServices;
import org.apache.ignite.client.ClientTransactions;
import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.client.IgniteClientFuture;
+import org.apache.ignite.client.events.ClientFailEvent;
+import org.apache.ignite.client.events.ClientLifecycleEventListener;
+import org.apache.ignite.client.events.ClientStartEvent;
+import org.apache.ignite.client.events.ClientStopEvent;
import org.apache.ignite.configuration.BinaryConfiguration;
import org.apache.ignite.configuration.ClientConfiguration;
import org.apache.ignite.configuration.ClientTransactionConfiguration;
@@ -68,6 +73,7 @@ import
org.apache.ignite.internal.client.thin.io.ClientConnectionMultiplexer;
import org.apache.ignite.internal.processors.platform.client.ClientStatus;
import
org.apache.ignite.internal.processors.platform.client.IgniteClientException;
import org.apache.ignite.internal.util.GridArgumentCheck;
+import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.logger.NullLogger;
@@ -101,6 +107,9 @@ public class TcpIgniteClient implements IgniteClient {
/** Registered entry listeners for all caches. */
private final ClientCacheEntryListenersRegistry lsnrsRegistry;
+ /** Event listeners. */
+ private final EventListener[] evtLsnrs;
+
/** Marshaller. */
private final ClientBinaryMarshaller marsh;
@@ -140,6 +149,8 @@ public class TcpIgniteClient implements IgniteClient {
ch = new ReliableChannel(chFactory, cfg, binary);
+ evtLsnrs = cfg.getEventListeners() == null ? null :
cfg.getEventListeners().clone();
+
try {
ch.channelsInit();
@@ -177,6 +188,10 @@ public class TcpIgniteClient implements IgniteClient {
/** {@inheritDoc} */
@Override public void close() {
ch.close();
+
+ ClientStopEvent evt = new ClientStopEvent(this);
+
+ triggerLifecycleEventListeners(log, evtLsnrs, lsnr ->
lsnr.onClientStop(evt));
}
/** {@inheritDoc} */
@@ -423,7 +438,46 @@ public class TcpIgniteClient implements IgniteClient {
* @return Client with successfully opened thin client connection.
*/
public static IgniteClient start(ClientConfiguration cfg) throws
ClientException {
- return new TcpIgniteClient(cfg);
+ try {
+ TcpIgniteClient client = new TcpIgniteClient(cfg);
+
+ ClientStartEvent evt = new ClientStartEvent(client, cfg);
+
+ triggerLifecycleEventListeners(client.log, client.evtLsnrs, lsnr
-> lsnr.onClientStart(evt));
+
+ return client;
+ }
+ catch (Throwable throwable) {
+ ClientFailEvent evt = new ClientFailEvent(cfg, throwable);
+
+ triggerLifecycleEventListeners(cfg.getLogger(),
cfg.getEventListeners(), lsnr -> lsnr.onClientFail(evt));
+
+ throw throwable;
+ }
+ }
+
+ /** */
+ private static void triggerLifecycleEventListeners(
+ @Nullable IgniteLogger log,
+ EventListener[] lsnrs,
+ Consumer<ClientLifecycleEventListener> action
+ ) {
+ if (F.isEmpty(lsnrs))
+ return;
+
+ for (EventListener lsnr: lsnrs) {
+ if (lsnr instanceof ClientLifecycleEventListener) {
+ try {
+ ClientLifecycleEventListener lsnr0 =
(ClientLifecycleEventListener)lsnr;
+
+ action.accept(lsnr0);
+ }
+ catch (Exception e) {
+ if (log != null)
+ log.warning("Exception thrown while consuming event in
listener " + lsnr, e);
+ }
+ }
+ }
}
/**
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/events/IgniteClientLifecycleEventListenerTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/events/IgniteClientLifecycleEventListenerTest.java
new file mode 100644
index 00000000000..82e18d60433
--- /dev/null
+++
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/events/IgniteClientLifecycleEventListenerTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.client.thin.events;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.client.events.ClientFailEvent;
+import org.apache.ignite.client.events.ClientLifecycleEvent;
+import org.apache.ignite.client.events.ClientLifecycleEventListener;
+import org.apache.ignite.client.events.ClientStartEvent;
+import org.apache.ignite.client.events.ClientStopEvent;
+import org.apache.ignite.configuration.ClientConfiguration;
+import org.apache.ignite.internal.client.thin.AbstractThinClientTest;
+import org.junit.Test;
+
+/**
+ * Tests lifecycle event listeners of a thin client.
+ */
+public class IgniteClientLifecycleEventListenerTest extends
AbstractThinClientTest {
+ /** */
+ List<ClientLifecycleEvent> evts = new ArrayList<>();
+
+ /** {@inheritDoc} */
+ @Override protected ClientConfiguration getClientConfiguration() {
+ return super.getClientConfiguration()
+ .setEventListeners(new ClientLifecycleEventListener() {
+ @Override public void onClientStart(ClientStartEvent evt) {
+ evts.add(evt);
+ }
+
+ @Override public void onClientFail(ClientFailEvent evt) {
+ evts.add(evt);
+ }
+
+ @Override public void onClientStop(ClientStopEvent evt) {
+ evts.add(evt);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testClientLifecycleEvents() throws Exception {
+ evts.clear();
+
+ startGrids(3);
+
+ IgniteClient client0;
+
+ try (IgniteClient client = startClient(0, 1, 2)) {
+ client0 = client;
+
+ assertEquals(1, evts.size());
+ ClientLifecycleEvent evt0 = evts.get(0);
+ assertTrue(evt0 instanceof ClientStartEvent);
+ assertEquals(client, ((ClientStartEvent)evt0).client());
+ assertEquals(3,
((ClientStartEvent)evt0).configuration().getAddresses().length);
+ }
+
+ assertEquals(2, evts.size());
+ ClientLifecycleEvent evt1 = evts.get(1);
+ assertTrue(evt1 instanceof ClientStopEvent);
+ assertEquals(client0, ((ClientStopEvent)evt1).client());
+
+ try {
+
Ignition.startClient(getClientConfiguration().setAddresses("failure"));
+ fail();
+ }
+ catch (Exception e) {
+ assertEquals(3, evts.size());
+ ClientLifecycleEvent evt2 = evts.get(2);
+ assertTrue(evt2 instanceof ClientFailEvent);
+ assertEquals(1,
((ClientFailEvent)evt2).configuration().getAddresses().length);
+ assertEquals(e, ((ClientFailEvent)evt2).throwable());
+ }
+ }
+}
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
b/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
index a013e7f69b4..9329e2377b3 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
@@ -45,6 +45,7 @@ import
org.apache.ignite.internal.client.thin.ThinClientPartitionAwarenessStable
import
org.apache.ignite.internal.client.thin.ThinClientPartitionAwarenessUnstableTopologyTest;
import org.apache.ignite.internal.client.thin.TimeoutTest;
import
org.apache.ignite.internal.client.thin.events.IgniteClientConnectionEventListenerTest;
+import
org.apache.ignite.internal.client.thin.events.IgniteClientLifecycleEventListenerTest;
import
org.apache.ignite.internal.client.thin.events.IgniteClientRequestEventListenerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -90,6 +91,7 @@ import org.junit.runners.Suite;
MetadataRegistrationTest.class,
IgniteClientConnectionEventListenerTest.class,
IgniteClientRequestEventListenerTest.class,
+ IgniteClientLifecycleEventListenerTest.class,
ThinClientEnpointsDiscoveryTest.class,
InactiveClusterCacheRequestTest.class,
AffinityMetricsTest.class,