Our goal is to define a single place where all type information will reside. We define TypeConfiguration class which will have multiple type extensions for different features. This configuration will be set for the whole Ignite instance with ability to override it on per-cache level.
public class TypeConfiguration implements Serializable { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** * Type name. Can be one of three things: * - Simple type name. Use it when type is not in classpath; * - Fully qualified type name. Prefer it when type is in classpath to avoid conflicts. * E.g. "my.package.employee.Address", "my.package.organization.Address"; * - Package wildcard. Must ends with ".*" in this case. E.g. "my.package.*". */ private String typeName; /** Used to configure single type when it is not in classpath. */ public void setTypeName(String); /** Used to configure specific class. Both typeName and packageName fields will be set. */ public void setClass(Class); /** Affinity key field name. */ private String affKeyFieldName; /** Type info extensions. */ private Map<Class<? extends TypeInfo>, ? extends TypeInfo> typeInfos; public TypeInfo[] getTypeInfo() {...} public void setTypeInfo(TypeInfo... typeInfos) {...} public <T extends TypeInfo> T getTypeInfo(Class<T> infoCls) {...} }
Notes:
public interface TypeInfo extends Serializable { /** Whether implemenation supports single type. */ bool supportSingleType(); /** Whether implementation supports multiple types. */ bool supportMultipleTypes(); }
Notes:
public class PersistenceTypeInfo implements TypeInfo { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** Schema name in database. */ private String dbSchema; /** Table name in database. */ private String dbTbl; /** Persisted fields. */ private Collection<PersistenceField> fields; }
public class PersistenceField implements Serializable { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** Column name in database. */ private String dbFieldName; /** Column JDBC type in database. */ private int dbFieldType; /** Field name in java object. */ private String javaFieldName; /** Corresponding java type. */ private Class<?> javaFieldType; }
Notes:
public class PortableTypeInfo implements TypeInfo { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** ID mapper. */ private PortableIdMapper idMapper; /** Serializer. */ private PortableSerializer serializer; /** Portable metadata enabled flag. When disabled queries and pretty toString() will not work. */ private Boolean metaDataEnabled = true; }
Notes:
public class QueryTypeInfo implements TypeInfo { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** Fields. */ private QueryField[] flds; /** Group indexes. */ private QueryCompoundIndex[] grpIdxs; /** Fields to index as text. */ private String[] txtIdxs; }
public class QueryField implements Serializable { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** Field name. */ private String name; /** Field class. */ private Class cls; /** Whether to index the field. Disabled by default. */ private QueryFieldIndexType idxTyp = QueryFieldIndexType.NONE; }
public enum QueryFieldIndexType { /** Do not index the field. */ NONE, /** Ascending order. */ ASC, /** Descending order. */ DESC }
public class QueryCompoundIndex implements Serializable { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** Index name. */ String name; /** Participating fields. */ private QueryFieldInfo[] flds; }
Notes
QueryFieldInfo.cls is a problem for non-Java users, because they have to write ugly things like "java.lang.Integer" which is very hard to understand for non-Java users. Lets switch to enum here?
public class IgniteConfiguration { /** Type configurations. */ private TypeConfiguration[] typeCfg; public TypeConfiguration[] getTypeConfiguration(); public void setTypeConfiguration(TypeConfiguration... typeCfg); }
public class CacheConfiguration { /** Type configurations. */ private TypeConfiguration[] typeCfg; public TypeConfiguration[] getTypeConfiguration(); public void setTypeConfiguration(TypeConfiguration... typeCfg); }
21 Comments
Dmitriy Setrakyan
Alexey Goncharuk
Dmitriy Setrakyan
I like the latest version better. A few more comments:
useTs
flag inPortableTypeInfo
is no longer valid, as we use the most precise timestamp on every platformmetaDataEnabled
inPortableTypeInfo
makes sense (only if not having metadata renders better performance)CacheConfiguration.isKeepDeserialized()
method to allow caching deserialized values on-heap.QueryFieldInfo
class to simplify indexing configuration (similar toPersistenceFieldInfo
CacheConfiguration.setIndexedTypes(String, String, String...)
method to specify key-value pairs for indexing (in addition to the current method that acceptsClass<?>
parameters)setIndexedTypes(...)
method toCacheConfiguration.setIndexedTypes(Class<?>, Class<?>, Class<?>...)
to ensure that user provides at least a key-value type pair, which is the most common use case.Vladimir Ozerov
Folks,
I updated the design a bit. Please review it paying attention to notes after each section.
Two issues are still to be addressed:
Dmitriy Setrakyan
Looks very good. I made a few minor changes, e.g. added
Serializable
where it was missing, and also changedQueryField
to extendSerializable,
and notTypeInfo
.Vladimir Ozerov
Not so good, though
It looks like we should not put portable configuration here. First, portable configuration is always global, it cannot be defined on per-cache level. Second, normally user will configure portables with wildcards. On the other hand, neither QueryTypeInfo, not PersistenceTypeInfo make sense on global level. They are always configured on per-cache level. I cannot imagine a scenario when user will want to share them between different caches.
So we can configure portable separately on Ignite level, and queries/persistence on cache level. But this doesn't differ from current configuration much. Yes, it is a bit cleaner, but no major differences.
Dmitriy Setrakyan
I actually now believe that all the PersistenceTypeInfo configuration should go to the
CacheJdbcPojoStore
, which is the only place where it is used. This would leave us with only 2 things to cover:affinity-key
andquery-configuration
.Dmitriy Setrakyan
How about just having
CacheTypeConfiguration
which will have the optional affinity field and the query config:I do understand that we merge key-type and value-type into one SQL table for SQL queries. This can be supported by having the following 2 methods:
Thoughts?
Dmitriy Setrakyan
Here is an updated (better?) version of the configuration:
Here we decoupled query type configuration from affinity key configuration. The querying engine will still take advantage of the affinity key configuration during query execution.
Alexey Kuznetsov
About JdbcCacheStoreConfiguration.
I propose the following:
Dmitriy Setrakyan
The persistence design looks good. I think we are going to merge portable marshaller with regular marshaller, so I don't think we will need 2 factories. What is the current purpose of having 2 marshallers?
Alexey Kuznetsov
Dmitriy, thanks for pointing this. I did some investigations and let's discuss the following design:
Note, I think we could drop prefix "Cache" ? Class names will be shorter and anyway these classes will be in package org.apache.ignite.cache.store.jdbc;
Dmitriy Setrakyan
Alexey, do we really need such long names?
How about
JdbcTypeField
andJdbcType
?Sergei Vladykin
Guys,
I think query and indexing related configuration should look like the following:
Respectively cache in addition to setIndexedTypes method must have setQueryEntities method.
Dmitriy Setrakyan
Sergi, can you specify how to configure individual field indexes vs. group indexes?
Sergei Vladykin
They are different only by number of fields. The same thing.
Dmitriy Setrakyan
Now I am confused. Are you suggesting that a group index can contain different types of indexes, like so?
Also, how do I specify ASC vs DESC property?
Yakov Zhdanov
No, this is impossible with proposed API.
Dmitriy Setrakyan
I am generally OK with the design, except for the following:
QueryIndex
, as it will have direct impact on the usability.I would like to propose the following changes:
Alexey Kuznetsov
Dmitry, in case of FULLTEXT and GEOSPATIAL indexes, there no such settings as ASC and DESC.
So, for such indexes I should set NULL?
I, personally, prefer Sergi way.
Dmitriy Setrakyan
I think this can be handled with convenience setters and constructors as shown above.