[ https://issues.apache.org/jira/browse/IGNITE-21521?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Pavel Tupitsyn updated IGNITE-21521: ------------------------------------ Description: Add the following test to *ItInternalTableTest* to reproduce: {code:java} @Test public void upsertAllOrderTest() { RecordView<Tuple> view = table.recordView(); InternalTable internalTable = ((TableViewInternal) table).internalTable(); List<BinaryRowEx> rows = new ArrayList<>(); int count = 100; int lastId = count - 1; long id = 12345; for (int i = 0; i < count; i++) { rows.add(createKeyValueRow(id, i, "row-" + i)); } internalTable.upsertAll(rows, null).join(); Tuple res = view.get(null, Tuple.create().set("key", id)); assertEquals(lastId, res.intValue("valInt")); assertEquals("row-" + lastId, res.stringValue("valStr")); } {code} As a user, I expect to observe the last value for the given key. Instead, there is a random value. This is caused by *PartitionReplicaListener* - when there is no row with specified key, we generate a new random *RowId*: {code:java} RowId rowId0 = insert ? new RowId(partId(), UUID.randomUUID()) : rowId {code} Then this row id is stored in a hash set, which results in a random update order. The same applies to the *DataStreamer*, which goes through *InternalTableImpl.updateAll*. was: Add the following test to *ItInternalTableTest* to reproduce: {code:java} @Test public void upsertAllOrderTest() { RecordView<Tuple> view = table.recordView(); InternalTable internalTable = ((TableViewInternal) table).internalTable(); List<BinaryRowEx> rows = new ArrayList<>(); int count = 100; int lastId = count - 1; long id = 12345; for (int i = 0; i < count; i++) { rows.add(createKeyValueRow(id, i, "row-" + i)); } internalTable.upsertAll(rows, null).join(); Tuple res = view.get(null, Tuple.create().set("key", id)); assertEquals(lastId, res.intValue("valInt")); assertEquals("row-" + lastId, res.stringValue("valStr")); } {code} As a user, I expect the last value for the given key to be applied. Instead, a random value will be used. This is caused by *PartitionReplicaListener* - when there is no row with specified key, we generate a new random *RowId*: {code:java} RowId rowId0 = insert ? new RowId(partId(), UUID.randomUUID()) : rowId {code} Then this row id is stored in a hash set, which results in a random update order. The same applies to the *DataStreamer*, which goes through *InternalTableImpl.updateAll*. > Wrong update order in upsertAll and DataStreamer for a new key > -------------------------------------------------------------- > > Key: IGNITE-21521 > URL: https://issues.apache.org/jira/browse/IGNITE-21521 > Project: Ignite > Issue Type: Bug > Affects Versions: 3.0.0-beta1 > Reporter: Pavel Tupitsyn > Assignee: Pavel Tupitsyn > Priority: Major > Labels: ignite-3 > Fix For: 3.0.0-beta2 > > > Add the following test to *ItInternalTableTest* to reproduce: > {code:java} > @Test > public void upsertAllOrderTest() { > RecordView<Tuple> view = table.recordView(); > InternalTable internalTable = ((TableViewInternal) > table).internalTable(); > List<BinaryRowEx> rows = new ArrayList<>(); > int count = 100; > int lastId = count - 1; > long id = 12345; > for (int i = 0; i < count; i++) { > rows.add(createKeyValueRow(id, i, "row-" + i)); > } > internalTable.upsertAll(rows, null).join(); > Tuple res = view.get(null, Tuple.create().set("key", id)); > assertEquals(lastId, res.intValue("valInt")); > assertEquals("row-" + lastId, res.stringValue("valStr")); > } > {code} > As a user, I expect to observe the last value for the given key. Instead, > there is a random value. > This is caused by *PartitionReplicaListener* - when there is no row with > specified key, we generate a new random *RowId*: > {code:java} > RowId rowId0 = insert ? new RowId(partId(), UUID.randomUUID()) : rowId > {code} > Then this row id is stored in a hash set, which results in a random update > order. The same applies to the *DataStreamer*, which goes through > *InternalTableImpl.updateAll*. -- This message was sent by Atlassian Jira (v8.20.10#820010)