apache / ignite

Apache Ignite
https://ignite.apache.org/
Apache License 2.0
4.83k stars 1.9k forks source link

Entry processor gets invoked twice even with backups=0 and atomicityMode=ATOMIC #11416

Closed Philosobyte closed 4 months ago

Philosobyte commented 5 months ago

On Ignite 2.16.0 with Java 21, entry processors invoked on empty caches seem to execute twice. I have created a simple example repo titled "ignite-duplicate-processing-test": https://github.com/Philosobyte/ignite-duplicate-processing-test/blob/main/src/test/java/com/philosobyte/igniteduplicateprocessingtest/DuplicateProcessingTest.java

In this example...

        @Bean
        public IgniteCache<LightsaberWielder, LightsaberColor> lightsaberColorsCache(Ignite ignite) {
            CacheConfiguration<LightsaberWielder, LightsaberColor> cacheConfig = new CacheConfiguration<>();
            cacheConfig.setName("lightsaber-colors");
            cacheConfig.setCacheMode(CacheMode.PARTITIONED);

            // make sure there are no backup partitions for an entry processor to execute on
            cacheConfig.setBackups(0);
            // even if there were backups, in ATOMIC mode, an entry processor should only execute on the primary partition
            cacheConfig.setAtomicityMode(CacheAtomicityMode.ATOMIC);

            return ignite.getOrCreateCache(cacheConfig);
        }
    // cache key
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class LightsaberWielder {
        String name;
    }

    // cache value
    public enum LightsaberColor {
        BLUE, RED
    }

This is the output:

2024-06-29T17:14:26.842-04:00  INFO 36880 --- [ignite-duplicate-processing-test] [    Test worker] c.p.i.DuplicateProcessingTest            : Processing on node b01f1c8d-b3dc-4f96-9ed1-7dcef02761e9 for key DuplicateProcessingTest.LightsaberWielder(name=anakin) and existing value null and random int: 1574068936
2024-06-29T17:14:26.842-04:00  INFO 36880 --- [ignite-duplicate-processing-test] [    Test worker] c.p.i.DuplicateProcessingTest            : Setting color to RED
2024-06-29T17:14:26.844-04:00  INFO 36880 --- [ignite-duplicate-processing-test] [    Test worker] c.p.i.DuplicateProcessingTest            : Processing on node b01f1c8d-b3dc-4f96-9ed1-7dcef02761e9 for key DuplicateProcessingTest.LightsaberWielder(name=anakin) and existing value null and random int: -666424287
2024-06-29T17:14:26.844-04:00  INFO 36880 --- [ignite-duplicate-processing-test] [    Test worker] c.p.i.DuplicateProcessingTest            : Setting color to BLUE
2024-06-29T17:14:26.850-04:00  INFO 36880 --- [ignite-duplicate-processing-test] [    Test worker] c.p.i.DuplicateProcessingTest            : replacementColor: BLUE

Note how there are two sets of log statements from the entry processor where I would normally expect just one. Interestingly, the result returned to the caller is always the result from the second execution instead of the first.

The reason this is a problem for us is we would have liked our entry processor not to be idempotent. This lets us optimize by not doing work when nothing has changed. If the entry processor executes twice, then the first execution will think "something has changed", then the second execution will think "nothing has changed", and then the return value will always tell the client "nothing has changed".

I would be happy to provide further information, and I appreciate any input.

P.S. this is the simplest example... in our business code, we ran into a bizarre case where passing different arguments to the entry processor affected whether the entry processor executed once or twice, even if the entry processor does not actually use the argument except to log the argument to console. For example, if we passed in an EmptyValue POJO containing no fields, the entry processor would execute once. If we passed in a much larger POJO containing maybe 1kB's worth of fields, the entry processor would execute twice. If there is interest, I can attempt to reproduce that more complicated case in a sample project, but I figured posting the simple example would suffice for now.

ptupitsyn commented 4 months ago

Discussed on the user list: https://lists.apache.org/thread/xbcnk17jrhvt278ps9mqo44n6z5jl24w

Please avoid asking the same question in multiple channels.