To clarify: you can use a different AffinityFunction implementation on the
client side. It just has to map to the same binary typeId.
Even if there is a legacy setup with AffinityKeyMapper on servers, you can
craft an AffinityFunction for the client that achieves correct behavior.
So I believe this should cover any use case.

On Thu, Jul 7, 2022 at 10:36 PM Pavel Tupitsyn <ptupit...@apache.org> wrote:

> AffinityKeyMapper is just a subset of AffinityFunction, isn't it?
> So by supporting AffinityFunction we cover all AffinityKeyMapper use cases.
>
>
> > managing the classpath, a user should always keep in mind it
> I don't consider this a problem. This is how Java works, what can we do?
> You can also stick the class into BinaryConfiguration on the client to
> make it explicit and make sure it is loaded.
>
> > it still possible having user bad implementations of AffinityFunction
> that can't be easily instantiated;
> It is also possible to provide a bad implementation of ToIntFunction, no
> difference.
>
> > a question - what we should do in case of class instantiating loading
> fails?
> Currently we don't fail on custom affinity, right? So we should keep this
> behavior. Print a warning.
>
> On Thu, Jul 7, 2022 at 10:27 PM Maxim Muzafarov <mmu...@apache.org> wrote:
>
>> Pavel,
>>
>>
>> Yes, you're right that AffinityKeyMapper is deprecated, this is sad to
>> say but it still used.
>>
>> Let me describe the cases in more detail. In general, we have
>> customers which are using:
>>
>> 1. an own custom AffinityFunction;
>> 2. the default RendezvousAffinityFunction + an own deprecated
>> AffinityKeyMapper;
>> 3. an own custom AffinityFunction + an own deprecated
>> AffinityKeyMapper (I doubt about this case);
>>
>> I'd like to provide a general solution that solves all the cases
>> mentioned above, thus we can't discuss only AffinityFunction. It
>> doesn't fit the initial goals.
>>
>>
>> > Can you please clarify the "tricky" part?
>>
>> Yes, from my point of view the tricky part here is:
>>
>> - managing the classpath, a user should always keep in mind it;
>> - it still possible having user bad implementations of
>> AffinityFunction that can't be easily instantiated;
>> - a question - what we should do in case of class instantiating
>> loading fails? drop the client, print the warn or do nothing. These
>> solutions have a different impact on a production environment and user
>> may have different expectations on that;
>>
>>
>> I'm not saying that solution you suggested is bad, it just has some
>> drawbacks (like other solutions) and doesn't solves all the cases if
>> we're not instantiating a deprecated AffinityKeyMapper (which looks a
>> bit ugly for me too).
>>
>>
>> Actually, we are not limited with setting/instantiating
>> AffinityFunction. We can provide for a user a control on which channel
>> (node) a particular cache request will be executed (this thing also
>> have a drawback - a transactional operation cannot be executed on an
>> arbitrary node, it should be executed on node it's started).
>>
>> On Thu, 7 Jul 2022 at 21:41, Pavel Tupitsyn <ptupit...@apache.org> wrote:
>> >
>> > > AffinityKeyMapper (it will be required too)
>> > It is deprecated. We should not add any functionality on top of
>> deprecated
>> > stuff.
>> > Let's discuss only AffinityFunction.
>> >
>> > > this approach requires of these classes to be present on a thin client
>> > side and it can be tricky
>> > Any of the approaches discussed above requires some additional logic to
>> be
>> > present on the client.
>> > Can you please clarify the "tricky" part?
>> >
>> > All you need is to provide AffinityFunction implementation with a proper
>> > class name
>> > (or even use nameMapper/idMapper to map to a different name), it is no
>> > different from the ToIntFunction approach.
>> >
>> >
>> > On Thu, Jul 7, 2022 at 9:23 PM Maxim Muzafarov <mmu...@apache.org>
>> wrote:
>> >
>> > > Folks,
>> > >
>> > > I'd like also to mention since we are talking about a customer's
>> > > custom affinity function and affinity mapper implementations we could
>> > > face with some issues during these classes instantiation. It could
>> > > work for the customer which I've faced on, but I cannoun be sure that
>> > > this approach will work for all of the cases.
>> > >
>> > > I think it is better to avoid such an issues and leave it up to a
>> > > user. Nevertheless, the worst scenario for the user would be having 2
>> > > hops on each put/get as it was before this thread.
>> > >
>> > > On Thu, 7 Jul 2022 at 21:12, Maxim Muzafarov <mmu...@apache.org>
>> wrote:
>> > > >
>> > > > Folks,
>> > > >
>> > > > I'm not familiar with a thin client protocol, so, please, correct me
>> > > > if I'm wrong - is it possible sending classes over the network for
>> > > > different type of thin clients? It seems to me it will not work. I
>> > > > think it is possible to use class name/or type id and we are capable
>> > > > to instantiate both of the AffinityFunction and AffinityKeyMapper
>> (it
>> > > > will be required too) classes. However, this approach requires of
>> > > > these classes to be present on a thin client side and it can be
>> tricky
>> > > > to configure if this client is used inside a container (e.g. with
>> > > > spring data or something).
>> > > >
>> > > > Setting directly some kind of a known mapper looks more
>> > > > straightforward and error prone approach.
>> > > >
>> > > > Please, correct me if I am wrong.
>> > > >
>> > > > On Thu, 7 Jul 2022 at 21:02, Семён Данилов <samvi...@yandex.ru>
>> wrote:
>> > > > >
>> > > > > +1 to Pavel’s approach. Giving user the ability to set affinity
>> > > function that is potentially different from the one that is on server
>> > > doesn’t look good.
>> > > > >
>> > > > > I’d even go further and try sending the affinity function class
>> itself
>> > > over the network, so users won’t have to alter the classpath by
>> adding the
>> > > class that is not directly used in the codebase.
>> > > > > On 7 Jul 2022, 21:41 +0400, Pavel Tupitsyn <ptupit...@apache.org
>> >,
>> > > wrote:
>> > > > > > Can we actually avoid any public API changes and do the
>> following:
>> > > > > >
>> > > > > > When a feature flag is present and there is a custom affinity
>> > > function on
>> > > > > > the server, send back the class name (or binary type id, if
>> > > possible) of
>> > > > > > the affinity function?
>> > > > > > Then simply instantiate it on the client and call
>> `partition(Object
>> > > key)`
>> > > > > > on it?
>> > > > > >
>> > > > > > On Thu, Jul 7, 2022 at 8:32 PM Maxim Muzafarov <
>> mmu...@apache.org>
>> > > wrote:
>> > > > > >
>> > > > > > > Pavel,
>> > > > > > >
>> > > > > > > Here is my thoughts.
>> > > > > > >
>> > > > > > > As I mentioned before, we will need only the
>> > > > > > > AffinityFunction#partition(Object key) method for calculation
>> on
>> > > the
>> > > > > > > client side due to all the partition-to-node mappings will be
>> > > > > > > requested asynchronously from a server node how it is
>> happening now
>> > > > > > > for cache groups with the default affinity function. Thus
>> setting
>> > > the
>> > > > > > > AffinityFunction looks on the client side redundant and it
>> can be
>> > > > > > > transformed to a simple ToInFunction<Object> interface.
>> > > > > > >
>> > > > > > > public interface ToIntFunction<Object> {
>> > > > > > > int applyAsInt(Object key);
>> > > > > > > }
>> > > > > > >
>> > > > > > > Another point that I'd like also to mention is that the cache
>> > > already
>> > > > > > > created in a cluster, so it will be better to eliminate the
>> > > duplicate
>> > > > > > > affinity function configuration (setting the number of
>> > > partitions). It
>> > > > > > > is fully possible to receive the number of partitions from a
>> server
>> > > > > > > node (the same way as it currently happening). Thus instead
>> of the
>> > > > > > > ToInFunction<Object> interface it will be better to use
>> > > > > > > ToInBiFunction<Object, Integer>.
>> > > > > > >
>> > > > > > > public interface ToIntBiFunction<Object, Integer> {
>> > > > > > > int applyAsInt(Object key, Integer parts);
>> > > > > > > }
>> > > > > > >
>> > > > > > >
>> > > > > > > I agree with you that "setPartitionAwarenessKeyMapper" may be
>> is
>> > > not
>> > > > > > > good naming here, we can rename it and move it to the public
>> API,
>> > > of
>> > > > > > > course.
>> > > > > > >
>> > > > > > > On Thu, 7 Jul 2022 at 20:06, Pavel Tupitsyn <
>> ptupit...@apache.org>
>> > > wrote:
>> > > > > > > >
>> > > > > > > > Maxim,
>> > > > > > > >
>> > > > > > > > I am confused. We were talking about a custom Affinity
>> Function.
>> > > > > > > > As you noted, AffinityKeyMapper is deprecated, why do we add
>> > > something
>> > > > > > > > named "setPartitionAwarenessKeyMapper"?
>> > > > > > > >
>> > > > > > > > Internal API approach is hacky.
>> > > > > > > > IMO we should either develop a proper feature with a good
>> public
>> > > API, or
>> > > > > > > > not add anything at all.
>> > > > > > > >
>> > > > > > > > On Thu, Jul 7, 2022 at 6:34 PM Maxim Muzafarov <
>> > > mmu...@apache.org>
>> > > > > > > wrote:
>> > > > > > > >
>> > > > > > > > > Folks,
>> > > > > > > > >
>> > > > > > > > >
>> > > > > > > > > Thank you for your comments.
>> > > > > > > > >
>> > > > > > > > > First of all, I'd like to point out that if the cache is
>> > > created with
>> > > > > > > > > a custom affinity function or the legacy AffinityKeyMapper
>> > > interface,
>> > > > > > > > > the thin client should be able to provide only a
>> > > `key-to-partition`
>> > > > > > > > > mapping function to handle the case described above. The
>> > > > > > > > > `partition-to-node` mappings the client will receive from
>> a
>> > > server
>> > > > > > > > > node it connected to. This will simplify a bit the final
>> > > solution.
>> > > > > > > > >
>> > > > > > > > > ==================
>> > > > > > > > >
>> > > > > > > > > I've checked your suggestions and it looks like both of
>> them
>> > > have some
>> > > > > > > > > sufficient drawbacks:
>> > > > > > > > >
>> > > > > > > > > 1. Using SystemProperty looks really hacky and we are
>> > > explicitly
>> > > > > > > > > complicate a thin client configuration for an end user.
>> > > > > > > > >
>> > > > > > > > > 2. Extending the ClientCacheConfiguration is a very good
>> and
>> > > > > > > > > straightforward idea, however it doesn't fit the case
>> > > described above.
>> > > > > > > > > Caches previously created with custom affinity
>> functions/key
>> > > mappers
>> > > > > > > > > already present in the cluster, so in this case we are
>> forcing
>> > > a user
>> > > > > > > > > to store an additional ClientCacheConfiguration. This is
>> not
>> > > good. The
>> > > > > > > > > cache.getOrCreate(cfg) method will also be used and fire
>> in
>> > > turn
>> > > > > > > > > CACHE_GET_OR_CREATE_WITH_CONFIGURATION request which is
>> not
>> > > necessary
>> > > > > > > > > here. For this case using cache.name(str) is only enough.
>> > > > > > > > >
>> > > > > > > > > ==================
>> > > > > > > > >
>> > > > > > > > > I propose the following two solutions that looks very
>> > > promising:
>> > > > > > > > >
>> > > > > > > > > 3. Extending cache create methdos with a
>> ClientCacheContext in
>> > > the
>> > > > > > > > > IgniteClient interface. This context will contain all
>> > > additional cache
>> > > > > > > > > attributes like custom cache affinity mappers that map
>> cache
>> > > keys to
>> > > > > > > > > partitions if a custom affinity was used on the server
>> side
>> > > (note that
>> > > > > > > > > all partition-to-node mappings will be received by thin
>> client
>> > > from a
>> > > > > > > > > server node).
>> > > > > > > > >
>> > > > > > > > > interface IgniteClientEx extends IgniteClient {
>> > > > > > > > > ClientCache<K, V> name(String name, ClientCacheContext
>> cctx);
>> > > > > > > > > ClientCache<K, V> getOrCreateCache(String name,
>> > > ClientCacheContext
>> > > > > > > > > cctx);
>> > > > > > > > > ClientCache<K, V>
>> getOrCreateCache(ClientCacheConfiguration
>> > > cfg,
>> > > > > > > > > ClientCacheContext cctx);
>> > > > > > > > > }
>> > > > > > > > >
>> > > > > > > > > class ClientCacheContext {
>> > > > > > > > > setPartitionAwarenessKeyMapper(ToIntBiFunction<Object,
>> Integer>
>> > > > > > > > > mapper);
>> > > > > > > > > }
>> > > > > > > > >
>> > > > > > > > > 4. Use the same approach as the IgniteCache interface
>> does for
>> > > the
>> > > > > > > > > same things - adding withPartitionAwarenessKeyMapper() to
>> the
>> > > > > > > > > interface. This method will allow to configure the thin
>> client
>> > > > > > > > > execution behaviour for the partition awareness feature by
>> > > setting a
>> > > > > > > > > custom cache key mapper.
>> > > > > > > > >
>> > > > > > > > > ==================
>> > > > > > > > >
>> > > > > > > > > I've used the 4-th solution due to it brings much less
>> source
>> > > code to
>> > > > > > > > > the Apache Ignite codebase and looks a bit simpler to
>> > > configure for a
>> > > > > > > > > user. I've also move the withPartitionAwarenessKeyMapper()
>> > > method to
>> > > > > > > > > an internal API interface which still solves a user issue
>> with
>> > > the
>> > > > > > > > > partition awareness, but also specifies that the custom
>> mapping
>> > > > > > > > > function and deprecated AffinityKeyMapper should not be
>> used,
>> > > in
>> > > > > > > > > general.
>> > > > > > > > >
>> > > > > > > > > Please, take a look at my patch:
>> > > > > > > > >
>> > > > > > > > > https://issues.apache.org/jira/browse/IGNITE-17316
>> > > > > > > > > https://github.com/apache/ignite/pull/10140/files
>> > > > > > > > >
>> > > > > > > > >
>> > > > > > > > > On Fri, 1 Jul 2022 at 14:41, Pavel Tupitsyn <
>> > > ptupit...@apache.org>
>> > > > > > > wrote:
>> > > > > > > > > >
>> > > > > > > > > > I have no objections to extending the Thin Client
>> > > configuration with
>> > > > > > > a
>> > > > > > > > > > pluggable Affinity Function.
>> > > > > > > > > > Let's make it a normal Java setter though, system
>> properties
>> > > are
>> > > > > > > hacky.
>> > > > > > > > > > Especially when only some of the caches use custom
>> affinity,
>> > > as Maxim
>> > > > > > > > > > mentioned.
>> > > > > > > > > >
>> > > > > > > > > > On Wed, Jun 29, 2022 at 7:20 PM Николай Ижиков <
>> > > nizhi...@apache.org>
>> > > > > > > > > wrote:
>> > > > > > > > > >
>> > > > > > > > > > > +1 to have ability to specify custom affinity for PA
>> on
>> > > thin
>> > > > > > > client.
>> > > > > > > > > > >
>> > > > > > > > > > > It seems to me custom affinity is a rare use-case of
>> > > Ignite API.
>> > > > > > > > > > > Propose to have SystemProperty that can specify
>> affinity
>> > > > > > > implementation
>> > > > > > > > > > > for a thin client.
>> > > > > > > > > > >
>> > > > > > > > > > >
>> > > > > > > > > > > > 29 июня 2022 г., в 18:53, Maxim Muzafarov <
>> > > mmu...@apache.org>
>> > > > > > > > > > > написал(а):
>> > > > > > > > > > > >
>> > > > > > > > > > > > Igniters,
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > I've faced with a customer's cluster which has more
>> than
>> > > 150
>> > > > > > > nodes
>> > > > > > > > > and
>> > > > > > > > > > > > most for them are the thick-client nodes. Due to
>> each
>> > > > > > > thick-client is
>> > > > > > > > > > > > a full-fledged cluster topology participant it
>> affects
>> > > the
>> > > > > > > cluster
>> > > > > > > > > > > > discovery machinery during the system operation and
>> > > adding an
>> > > > > > > > > > > > additional overhead for using/deploying a new nodes
>> in
>> > > Kubernetes
>> > > > > > > > > > > > environment. However, the main thing from my point
>> of
>> > > view it
>> > > > > > > > > prevents
>> > > > > > > > > > > > updating the client side and server side components
>> > > independently
>> > > > > > > > > > > > (Apache Ignite doesn't support rolling upgrade).
>> > > > > > > > > > > >
>> > > > > > > > > > > > Accordingly to the assumptions above using thin
>> clients
>> > > become a
>> > > > > > > > > > > > necessary. This looks even more attractive, since
>> the
>> > > thin
>> > > > > > > client has
>> > > > > > > > > > > > a fairly rich API over the past few releases.
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > The MAIN ISSUE here that blocks thin client usage is
>> > > that for
>> > > > > > > some of
>> > > > > > > > > > > > cache groups a custom affinity function (and an
>> > > > > > > AffinityKeyMapper)
>> > > > > > > > > was
>> > > > > > > > > > > > used which prevents enabling the Partition Awareness
>> > > thin client
>> > > > > > > > > > > > feature. Thus each cache request will have two hops.
>> > > > > > > > > > > >
>> > > > > > > > > > > > Of course, we can force users to migrate to a new
>> API,
>> > > but this
>> > > > > > > > > > > > becomes more difficult when Apache Ignite is part
>> of a
>> > > much
>> > > > > > > larger
>> > > > > > > > > > > > architectural solution and thus it is doent' looks
>> so
>> > > friendly.
>> > > > > > > > > > > >
>> > > > > > > > > > > > The MAIN QUESTION here - does anyone know our users
>> who
>> > > have
>> > > > > > > > > > > > encountered with the same issue? I want to solve
>> such a
>> > > problem
>> > > > > > > once
>> > > > > > > > > > > > and make all such users happy by implementing the
>> general
>> > > > > > > approach.
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > = Possible solutions =
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > 1. Making an affinity function pluggable (mapping
>> > > calculations)
>> > > > > > > on
>> > > > > > > > > the
>> > > > > > > > > > > > thin clients side. Currently the
>> > > RendezvousAffinityFunction [1]
>> > > > > > > is
>> > > > > > > > > > > > only supported
>> > > > > > > > > > > > for the partition awareness. A user's affinity
>> function
>> > > seems to
>> > > > > > > be
>> > > > > > > > > > > > the stateless function due to there is no machinery
>> to
>> > > transfer
>> > > > > > > > > states
>> > > > > > > > > > > > to the thin client.
>> > > > > > > > > > > >
>> > > > > > > > > > > > Pros - a general solution for all such cases;
>> > > > > > > > > > > > Cons - unnecessary complexity, extending public API;
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > 2. Creating an Ignite extension which will extend
>> the
>> > > thin
>> > > > > > > client API
>> > > > > > > > > > > > thus a user will have a full control over a
>> destination
>> > > node to
>> > > > > > > which
>> > > > > > > > > > > > requests being sent.
>> > > > > > > > > > > >
>> > > > > > > > > > > > Pros - isolated solution, simple implementation;
>> > > > > > > > > > > > Cons - hard to support spring-boot-thin-client etc.
>> and
>> > > other
>> > > > > > > > > > > > extensions based on the thin client API;
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > Folks, please share your thoughts.
>> > > > > > > > > > > >
>> > > > > > > > > > > >
>> > > > > > > > > > > > [1]
>> > > > > > > > > > >
>> > > > > > > > >
>> > > > > > >
>> > >
>> https://github.com/apache/ignite/blob/master/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePartitionsRequest.java#L206
>> > > > > > > > > > >
>> > > > > > > > > > >
>> > > > > > > > >
>> > > > > > >
>> > >
>>
>

Reply via email to