Aleksey Plekhanov created IGNITE-23190:
------------------------------------------
Summary: Client node deployment manager can be broken on client
disconnection
Key: IGNITE-23190
URL: https://issues.apache.org/jira/browse/IGNITE-23190
Project: Ignite
Issue Type: Bug
Reporter: Aleksey Plekhanov
Assignee: Aleksey Plekhanov
On client disconnect we call {{onDisconnected}} method for each grid component.
For {{GridDeploymentManager}} this callback stops and starts again deployment
stores (including local deployment store).
If some process registers a class between client disconnection and client
reconnection (default timeout between before reconnection is 10 seconds) - new
local deployment will be registered in local deployment store, but this
deployment will be binded to the old node id (node id is regenerated on
reconnect). All futher class registrations with the same local classloader will
use the same deployment and will throw an exception.
Reproducer:
{code:java}
@WithSystemProperty(key = IGNITE_DISCO_FAILED_CLIENT_RECONNECT_DELAY, value =
"1000")
public class IgniteClientReconnectDeploymentTest extends
IgniteClientReconnectAbstractTest {
/** {@inheritDoc} */
@Override protected int serverCount() {
return 1;
}
/** {@inheritDoc} */
@Override protected int clientCount() {
return 1;
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
return
super.getConfiguration(igniteInstanceName).setPeerClassLoadingEnabled(true);
}
/**
* @throws Exception If failed.
*/
@Test
public void testDeploy() throws Exception {
IgniteEx client = grid(serverCount());
Ignite srv = ignite(0);
IgniteCache<Integer, Integer> cache =
client.getOrCreateCache("test_cache");
reconnectClientNode(client, srv, () -> {
try {
client.context().deploy().deploy(TestEntryProcessor.class,
TestEntryProcessor.class.getClassLoader());
}
catch (IgniteCheckedException e) {
throw new AssertionError(e);
}
});
cache.invoke(0, new TestEntryProcessor());
}
/** */
private static class TestEntryProcessor implements EntryProcessor<Integer,
Integer, Boolean> {
/** {@inheritDoc} */
@Override public Boolean process(MutableEntry<Integer, Integer> entry,
Object... args) {
return true;
}
}
}
{code}
Shows a warning:
{noformat}
[WARN
][test-runner-#137%internal.IgniteClientReconnectDeploymentTest%][GridCacheDeploymentManager]
Should not use deployment to prepare deployable, because local node id does
not correspond with class loader id, and there are no more participants
[locNodeId=061e738c-b0d5-4f19-bef9-c220a77619a3,
deployment=GridDeploymentInfoBean
[clsLdrId=a1f5ca0e191-914c1515-3b63-4a33-bf76-efaf58300001, depMode=SHARED,
userVer=0, locDepOwner=false, participants=null],
deployable=GridNearAtomicSingleUpdateRequest [key=UserKeyCacheObjectImpl
[part=0, val=0, hasValBytes=true], super=GridNearAtomicSingleUpdateRequest
[key=UserKeyCacheObjectImpl [part=0, val=0, hasValBytes=true],
parent=GridNearAtomicAbstractSingleUpdateRequest
[nodeId=cf943568-0cf9-4848-9037-ed0f2e700000, futId=1,
topVer=AffinityTopologyVersion [topVer=4, minorTopVer=0],
parent=GridNearAtomicAbstractUpdateRequest [res=null, flags=needRes]]]],
locDep=GridDeployment [ts=1726051279184, depMode=SHARED,
clsLdr=sun.misc.Launcher$AppClassLoader@18b4aac2,
clsLdrId=a1f5ca0e191-914c1515-3b63-4a33-bf76-efaf58300001, userVer=0, loc=true,
sampleClsName=org.apache.ignite.internal.IgniteClientReconnectDeploymentTest$TestEntryProcessor,
pendingUndeploy=false, undeployed=false, usage=0]]
{noformat}
And throws an exception later:
{noformat}
javax.cache.CacheException: class
org.apache.ignite.internal.processors.cache.IgnitePeerToPeerClassLoadingException:
Failed to load class using class loader with given id (loader id doesn't match
sender id and there are no more participants)
[clsLdrId=a1f5ca0e191-914c1515-3b63-4a33-bf76-efaf58300001,
senderId=061e738c-b0d5-4f19-bef9-c220a77619a3, participants=null]
at
org.apache.ignite.internal.processors.cache.GridCacheUtils.convertToCacheException(GridCacheUtils.java:1207)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.cacheException(IgniteCacheProxyImpl.java:2090)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.invoke(IgniteCacheProxyImpl.java:1731)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.invoke(GatewayProtectedCacheProxy.java:1220)
~[classes/:?]
at
org.apache.ignite.internal.IgniteClientReconnectDeploymentTest.testDeploy(IgniteClientReconnectDeploymentTest.java:71)
~[test-classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
~[?:1.8.0_412]
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
~[?:1.8.0_412]
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
~[?:1.8.0_412]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_412]
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
~[junit-4.12.jar:4.12]
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
~[junit-4.12.jar:4.12]
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
~[junit-4.12.jar:4.12]
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
~[junit-4.12.jar:4.12]
at
org.apache.ignite.testframework.junits.GridAbstractTest$6.run(GridAbstractTest.java:2499)
~[test-classes/:?]
at java.lang.Thread.run(Thread.java:750) ~[?:1.8.0_412]
Caused by:
org.apache.ignite.internal.processors.cache.IgnitePeerToPeerClassLoadingException:
Failed to load class using class loader with given id (loader id doesn't match
sender id and there are no more participants)
[clsLdrId=a1f5ca0e191-914c1515-3b63-4a33-bf76-efaf58300001,
senderId=061e738c-b0d5-4f19-bef9-c220a77619a3, participants=null]
at
org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.p2pContext(GridCacheDeploymentManager.java:407)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GridCacheIoManager.unmarshall(GridCacheIoManager.java:1608)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GridCacheIoManager.onMessage0(GridCacheIoManager.java:592)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GridCacheIoManager.handleMessage(GridCacheIoManager.java:398)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GridCacheIoManager.handleMessage(GridCacheIoManager.java:316)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GridCacheIoManager.access$100(GridCacheIoManager.java:104)
~[classes/:?]
at
org.apache.ignite.internal.processors.cache.GridCacheIoManager$1.onMessage(GridCacheIoManager.java:306)
~[classes/:?]
at
org.apache.ignite.internal.managers.communication.GridIoManager.invokeListener(GridIoManager.java:1893)
~[classes/:?]
at
org.apache.ignite.internal.managers.communication.GridIoManager.processRegularMessage0(GridIoManager.java:1514)
~[classes/:?]
at
org.apache.ignite.internal.managers.communication.GridIoManager.access$5300(GridIoManager.java:240)
~[classes/:?]
at
org.apache.ignite.internal.managers.communication.GridIoManager$9.execute(GridIoManager.java:1418)
~[classes/:?]
at
org.apache.ignite.internal.managers.communication.TraceRunnable.run(TraceRunnable.java:55)
~[classes/:?]
at
org.apache.ignite.internal.util.StripedExecutor$Stripe.body(StripedExecutor.java:637)
~[classes/:?]
at
org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:125)
~[classes/:?]
{noformat}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)