You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ignite.apache.org by "Alexey Kukushkin (Jira)" <ji...@apache.org> on 2020/04/14 20:11:00 UTC
[jira] [Created] (IGNITE-12898) Server node with CacheStore fails
to re-join the cluster: IgniteCheckedException: Cannot enable read-through
(loader or store is not provided) for cache
Alexey Kukushkin created IGNITE-12898:
-----------------------------------------
Summary: Server node with CacheStore fails to re-join the cluster: IgniteCheckedException: Cannot enable read-through (loader or store is not provided) for cache
Key: IGNITE-12898
URL: https://issues.apache.org/jira/browse/IGNITE-12898
Project: Ignite
Issue Type: Bug
Affects Versions: 2.8
Reporter: Alexey Kukushkin
If a cache with external persistence is dynamically created on a non-affinity node then the cache affinity node cannot join the cluster after restart.
h2. Repro Steps
# Run an "empty" Ignite node where no cache is going to be started
# Run a cache affinity node having the "ROLE" attribute set to "DATA"
# Create the cache from the "empty" node and use a Node Filter to limit the cache to the "data" node. External persistence is configured for the cache.
# Restart the "data" node
h3. Actual Result
{{IgniteCheckedException: Cannot enable read-through (loader or store is not provided) for cache}}
h2. Reproducer
h3. Reproducer.java
{code:java}
public class Reproducer {
@Test
public void test() throws Exception {
final String DB_URL = "jdbc:h2:mem:test";
final String ENTITY_NAME = "Person";
Function<String, IgniteConfiguration> igniteCfgFactory = instanceName ->
new IgniteConfiguration()
.setIgniteInstanceName(instanceName)
.setDiscoverySpi(new TcpDiscoverySpi()
.setIpFinder(new TcpDiscoveryVmIpFinder().setAddresses(Collections.singleton("127.0.0.1:47500")))
);
// 1. Run an "empty" Ignite node where no cache is going to be started
try (Connection dbConn = DriverManager.getConnection(DB_URL, "sa", "");
Statement dbStmt = dbConn.createStatement();
Ignite emptyNode = Ignition.start(igniteCfgFactory.apply("emptyyNode"))) {
// 2. Run a "Person" cache affinity node having the "ROLE" attribute set to "DATA"
Map<String, Object> dataNodeAttrs = new HashMap<>(1);
dataNodeAttrs.put(DataNodeFilter.ATTR_NAME, DataNodeFilter.ATTR_VAL);
Ignite dataNode = Ignition.start(igniteCfgFactory.apply("dataNode").setUserAttributes(dataNodeAttrs));
// 3. Create the "Person" cache from the "empty" node and use a Node Filter to limit the cache to the
// "data" node. External persistence to the "Person" table in H2 DB is configured for the cache.
dbStmt.execute("CREATE TABLE " + ENTITY_NAME + " (id int PRIMARY KEY, name varchar)");
CacheJdbcPojoStoreFactory<Integer, BinaryObject> igniteStoreFactory = new CacheJdbcPojoStoreFactory<>();
igniteStoreFactory.setDataSourceFactory(() -> JdbcConnectionPool.create(DB_URL, "sa", ""))
.setTypes(
new JdbcType()
.setCacheName(ENTITY_NAME)
.setDatabaseTable(ENTITY_NAME)
.setKeyType(Integer.class)
.setValueType(ENTITY_NAME)
.setKeyFields(new JdbcTypeField(java.sql.Types.INTEGER, "id", Integer.class, "id"))
.setValueFields(
new JdbcTypeField(java.sql.Types.INTEGER, "id", Integer.class, "id"),
new JdbcTypeField(java.sql.Types.VARCHAR, "name", String.class, "name")
)
);
CacheConfiguration<Integer, BinaryObject> cacheCfg =
new CacheConfiguration<Integer, BinaryObject>(ENTITY_NAME)
.setCacheMode(CacheMode.REPLICATED)
.setCacheStoreFactory(igniteStoreFactory)
.setWriteThrough(true)
.setReadThrough(true)
.setNodeFilter(new DataNodeFilter());
emptyNode.createCache(cacheCfg).withKeepBinary();
// 4. Restart the "data" node
dataNode.close();
dataNode = Ignition.start(igniteCfgFactory.apply("node2").setUserAttributes(dataNodeAttrs));
dataNode.close();
}
}
private static class DataNodeFilter implements IgnitePredicate<ClusterNode> {
public static final String ATTR_NAME = "ROLE";
public static final String ATTR_VAL = "DATA";
@Override public boolean apply(ClusterNode node) {
Object role = node.attributes().get(ATTR_NAME);
return role != null && ATTR_VAL.equalsIgnoreCase(role.toString());
}
}
}
{code}
h3. build.gradle
{code:groovy}
dependencies {
compile group: 'org.apache.ignite', name: 'ignite-core', version: '2.8.0'
compile group: 'com.h2database', name: 'h2', version: '1.4.200'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
{code}
h2. Workaround
Create dynamic caches only on the affinity nodes or use "static" caches defined in ignite node configuration.
h2. Stack Trace
{code}
class org.apache.ignite.IgniteCheckedException: Cannot enable read-through (loader or store is not provided) for cache: Person
at org.apache.ignite.internal.processors.cache.ValidationOnNodeJoinUtils.validate(ValidationOnNodeJoinUtils.java:348)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.createCacheContext(GridCacheProcessor.java:1201)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareCacheContext(GridCacheProcessor.java:1995)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.lambda$prepareStartCaches$d40a1773$1(GridCacheProcessor.java:1830)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.lambda$prepareStartCaches$8(GridCacheProcessor.java:1754)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.lambda$prepareStartCaches$926b6886$1(GridCacheProcessor.java:1827)
at org.apache.ignite.internal.util.IgniteUtils.doInParallel(IgniteUtils.java:11157)
at org.apache.ignite.internal.util.IgniteUtils.doInParallel(IgniteUtils.java:11059)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareStartCaches(GridCacheProcessor.java:1822)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareStartCaches(GridCacheProcessor.java:1753)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.startCachesOnLocalJoin(GridCacheProcessor.java:1699)
at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.initCachesOnLocalJoin(GridDhtPartitionsExchangeFuture.java:994)
at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.init(GridDhtPartitionsExchangeFuture.java:847)
at org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager$ExchangeWorker.body0(GridCachePartitionExchangeManager.java:3172)
at org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager$ExchangeWorker.body(GridCachePartitionExchangeManager.java:3021)
at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:120)
at java.base/java.lang.Thread.run(Thread.java:834)
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)