This is an automated email from the ASF dual-hosted git repository.

tkalkirill pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 4177222f7f IGNITE-18408 Store replication protocol config as bytes in 
MvPartitionStorage (#1699)
4177222f7f is described below

commit 4177222f7fcb1ca901588030f29d8a502695fc4f
Author: Roman Puchkovskiy <[email protected]>
AuthorDate: Tue Feb 21 19:54:45 2023 +0400

    IGNITE-18408 Store replication protocol config as bytes in 
MvPartitionStorage (#1699)
---
 .../internal/storage/MvPartitionStorage.java       | 12 ++---
 .../internal/storage/engine/MvTableStorage.java    |  7 ++-
 .../storage/AbstractMvPartitionStorageTest.java    | 25 ++--------
 .../storage/AbstractMvTableStorageTest.java        | 37 +++++++-------
 .../storage/impl/TestMvPartitionStorage.java       | 19 ++++---
 .../internal/storage/impl/TestMvTableStorage.java  |  5 +-
 .../pagememory/AbstractPageMemoryTableStorage.java |  5 +-
 .../mv/AbstractPageMemoryMvPartitionStorage.java   |  3 +-
 .../mv/PersistentPageMemoryMvPartitionStorage.java | 30 ++---------
 .../mv/VolatilePageMemoryMvPartitionStorage.java   | 16 +++---
 ...PersistentPageMemoryMvPartitionStorageTest.java | 58 +++++++---------------
 .../storage/rocksdb/RocksDbMvPartitionStorage.java | 49 +++++++++---------
 .../storage/rocksdb/RocksDbTableStorage.java       |  5 +-
 .../distributed/raft/PartitionDataStorage.java     | 12 +----
 .../table/distributed/raft/PartitionListener.java  |  1 -
 .../distributed/raft}/RaftGroupConfiguration.java  |  2 +-
 .../raft/RaftGroupConfigurationConverter.java      | 51 +++++++++++++++++++
 .../distributed/raft/snapshot/PartitionAccess.java |  2 +-
 .../raft/snapshot/PartitionAccessImpl.java         | 13 +++--
 .../snapshot/PartitionSnapshotStorageFactory.java  |  2 +-
 .../snapshot/incoming/IncomingSnapshotCopier.java  |  2 +-
 .../raft/snapshot/outgoing/OutgoingSnapshot.java   |  2 +-
 .../SnapshotAwarePartitionDataStorage.java         | 12 ++---
 .../raft/snapshot/outgoing/SnapshotMetaUtils.java  |  2 +-
 .../raft/PartitionCommandListenerTest.java         | 11 +++-
 .../raft/RaftGroupConfigurationConverterTest.java  | 48 ++++++++++++++++++
 .../PartitionSnapshotStorageFactoryTest.java       |  2 +-
 .../incoming/IncomingSnapshotCopierTest.java       | 15 ++++--
 .../outgoing/OutgoingSnapshotCommonTest.java       |  2 +-
 .../outgoing/OutgoingSnapshotReaderTest.java       |  2 +-
 .../OutgoingSnapshotTxDataStreamingTest.java       |  2 +-
 .../outgoing/OutgoingSnapshotsManagerTest.java     |  2 +-
 .../SnapshotAwarePartitionDataStorageTest.java     | 25 +++++-----
 .../snapshot/outgoing/SnapshotMetaUtilsTest.java   |  2 +-
 .../distributed/TestPartitionDataStorage.java      | 12 ++---
 35 files changed, 264 insertions(+), 231 deletions(-)

diff --git 
a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
 
b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
index 307b1279d6..5bf5b9b9d3 100644
--- 
a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
+++ 
b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
@@ -101,20 +101,18 @@ public interface MvPartitionStorage extends 
ManuallyCloseable {
     long persistedIndex();
 
     /**
-     * Committed RAFT group configuration corresponding to the write command 
with the highest index applied to the storage.
+     * Byte representation of the committed replication protocol group 
configuration corresponding to the write command with the highest
+     * index applied to the storage.
      * {@code null} if it was never saved.
      */
-    @Nullable
-    // TODO: IGNITE-18408 - store bytes in the storage, not a configuration 
object
-    RaftGroupConfiguration committedGroupConfiguration();
+    byte @Nullable [] committedGroupConfiguration();
 
     /**
      * Updates RAFT group configuration.
      *
-     * @param config Configuration to save.
+     * @param config Byte representation of the configuration to save.
      */
-    // TODO: IGNITE-18408 - store bytes in the storage, not a configuration 
object
-    void committedGroupConfiguration(RaftGroupConfiguration config);
+    void committedGroupConfiguration(byte[] config);
 
     /**
      * Reads the value from the storage as it was at the given timestamp.
diff --git 
a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/MvTableStorage.java
 
b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/MvTableStorage.java
index c39831b8a2..341623ae47 100644
--- 
a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/MvTableStorage.java
+++ 
b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/MvTableStorage.java
@@ -30,7 +30,6 @@ import 
org.apache.ignite.internal.schema.configuration.TableConfiguration;
 import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
 import 
org.apache.ignite.internal.schema.configuration.index.TableIndexConfiguration;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageClosedException;
 import org.apache.ignite.internal.storage.StorageException;
@@ -202,7 +201,7 @@ public interface MvTableStorage extends ManuallyCloseable {
      * to one of the methods:
      * <ul>
      *     <li>{@link #abortRebalancePartition(int)} ()} - in case of errors 
or cancellation of rebalance;</li>
-     *     <li>{@link #finishRebalancePartition(int, long, long, 
RaftGroupConfiguration)} - in case of successful completion of rebalance.
+     *     <li>{@link #finishRebalancePartition(int, long, long, byte[])} - in 
case of successful completion of rebalance.
      *     </li>
      * </ul>
      *
@@ -247,7 +246,7 @@ public interface MvTableStorage extends ManuallyCloseable {
      *
      * @param lastAppliedIndex Last applied index.
      * @param lastAppliedTerm Last applied term.
-     * @param raftGroupConfig RAFT group configuration.
+     * @param groupConfig Replication protocol group configuration (byte 
representation).
      * @return Future of the finish rebalance for a multi-version partition 
storage and its indexes.
      * @throws IllegalArgumentException If Partition ID is out of bounds.
      * @throws StorageRebalanceException If there is an error when completing 
rebalance.
@@ -256,7 +255,7 @@ public interface MvTableStorage extends ManuallyCloseable {
             int partitionId,
             long lastAppliedIndex,
             long lastAppliedTerm,
-            RaftGroupConfiguration raftGroupConfig
+            byte[] groupConfig
     );
 
     /**
diff --git 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
index f1e1b7c867..437626a11a 100644
--- 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
+++ 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
@@ -1296,12 +1296,7 @@ public abstract class AbstractMvPartitionStorageTest 
extends BaseMvPartitionStor
 
     @Test
     void groupConfigurationIsSaved() {
-        RaftGroupConfiguration configToSave = new RaftGroupConfiguration(
-                List.of("peer1", "peer2"),
-                List.of("learner1", "learner2"),
-                List.of("old-peer1", "old-peer2"),
-                List.of("old-learner1", "old-learner2")
-        );
+        byte[] configToSave = {1, 2, 3};
 
         storage.runConsistently(() -> {
             storage.committedGroupConfiguration(configToSave);
@@ -1309,7 +1304,7 @@ public abstract class AbstractMvPartitionStorageTest 
extends BaseMvPartitionStor
             return null;
         });
 
-        RaftGroupConfiguration returnedConfig = 
storage.committedGroupConfiguration();
+        byte[] returnedConfig = storage.committedGroupConfiguration();
 
         assertThat(returnedConfig, is(notNullValue()));
         assertThat(returnedConfig, is(equalTo(configToSave)));
@@ -1317,12 +1312,7 @@ public abstract class AbstractMvPartitionStorageTest 
extends BaseMvPartitionStor
 
     @Test
     void groupConfigurationIsUpdated() {
-        RaftGroupConfiguration firstConfig = new RaftGroupConfiguration(
-                List.of("peer1", "peer2"),
-                List.of("learner1", "learner2"),
-                List.of("old-peer1", "old-peer2"),
-                List.of("old-learner1", "old-learner2")
-        );
+        byte[] firstConfig = {1, 2, 3};
 
         storage.runConsistently(() -> {
             storage.committedGroupConfiguration(firstConfig);
@@ -1330,12 +1320,7 @@ public abstract class AbstractMvPartitionStorageTest 
extends BaseMvPartitionStor
             return null;
         });
 
-        RaftGroupConfiguration secondConfig = new RaftGroupConfiguration(
-                List.of("peer3", "peer4"),
-                List.of("learner3", "learner4"),
-                List.of("old-peer3", "old-peer4"),
-                List.of("old-learner3", "old-learner4")
-        );
+        byte[] secondConfig = {3, 2, 1};
 
         storage.runConsistently(() -> {
             storage.committedGroupConfiguration(secondConfig);
@@ -1343,7 +1328,7 @@ public abstract class AbstractMvPartitionStorageTest 
extends BaseMvPartitionStor
             return null;
         });
 
-        RaftGroupConfiguration returnedConfig = 
storage.committedGroupConfiguration();
+        byte[] returnedConfig = storage.committedGroupConfiguration();
 
         assertThat(returnedConfig, is(notNullValue()));
         assertThat(returnedConfig, is(equalTo(secondConfig)));
diff --git 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
index e644696f00..ca17393233 100644
--- 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
+++ 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
@@ -34,6 +34,7 @@ import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
 import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -73,6 +74,7 @@ import 
org.apache.ignite.internal.storage.index.SortedIndexStorage;
 import org.apache.ignite.internal.util.Cursor;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.lang.IgniteTuple3;
+import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -433,7 +435,7 @@ public abstract class AbstractMvTableStorageTest extends 
BaseMvStoragesTest {
         // Error because reblance has not yet started for the partition.
         assertThrows(
                 StorageRebalanceException.class,
-                () -> tableStorage.finishRebalancePartition(PARTITION_ID, 100, 
500, mock(RaftGroupConfiguration.class))
+                () -> tableStorage.finishRebalancePartition(PARTITION_ID, 100, 
500, new byte[0])
         );
 
         List<IgniteTuple3<RowId, BinaryRow, HybridTimestamp>> 
rowsBeforeRebalanceStart = List.of(
@@ -465,16 +467,16 @@ public abstract class AbstractMvTableStorageTest extends 
BaseMvStoragesTest {
         // Partition is out of configuration range.
         assertThrows(
                 IllegalArgumentException.class,
-                () -> 
tableStorage.finishRebalancePartition(getPartitionIdOutOfRange(), 100, 500, 
mock(RaftGroupConfiguration.class))
+                () -> 
tableStorage.finishRebalancePartition(getPartitionIdOutOfRange(), 100, 500, new 
byte[0])
         );
 
         // Partition does not exist.
         assertThrows(
                 StorageRebalanceException.class,
-                () -> tableStorage.finishRebalancePartition(1, 100, 500, 
mock(RaftGroupConfiguration.class))
+                () -> tableStorage.finishRebalancePartition(1, 100, 500, new 
byte[0])
         );
 
-        RaftGroupConfiguration raftGroupConfig = 
createRandomRaftGroupConfiguration();
+        byte[] raftGroupConfig = createRandomRaftGroupConfiguration();
 
         assertThat(tableStorage.finishRebalancePartition(PARTITION_ID, 10, 20, 
raftGroupConfig), willCompleteSuccessfully());
 
@@ -665,7 +667,7 @@ public abstract class AbstractMvTableStorageTest extends 
BaseMvStoragesTest {
                 new IgniteTuple3<>(new RowId(PARTITION_ID), binaryRow(new 
TestKey(1, "1"), new TestValue(1, "1")), clock.now())
         );
 
-        RaftGroupConfiguration raftGroupConfig = 
createRandomRaftGroupConfiguration();
+        byte[] raftGroupConfig = createRandomRaftGroupConfiguration();
 
         fillStorages(mvPartitionStorage, hashIndexStorage, sortedIndexStorage, 
rows);
 
@@ -856,11 +858,11 @@ public abstract class AbstractMvTableStorageTest extends 
BaseMvStoragesTest {
 
         storage.runConsistently(() -> {
             assertThrows(StorageRebalanceException.class, () -> 
storage.lastApplied(100, 500));
-            assertThrows(StorageRebalanceException.class, () -> 
storage.committedGroupConfiguration(mock(RaftGroupConfiguration.class)));
+            assertThrows(StorageRebalanceException.class, () -> 
storage.committedGroupConfiguration(new byte[0]));
 
             assertThrows(
                     StorageRebalanceException.class,
-                    () -> 
storage.committedGroupConfiguration(mock(RaftGroupConfiguration.class))
+                    () -> storage.committedGroupConfiguration(new byte[0])
             );
 
             RowId rowId = new RowId(PARTITION_ID);
@@ -996,25 +998,20 @@ public abstract class AbstractMvTableStorageTest extends 
BaseMvStoragesTest {
         }
     }
 
-    private static RaftGroupConfiguration createRandomRaftGroupConfiguration() 
{
+    private static byte[] createRandomRaftGroupConfiguration() {
         Random random = new Random(System.currentTimeMillis());
 
-        return new RaftGroupConfiguration(
-                random.ints(random.nextInt(10)).mapToObj(i -> "peer" + 
i).collect(toList()),
-                random.ints(random.nextInt(10)).mapToObj(i -> "lerner" + 
i).collect(toList()),
-                random.ints(random.nextInt(10)).mapToObj(i -> "oldPeer" + 
i).collect(toList()),
-                random.ints(random.nextInt(10)).mapToObj(i -> "oldLerner" + 
i).collect(toList())
-        );
+        byte[] bytes = new byte[100];
+
+        random.nextBytes(bytes);
+
+        return bytes;
     }
 
-    private static void checkRaftGroupConfigs(RaftGroupConfiguration exp, 
RaftGroupConfiguration act) {
+    private static void checkRaftGroupConfigs(byte @Nullable [] exp, byte 
@Nullable [] act) {
         assertNotNull(exp);
         assertNotNull(act);
 
-        assertThat(act.peers(), equalTo(exp.peers()));
-        assertThat(act.learners(), equalTo(exp.learners()));
-
-        assertThat(act.oldPeers(), equalTo(exp.oldPeers()));
-        assertThat(act.oldLearners(), equalTo(exp.oldLearners()));
+        assertArrayEquals(exp, act);
     }
 }
diff --git 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
index 9be4441e0c..f1dbbb7478 100644
--- 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
+++ 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.storage.impl;
 
 import static java.util.Comparator.comparing;
 
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.NavigableSet;
 import java.util.NoSuchElementException;
@@ -32,7 +33,6 @@ import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.BinaryRowAndRowId;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.PartitionTimestampCursor;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageClosedException;
@@ -57,8 +57,7 @@ public class TestMvPartitionStorage implements 
MvPartitionStorage {
 
     private volatile long lastAppliedTerm;
 
-    @Nullable
-    private volatile RaftGroupConfiguration groupConfig;
+    private volatile byte @Nullable [] groupConfig;
 
     private final int partitionId;
 
@@ -149,18 +148,18 @@ public class TestMvPartitionStorage implements 
MvPartitionStorage {
     }
 
     @Override
-    @Nullable
-    public RaftGroupConfiguration committedGroupConfiguration() {
+    public byte @Nullable [] committedGroupConfiguration() {
         checkStorageClosed();
 
-        return groupConfig;
+        byte[] currentConfig = groupConfig;
+        return currentConfig == null ? null : Arrays.copyOf(currentConfig, 
currentConfig.length);
     }
 
     @Override
-    public void committedGroupConfiguration(RaftGroupConfiguration config) {
+    public void committedGroupConfiguration(byte[] config) {
         checkStorageClosedOrInProcessOfRebalance();
 
-        this.groupConfig = config;
+        this.groupConfig = Arrays.copyOf(config, config.length);
     }
 
     @Override
@@ -611,7 +610,7 @@ public class TestMvPartitionStorage implements 
MvPartitionStorage {
         groupConfig = null;
     }
 
-    void finishRebalance(long lastAppliedIndex, long lastAppliedTerm, 
RaftGroupConfiguration raftGroupConfig) {
+    void finishRebalance(long lastAppliedIndex, long lastAppliedTerm, byte[] 
groupConfig) {
         checkStorageClosed();
 
         assert rebalance;
@@ -620,7 +619,7 @@ public class TestMvPartitionStorage implements 
MvPartitionStorage {
 
         this.lastAppliedIndex = lastAppliedIndex;
         this.lastAppliedTerm = lastAppliedTerm;
-        this.groupConfig = raftGroupConfig;
+        this.groupConfig = Arrays.copyOf(groupConfig, groupConfig.length);
     }
 
     boolean closed() {
diff --git 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvTableStorage.java
 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvTableStorage.java
index 33829de4ac..771c00960f 100644
--- 
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvTableStorage.java
+++ 
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvTableStorage.java
@@ -31,7 +31,6 @@ import java.util.stream.Stream;
 import org.apache.ignite.internal.schema.configuration.TableConfiguration;
 import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.StorageRebalanceException;
 import org.apache.ignite.internal.storage.engine.MvTableStorage;
@@ -313,7 +312,7 @@ public class TestMvTableStorage implements MvTableStorage {
             int partitionId,
             long lastAppliedIndex,
             long lastAppliedTerm,
-            RaftGroupConfiguration raftGroupConfig
+            byte[] groupConfig
     ) {
         checkPartitionId(partitionId);
 
@@ -331,7 +330,7 @@ public class TestMvTableStorage implements MvTableStorage {
 
         return rebalanceFuture
                 .thenAccept(unused -> {
-                    partitionStorage.finishRebalance(lastAppliedIndex, 
lastAppliedTerm, raftGroupConfig);
+                    partitionStorage.finishRebalance(lastAppliedIndex, 
lastAppliedTerm, groupConfig);
 
                     
testHashIndexStorageStream(partitionId).forEach(TestHashIndexStorage::finishRebalance);
 
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
index d2ee618127..01fbf1d519 100644
--- 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
@@ -39,7 +39,6 @@ import org.apache.ignite.internal.pagememory.tree.BplusTree;
 import org.apache.ignite.internal.schema.configuration.TableConfiguration;
 import org.apache.ignite.internal.schema.configuration.TableView;
 import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.StorageRebalanceException;
 import org.apache.ignite.internal.storage.engine.MvTableStorage;
@@ -383,7 +382,7 @@ public abstract class AbstractPageMemoryTableStorage 
implements MvTableStorage {
             int partitionId,
             long lastAppliedIndex,
             long lastAppliedTerm,
-            RaftGroupConfiguration raftGroupConfig
+            byte[] groupConfig
     ) {
         return inBusyLock(busyLock, () -> {
             AbstractPageMemoryMvPartitionStorage mvPartitionStorage = 
getMvPartitionBusy(partitionId);
@@ -402,7 +401,7 @@ public abstract class AbstractPageMemoryTableStorage 
implements MvTableStorage {
                 mvPartitionStorage.runConsistently(() -> {
                     
mvPartitionStorage.lastAppliedOnRebalance(lastAppliedIndex, lastAppliedTerm);
 
-                    
mvPartitionStorage.committedGroupConfigurationOnRebalance(raftGroupConfig);
+                    
mvPartitionStorage.committedGroupConfigurationOnRebalance(groupConfig);
 
                     return null;
                 });
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
index 5a800b9508..2de9261ba0 100644
--- 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
@@ -51,7 +51,6 @@ import 
org.apache.ignite.internal.schema.configuration.index.TableIndexView;
 import org.apache.ignite.internal.storage.BinaryRowAndRowId;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.PartitionTimestampCursor;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageClosedException;
@@ -877,7 +876,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage 
implements MvPartitio
     /**
      * Sets the RAFT group configuration on rebalance.
      */
-    public abstract void 
committedGroupConfigurationOnRebalance(RaftGroupConfiguration config);
+    public abstract void committedGroupConfigurationOnRebalance(byte[] config);
 
     /**
      * Prepares the storage and its indexes for cleanup.
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
index 1d01d14e68..74f5fee5f9 100644
--- 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
@@ -38,7 +38,6 @@ import 
org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointSt
 import 
org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointTimeoutLock;
 import org.apache.ignite.internal.pagememory.tree.BplusTree;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.StorageException;
 import 
org.apache.ignite.internal.storage.pagememory.PersistentPageMemoryTableStorage;
 import 
org.apache.ignite.internal.storage.pagememory.configuration.schema.PersistentPageMemoryStorageEngineView;
@@ -49,7 +48,6 @@ import 
org.apache.ignite.internal.storage.pagememory.index.meta.IndexMeta;
 import org.apache.ignite.internal.storage.pagememory.index.meta.IndexMetaTree;
 import 
org.apache.ignite.internal.storage.pagememory.index.sorted.PageMemorySortedIndexStorage;
 import org.apache.ignite.internal.storage.pagememory.mv.gc.GcQueue;
-import org.apache.ignite.internal.util.ByteUtils;
 import org.apache.ignite.lang.IgniteInternalCheckedException;
 import org.jetbrains.annotations.Nullable;
 
@@ -225,8 +223,7 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
     }
 
     @Override
-    @Nullable
-    public RaftGroupConfiguration committedGroupConfiguration() {
+    public byte @Nullable [] committedGroupConfiguration() {
         return busy(() -> {
             throwExceptionIfStorageNotInRunnableOrRebalanceState(state.get(), 
this::createStorageInfo);
 
@@ -240,9 +237,7 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
                         return null;
                     }
 
-                    byte[] bytes = 
blobStorage.readBlob(meta.lastReplicationProtocolGroupConfigFirstPageId());
-
-                    return replicationProtocolGroupConfigFromBytes(bytes);
+                    return 
blobStorage.readBlob(meta.lastReplicationProtocolGroupConfigFirstPageId());
                 } finally {
                     
replicationProtocolGroupConfigReadWriteLock.readLock().unlock();
                 }
@@ -253,7 +248,7 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
     }
 
     @Override
-    public void committedGroupConfiguration(RaftGroupConfiguration config) {
+    public void committedGroupConfiguration(byte[] config) {
         busy(() -> {
             throwExceptionIfStorageNotInRunnableState();
 
@@ -263,14 +258,12 @@ public class PersistentPageMemoryMvPartitionStorage 
extends AbstractPageMemoryMv
         });
     }
 
-    private void committedGroupConfigurationBusy(RaftGroupConfiguration 
config) {
+    private void committedGroupConfigurationBusy(byte[] groupConfigBytes) {
         assert checkpointTimeoutLock.checkpointLockIsHeldByThread();
 
         CheckpointProgress lastCheckpoint = 
checkpointManager.lastCheckpointProgress();
         UUID lastCheckpointId = lastCheckpoint == null ? null : 
lastCheckpoint.id();
 
-        byte[] groupConfigBytes = 
replicationProtocolGroupConfigToBytes(config);
-
         replicationProtocolGroupConfigReadWriteLock.writeLock().lock();
 
         try {
@@ -288,19 +281,6 @@ public class PersistentPageMemoryMvPartitionStorage 
extends AbstractPageMemoryMv
         }
     }
 
-    @Nullable
-    private static RaftGroupConfiguration 
replicationProtocolGroupConfigFromBytes(byte @Nullable [] bytes) {
-        if (bytes == null) {
-            return null;
-        }
-
-        return ByteUtils.fromBytes(bytes);
-    }
-
-    private static byte[] 
replicationProtocolGroupConfigToBytes(RaftGroupConfiguration config) {
-        return ByteUtils.toBytes(config);
-    }
-
     @Override
     public PageMemoryHashIndexStorage getOrCreateHashIndex(UUID indexId) {
         return runConsistently(() -> super.getOrCreateHashIndex(indexId));
@@ -431,7 +411,7 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
     }
 
     @Override
-    public void committedGroupConfigurationOnRebalance(RaftGroupConfiguration 
config) {
+    public void committedGroupConfigurationOnRebalance(byte[] config) {
         throwExceptionIfStorageNotInProgressOfRebalance(state.get(), 
this::createStorageInfo);
 
         committedGroupConfigurationBusy(config);
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
index 41b058143b..78de1781d0 100644
--- 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
@@ -22,6 +22,7 @@ import static 
org.apache.ignite.internal.storage.util.StorageUtils.throwExceptio
 import static 
org.apache.ignite.internal.storage.util.StorageUtils.throwExceptionIfStorageNotInProgressOfRebalance;
 import static 
org.apache.ignite.internal.storage.util.StorageUtils.throwExceptionIfStorageNotInRunnableOrRebalanceState;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Predicate;
@@ -32,7 +33,6 @@ import org.apache.ignite.internal.pagememory.tree.BplusTree;
 import org.apache.ignite.internal.pagememory.util.GradualTaskExecutor;
 import org.apache.ignite.internal.pagememory.util.PageIdUtils;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.StorageException;
 import 
org.apache.ignite.internal.storage.pagememory.VolatilePageMemoryTableStorage;
 import 
org.apache.ignite.internal.storage.pagememory.index.hash.PageMemoryHashIndexStorage;
@@ -61,8 +61,7 @@ public class VolatilePageMemoryMvPartitionStorage extends 
AbstractPageMemoryMvPa
     private volatile long lastAppliedTerm;
 
     /** Last group configuration. */
-    @Nullable
-    private volatile RaftGroupConfiguration groupConfig;
+    private volatile byte @Nullable [] groupConfig;
 
     /**
      * Constructor.
@@ -153,20 +152,21 @@ public class VolatilePageMemoryMvPartitionStorage extends 
AbstractPageMemoryMvPa
     }
 
     @Override
-    public @Nullable RaftGroupConfiguration committedGroupConfiguration() {
+    public byte @Nullable [] committedGroupConfiguration() {
         return busy(() -> {
             throwExceptionIfStorageNotInRunnableOrRebalanceState(state.get(), 
this::createStorageInfo);
 
-            return groupConfig;
+            byte[] currentConfig = groupConfig;
+            return currentConfig == null ? null : Arrays.copyOf(currentConfig, 
currentConfig.length);
         });
     }
 
     @Override
-    public void committedGroupConfiguration(RaftGroupConfiguration config) {
+    public void committedGroupConfiguration(byte[] config) {
         busy(() -> {
             throwExceptionIfStorageNotInRunnableState();
 
-            groupConfig = config;
+            groupConfig = Arrays.copyOf(config, config.length);
 
             return null;
         });
@@ -335,7 +335,7 @@ public class VolatilePageMemoryMvPartitionStorage extends 
AbstractPageMemoryMvPa
     }
 
     @Override
-    public void committedGroupConfigurationOnRebalance(RaftGroupConfiguration 
config) throws StorageException {
+    public void committedGroupConfigurationOnRebalance(byte[] config) throws 
StorageException {
         throwExceptionIfStorageNotInProgressOfRebalance(state.get(), 
this::createStorageInfo);
 
         this.groupConfig = config;
diff --git 
a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
 
b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
index f75b17a8b9..6da99df03a 100644
--- 
a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
+++ 
b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.storage.pagememory.mv;
 
-import static java.util.stream.Collectors.toList;
 import static 
org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointState.FINISHED;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
@@ -25,12 +24,9 @@ import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.is;
 
 import java.nio.file.Path;
-import java.util.List;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
 import 
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import 
org.apache.ignite.internal.storage.pagememory.PersistentPageMemoryStorageEngine;
@@ -81,12 +77,7 @@ class PersistentPageMemoryMvPartitionStorageTest extends 
AbstractPageMemoryMvPar
 
     @Test
     void groupConfigIsPersisted() throws Exception {
-        RaftGroupConfiguration originalConfig = new RaftGroupConfiguration(
-                List.of("peer1", "peer2"),
-                List.of("old-peer1", "old-peer2"),
-                List.of("learner1", "learner2"),
-                List.of("old-learner1", "old-learner2")
-        );
+        byte[] originalConfig = {1, 2, 3};
 
         storage.runConsistently(() -> {
             storage.committedGroupConfiguration(originalConfig);
@@ -96,23 +87,14 @@ class PersistentPageMemoryMvPartitionStorageTest extends 
AbstractPageMemoryMvPar
 
         restartStorage();
 
-        RaftGroupConfiguration readConfig = 
storage.committedGroupConfiguration();
+        byte[] readConfig = storage.committedGroupConfiguration();
 
         assertThat(readConfig, is(equalTo(originalConfig)));
     }
 
     @Test
     void groupConfigWhichDoesNotFitInOnePageIsPersisted() throws Exception {
-        List<String> oneMbOfPeers = IntStream.range(0, 100_000)
-                .mapToObj(n -> String.format("peer%06d", n))
-                .collect(toList());
-
-        RaftGroupConfiguration originalConfig = new RaftGroupConfiguration(
-                oneMbOfPeers,
-                List.of("old-peer1", "old-peer2"),
-                List.of("learner1", "learner2"),
-                List.of("old-learner1", "old-learner2")
-        );
+        byte[] originalConfig = configThatDoesNotFitInOnePage();
 
         storage.runConsistently(() -> {
             storage.committedGroupConfiguration(originalConfig);
@@ -122,25 +104,26 @@ class PersistentPageMemoryMvPartitionStorageTest extends 
AbstractPageMemoryMvPar
 
         restartStorage();
 
-        RaftGroupConfiguration readConfig = 
storage.committedGroupConfiguration();
+        byte[] readConfig = storage.committedGroupConfiguration();
 
         assertThat(readConfig, is(equalTo(originalConfig)));
     }
 
+    private static byte[] configThatDoesNotFitInOnePage() {
+        byte[] originalconfig = new byte[1_000_000];
+
+        for (int i = 0; i < originalconfig.length; i++) {
+            originalconfig[i] = (byte) (i % 100);
+        }
+
+        return originalconfig;
+    }
+
     @Test
     void groupConfigShorteningWorksCorrectly() throws Exception {
-        List<String> oneMbOfPeers = IntStream.range(0, 100_000)
-                .mapToObj(n -> String.format("peer%06d", n))
-                .collect(toList());
-
-        assertThat(oneMbOfPeers.size() * oneMbOfPeers.get(0).length(), 
is(greaterThan(5 * pageSize())));
+        byte[] originalConfigOfMoreThanOnePage = 
configThatDoesNotFitInOnePage();
 
-        RaftGroupConfiguration originalConfigOfMoreThanOnePage = new 
RaftGroupConfiguration(
-                oneMbOfPeers,
-                List.of("old-peer1", "old-peer2"),
-                List.of("learner1", "learner2"),
-                List.of("old-learner1", "old-learner2")
-        );
+        assertThat(originalConfigOfMoreThanOnePage.length, is(greaterThan(5 * 
pageSize())));
 
         storage.runConsistently(() -> {
             
storage.committedGroupConfiguration(originalConfigOfMoreThanOnePage);
@@ -148,12 +131,7 @@ class PersistentPageMemoryMvPartitionStorageTest extends 
AbstractPageMemoryMvPar
             return null;
         });
 
-        RaftGroupConfiguration configWhichFitsInOnePage = new 
RaftGroupConfiguration(
-                List.of("peer1", "peer2"),
-                List.of("old-peer1", "old-peer2"),
-                List.of("learner1", "learner2"),
-                List.of("old-learner1", "old-learner2")
-        );
+        byte[] configWhichFitsInOnePage = {1, 2, 3};
 
         storage.runConsistently(() -> {
             storage.committedGroupConfiguration(configWhichFitsInOnePage);
@@ -163,7 +141,7 @@ class PersistentPageMemoryMvPartitionStorageTest extends 
AbstractPageMemoryMvPar
 
         restartStorage();
 
-        RaftGroupConfiguration readConfig = 
storage.committedGroupConfiguration();
+        byte[] readConfig = storage.committedGroupConfiguration();
 
         assertThat(readConfig, is(equalTo(configWhichFitsInOnePage)));
     }
diff --git 
a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
 
b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
index d7234b4a05..151b165fc1 100644
--- 
a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
+++ 
b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
@@ -41,13 +41,13 @@ import static 
org.apache.ignite.internal.storage.util.StorageUtils.throwExceptio
 import static 
org.apache.ignite.internal.storage.util.StorageUtils.throwExceptionIfStorageInProgressOfRebalance;
 import static org.apache.ignite.internal.util.ByteUtils.bytesToLong;
 import static org.apache.ignite.internal.util.ByteUtils.bytesToUuid;
-import static org.apache.ignite.internal.util.ByteUtils.fromBytes;
 import static org.apache.ignite.internal.util.ByteUtils.longToBytes;
 import static org.apache.ignite.internal.util.ByteUtils.putUuidToBytes;
 import static org.rocksdb.ReadTier.PERSISTED_TIER;
 
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.UUID;
@@ -62,7 +62,6 @@ import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.storage.BinaryRowAndRowId;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.PartitionTimestampCursor;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageException;
@@ -70,7 +69,6 @@ import 
org.apache.ignite.internal.storage.StorageRebalanceException;
 import org.apache.ignite.internal.storage.TxIdMismatchException;
 import org.apache.ignite.internal.storage.util.StorageState;
 import org.apache.ignite.internal.util.ArrayUtils;
-import org.apache.ignite.internal.util.ByteUtils;
 import org.apache.ignite.internal.util.Cursor;
 import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.IgniteSpinBusyLock;
@@ -170,15 +168,13 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
     private volatile long lastAppliedTerm;
 
     /** On-heap-cached last committed group configuration. */
-    @Nullable
-    private volatile RaftGroupConfiguration lastGroupConfig;
+    private volatile byte @Nullable [] lastGroupConfig;
 
     private volatile long pendingAppliedIndex;
 
     private volatile long pendingAppliedTerm;
 
-    @Nullable
-    private volatile RaftGroupConfiguration pendingGroupConfig;
+    private volatile byte @Nullable [] pendingGroupConfig;
 
     /** The value of {@link #lastAppliedIndex} persisted to the device at this 
moment. */
     private volatile long persistedIndex;
@@ -312,18 +308,19 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
     }
 
     @Override
-    @Nullable
-    public RaftGroupConfiguration committedGroupConfiguration() {
-        return busy(() -> threadLocalWriteBatch.get() == null ? 
lastGroupConfig : pendingGroupConfig);
+    public byte @Nullable [] committedGroupConfiguration() {
+        byte[] array = busy(() -> threadLocalWriteBatch.get() == null ? 
lastGroupConfig : pendingGroupConfig);
+
+        return array == null ? null : copy(array);
     }
 
     @Override
-    public void committedGroupConfiguration(RaftGroupConfiguration config) {
+    public void committedGroupConfiguration(byte[] config) {
         busy(() -> {
             throwExceptionIfStorageInProgressOfRebalance(state.get(), 
this::createStorageInfo);
 
             try {
-                saveRaftGroupConfiguration(requireWriteBatch(), config);
+                saveGroupConfiguration(requireWriteBatch(), config);
 
                 return null;
             } catch (RocksDBException e) {
@@ -332,10 +329,14 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
         });
     }
 
-    private void saveRaftGroupConfiguration(AbstractWriteBatch writeBatch, 
RaftGroupConfiguration config) throws RocksDBException {
-        writeBatch.put(meta, lastGroupConfigKey, ByteUtils.toBytes(config));
+    private void saveGroupConfiguration(AbstractWriteBatch writeBatch, byte[] 
config) throws RocksDBException {
+        writeBatch.put(meta, lastGroupConfigKey, config);
+
+        pendingGroupConfig = copy(config);
+    }
 
-        pendingGroupConfig = config;
+    private static byte[] copy(byte[] array) {
+        return Arrays.copyOf(array, array.length);
     }
 
     /**
@@ -395,16 +396,12 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
      * @param readOptions Read options to be used for reading.
      * @return Group configuration.
      */
-    private @Nullable RaftGroupConfiguration readLastGroupConfig(ReadOptions 
readOptions) {
-        byte[] bytes;
-
+    private byte @Nullable [] readLastGroupConfig(ReadOptions readOptions) {
         try {
-            bytes = db.get(meta, readOptions, lastGroupConfigKey);
+            return db.get(meta, readOptions, lastGroupConfigKey);
         } catch (RocksDBException e) {
             throw new StorageException(e);
         }
-
-        return bytes == null ? null : fromBytes(bytes);
     }
 
     @Override
@@ -1480,7 +1477,7 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
      *
      * @throws StorageRebalanceException If there was an error when finishing 
the rebalance.
      */
-    void finishRebalance(WriteBatch writeBatch, long lastAppliedIndex, long 
lastAppliedTerm, RaftGroupConfiguration raftGroupConfig) {
+    void finishRebalance(WriteBatch writeBatch, long lastAppliedIndex, long 
lastAppliedTerm, byte[] groupConfig) {
         if (!state.compareAndSet(StorageState.REBALANCE, 
StorageState.RUNNABLE)) {
             throwExceptionDependingOnStorageStateOnRebalance(state.get(), 
createStorageInfo());
         }
@@ -1488,7 +1485,7 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
         try {
             saveLastApplied(writeBatch, lastAppliedIndex, lastAppliedTerm);
 
-            saveRaftGroupConfigurationOnRebalance(writeBatch, raftGroupConfig);
+            saveGroupConfigurationOnRebalance(writeBatch, groupConfig);
         } catch (RocksDBException e) {
             throw new StorageRebalanceException("Error when trying to abort 
rebalancing storage: " + createStorageInfo(), e);
         }
@@ -1516,10 +1513,10 @@ public class RocksDbMvPartitionStorage implements 
MvPartitionStorage {
         persistedIndex = lastAppliedIndex;
     }
 
-    private void saveRaftGroupConfigurationOnRebalance(WriteBatch writeBatch, 
RaftGroupConfiguration config) throws RocksDBException {
-        saveRaftGroupConfiguration(writeBatch, config);
+    private void saveGroupConfigurationOnRebalance(WriteBatch writeBatch, 
byte[] config) throws RocksDBException {
+        saveGroupConfiguration(writeBatch, config);
 
-        this.lastGroupConfig = config;
+        this.lastGroupConfig = copy(config);
     }
 
     /**
diff --git 
a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbTableStorage.java
 
b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbTableStorage.java
index 4767d1314d..0504e95d75 100644
--- 
a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbTableStorage.java
+++ 
b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbTableStorage.java
@@ -51,7 +51,6 @@ import 
org.apache.ignite.internal.rocksdb.flush.RocksDbFlusher;
 import org.apache.ignite.internal.schema.configuration.TableConfiguration;
 import org.apache.ignite.internal.schema.configuration.TableView;
 import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.StorageRebalanceException;
 import org.apache.ignite.internal.storage.engine.MvTableStorage;
@@ -751,7 +750,7 @@ public class RocksDbTableStorage implements MvTableStorage {
             int partitionId,
             long lastAppliedIndex,
             long lastAppliedTerm,
-            RaftGroupConfiguration raftGroupConfig
+            byte[] groupConfig
     ) {
         return inBusyLock(busyLock, () -> {
             RocksDbMvPartitionStorage mvPartitionStorage = 
getMvPartitionBusy(partitionId);
@@ -767,7 +766,7 @@ public class RocksDbTableStorage implements MvTableStorage {
             }
 
             try (WriteBatch writeBatch = new WriteBatch()) {
-                mvPartitionStorage.finishRebalance(writeBatch, 
lastAppliedIndex, lastAppliedTerm, raftGroupConfig);
+                mvPartitionStorage.finishRebalance(writeBatch, 
lastAppliedIndex, lastAppliedTerm, groupConfig);
 
                 
getHashIndexStorages(partitionId).forEach(RocksDbHashIndexStorage::finishRebalance);
                 
getSortedIndexStorages(partitionId).forEach(RocksDbSortedIndexStorage::finishRebalance);
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionDataStorage.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionDataStorage.java
index 5b9ac5b6e1..eacb234335 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionDataStorage.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionDataStorage.java
@@ -24,7 +24,6 @@ import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.MvPartitionStorage.WriteClosure;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageException;
@@ -100,20 +99,11 @@ public interface PartitionDataStorage extends 
ManuallyCloseable {
      */
     void lastApplied(long lastAppliedIndex, long lastAppliedTerm) throws 
StorageException;
 
-    /**
-     * Committed RAFT group configuration corresponding to the write command 
with the highest index applied to the storage.
-     * {@code null} if it was never saved.
-     *
-     * @see MvPartitionStorage#committedGroupConfiguration()
-     */
-    @Nullable
-    RaftGroupConfiguration committedGroupConfiguration();
-
     /**
      * Updates RAFT group configuration.
      *
      * @param config Configuration to save.
-     * @see 
MvPartitionStorage#committedGroupConfiguration(RaftGroupConfiguration)
+     * @see MvPartitionStorage#committedGroupConfiguration(byte[])
      */
     void committedGroupConfiguration(RaftGroupConfiguration config);
 
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionListener.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionListener.java
index 2041bfebe8..cfa716db62 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionListener.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionListener.java
@@ -45,7 +45,6 @@ import 
org.apache.ignite.internal.replicator.command.SafeTimePropagatingCommand;
 import org.apache.ignite.internal.replicator.command.SafeTimeSyncCommand;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.PartitionTimestampCursor;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.table.distributed.StorageUpdateHandler;
diff --git 
a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/RaftGroupConfiguration.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfiguration.java
similarity index 98%
rename from 
modules/storage-api/src/main/java/org/apache/ignite/internal/storage/RaftGroupConfiguration.java
rename to 
modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfiguration.java
index 763c55a93d..ebd13331ca 100644
--- 
a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/RaftGroupConfiguration.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfiguration.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.storage;
+package org.apache.ignite.internal.table.distributed.raft;
 
 import java.io.Serializable;
 import java.util.Collection;
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfigurationConverter.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfigurationConverter.java
new file mode 100644
index 0000000000..853ac5886d
--- /dev/null
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfigurationConverter.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.table.distributed.raft;
+
+import org.apache.ignite.internal.util.ByteUtils;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Used to convert {@link RaftGroupConfiguration} to/from bytes.
+ */
+public class RaftGroupConfigurationConverter {
+    /**
+     * Parses the byte representation of a {@link RaftGroupConfiguration}.
+     *
+     * @param bytes Byte representation (might be null).
+     * @return Parsed value ({@code null} if the input is {@code null}).
+     */
+    @Nullable
+    public RaftGroupConfiguration fromBytes(byte @Nullable [] bytes) {
+        if (bytes == null) {
+            return null;
+        }
+
+        return ByteUtils.fromBytes(bytes);
+    }
+
+    /**
+     * Converts the given configuration to its byte representation.
+     *
+     * @param configuration Config to convert.
+     * @return Byte representation.
+     */
+    public byte[] toBytes(RaftGroupConfiguration configuration) {
+        return ByteUtils.toBytes(configuration);
+    }
+}
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccess.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccess.java
index 8609160f6b..106f459ad1 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccess.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccess.java
@@ -22,12 +22,12 @@ import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.StorageRebalanceException;
 import org.apache.ignite.internal.storage.TxIdMismatchException;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import org.apache.ignite.internal.tx.TxMeta;
 import org.apache.ignite.internal.util.Cursor;
 import org.apache.ignite.lang.IgniteBiTuple;
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccessImpl.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccessImpl.java
index 305a80e079..bf97b1fb23 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccessImpl.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionAccessImpl.java
@@ -24,11 +24,12 @@ import java.util.function.Supplier;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.engine.MvTableStorage;
 import 
org.apache.ignite.internal.table.distributed.TableSchemaAwareIndexStorage;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfigurationConverter;
 import org.apache.ignite.internal.tx.TxMeta;
 import org.apache.ignite.internal.tx.storage.state.TxStateStorage;
 import org.apache.ignite.internal.tx.storage.state.TxStateTableStorage;
@@ -49,6 +50,8 @@ public class PartitionAccessImpl implements PartitionAccess {
 
     private final Supplier<Collection<TableSchemaAwareIndexStorage>> indexes;
 
+    private final RaftGroupConfigurationConverter 
raftGroupConfigurationConverter = new RaftGroupConfigurationConverter();
+
     /**
      * Constructor.
      *
@@ -104,7 +107,9 @@ public class PartitionAccessImpl implements PartitionAccess 
{
 
     @Override
     public @Nullable RaftGroupConfiguration committedGroupConfiguration() {
-        return 
getMvPartitionStorage(partitionId()).committedGroupConfiguration();
+        byte[] configBytes = 
getMvPartitionStorage(partitionId()).committedGroupConfiguration();
+
+        return raftGroupConfigurationConverter.fromBytes(configBytes);
     }
 
     @Override
@@ -192,8 +197,10 @@ public class PartitionAccessImpl implements 
PartitionAccess {
     public CompletableFuture<Void> finishRebalance(long lastAppliedIndex, long 
lastAppliedTerm, RaftGroupConfiguration raftGroupConfig) {
         TxStateStorage txStateStorage = getTxStateStorage(partitionId());
 
+        byte[] configBytes = 
raftGroupConfigurationConverter.toBytes(raftGroupConfig);
+
         return CompletableFuture.allOf(
-                mvTableStorage.finishRebalancePartition(partitionId(), 
lastAppliedIndex, lastAppliedTerm, raftGroupConfig),
+                mvTableStorage.finishRebalancePartition(partitionId(), 
lastAppliedIndex, lastAppliedTerm, configBytes),
                 txStateStorage.finishRebalance(lastAppliedIndex, 
lastAppliedTerm)
         );
     }
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactory.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactory.java
index d8debe41d9..ee0074b6f8 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactory.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactory.java
@@ -20,7 +20,7 @@ package 
org.apache.ignite.internal.table.distributed.raft.snapshot;
 import java.util.concurrent.Executor;
 import org.apache.ignite.internal.raft.storage.SnapshotStorageFactory;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.outgoing.OutgoingSnapshotsManager;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.outgoing.SnapshotMetaUtils;
 import org.apache.ignite.internal.tx.storage.state.TxStateStorage;
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopier.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopier.java
index 10362f8940..904eb21d71 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopier.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopier.java
@@ -32,11 +32,11 @@ import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageRebalanceException;
 import org.apache.ignite.internal.table.distributed.TableMessagesFactory;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccess;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionSnapshotStorage;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.SnapshotUri;
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshot.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshot.java
index 0697b0cae9..2644395854 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshot.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshot.java
@@ -32,10 +32,10 @@ import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.table.distributed.TableMessagesFactory;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccess;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.message.SnapshotMetaRequest;
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorage.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorage.java
index a5bf3601d9..7f470d0bc8 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorage.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorage.java
@@ -23,12 +23,13 @@ import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.MvPartitionStorage.WriteClosure;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.TxIdMismatchException;
 import org.apache.ignite.internal.table.distributed.raft.PartitionDataStorage;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfigurationConverter;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import org.apache.ignite.internal.util.Cursor;
 import org.jetbrains.annotations.Nullable;
@@ -43,6 +44,8 @@ public class SnapshotAwarePartitionDataStorage implements 
PartitionDataStorage {
     private final PartitionsSnapshots partitionsSnapshots;
     private final PartitionKey partitionKey;
 
+    private final RaftGroupConfigurationConverter 
raftGroupConfigurationConverter = new RaftGroupConfigurationConverter();
+
     /**
      * Creates a new instance.
      */
@@ -99,14 +102,9 @@ public class SnapshotAwarePartitionDataStorage implements 
PartitionDataStorage {
         partitionStorage.lastApplied(lastAppliedIndex, lastAppliedTerm);
     }
 
-    @Override
-    public @Nullable RaftGroupConfiguration committedGroupConfiguration() {
-        return partitionStorage.committedGroupConfiguration();
-    }
-
     @Override
     public void committedGroupConfiguration(RaftGroupConfiguration config) {
-        partitionStorage.committedGroupConfiguration(config);
+        
partitionStorage.committedGroupConfiguration(raftGroupConfigurationConverter.toBytes(config));
     }
 
     @Override
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtils.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtils.java
index 0cee7c5250..0ed0b403a1 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtils.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtils.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.table.distributed.raft.snapshot.outgoing;
 
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import org.apache.ignite.raft.jraft.RaftMessagesFactory;
 import org.apache.ignite.raft.jraft.entity.RaftOutter.SnapshotMeta;
 import org.apache.ignite.raft.jraft.entity.SnapshotMetaBuilder;
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
index bf61a8a372..c1c2e699c9 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
@@ -75,7 +75,6 @@ import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.MvPartitionStorage.WriteClosure;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.impl.TestMvPartitionStorage;
@@ -168,6 +167,8 @@ public class PartitionCommandListenerTest {
     @Captor
     private ArgumentCaptor<Throwable> commandClosureResultCaptor;
 
+    private final RaftGroupConfigurationConverter 
raftGroupConfigurationConverter = new RaftGroupConfigurationConverter();
+
     /**
      * Initializes a table listener before tests.
      */
@@ -404,8 +405,14 @@ public class PartitionCommandListenerTest {
                 1, 2, List.of("peer"), List.of("learner"), 
List.of("old-peer"), List.of("old-learner")
         ));
 
+        RaftGroupConfiguration expectedConfig = new RaftGroupConfiguration(
+                List.of("peer"),
+                List.of("learner"),
+                List.of("old-peer"),
+                List.of("old-learner")
+        );
         verify(mvPartitionStorage).committedGroupConfiguration(
-                new RaftGroupConfiguration(List.of("peer"), 
List.of("learner"), List.of("old-peer"), List.of("old-learner"))
+                raftGroupConfigurationConverter.toBytes(expectedConfig)
         );
     }
 
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfigurationConverterTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfigurationConverterTest.java
new file mode 100644
index 0000000000..8880c2982b
--- /dev/null
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/RaftGroupConfigurationConverterTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.table.distributed.raft;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class RaftGroupConfigurationConverterTest {
+    private final RaftGroupConfigurationConverter converter = new 
RaftGroupConfigurationConverter();
+
+    @Test
+    void convertsAndParses() {
+        RaftGroupConfiguration configuration = new RaftGroupConfiguration(
+                List.of("peer"),
+                List.of("learner"),
+                List.of("old-peer"),
+                List.of("old-learner")
+        );
+
+        byte[] bytes = converter.toBytes(configuration);
+
+        assertThat(converter.fromBytes(bytes), is(configuration));
+    }
+
+    @Test
+    void parsesNullToNull() {
+        assertThat(converter.fromBytes(null), is(nullValue()));
+    }
+}
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactoryTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactoryTest.java
index 43b22b73a9..81e8fd3337 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactoryTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/PartitionSnapshotStorageFactoryTest.java
@@ -25,7 +25,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.util.concurrent.Executor;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.outgoing.OutgoingSnapshotsManager;
 import org.apache.ignite.network.TopologyService;
 import org.apache.ignite.raft.jraft.option.RaftOptions;
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopierTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopierTest.java
index 4fe17d1a91..f09ffbd30e 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopierTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/incoming/IncomingSnapshotCopierTest.java
@@ -29,6 +29,7 @@ import static 
org.apache.ignite.internal.util.IgniteUtils.shutdownAndAwaitTermin
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -66,7 +67,6 @@ import 
org.apache.ignite.internal.schema.configuration.TableConfiguration;
 import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
 import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageException;
@@ -74,6 +74,8 @@ import 
org.apache.ignite.internal.storage.engine.MvTableStorage;
 import org.apache.ignite.internal.storage.impl.TestMvPartitionStorage;
 import org.apache.ignite.internal.storage.impl.TestMvTableStorage;
 import org.apache.ignite.internal.table.distributed.TableMessagesFactory;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfigurationConverter;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccessImpl;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionSnapshotStorage;
@@ -133,6 +135,8 @@ public class IncomingSnapshotCopierTest {
 
     private final UUID snapshotId = UUID.randomUUID();
 
+    private final RaftGroupConfigurationConverter 
raftGroupConfigurationConverter = new RaftGroupConfigurationConverter();
+
     @AfterEach
     void tearDown() {
         shutdownAndAwaitTermination(executorService, 1, TimeUnit.SECONDS);
@@ -183,7 +187,10 @@ public class IncomingSnapshotCopierTest {
 
         assertEquals(expLastAppliedIndex, 
outgoingMvPartitionStorage.lastAppliedIndex());
         assertEquals(expLastAppliedTerm, 
outgoingMvPartitionStorage.lastAppliedTerm());
-        assertEquals(expLastGroupConfig, 
outgoingMvPartitionStorage.committedGroupConfiguration());
+        assertArrayEquals(
+                raftGroupConfigurationConverter.toBytes(expLastGroupConfig),
+                outgoingMvPartitionStorage.committedGroupConfiguration()
+        );
         assertEquals(expLastAppliedIndex, 
outgoingTxStatePartitionStorage.lastAppliedIndex());
         assertEquals(expLastAppliedTerm, 
outgoingTxStatePartitionStorage.lastAppliedTerm());
 
@@ -275,7 +282,7 @@ public class IncomingSnapshotCopierTest {
         );
     }
 
-    private static void fillMvPartitionStorage(
+    private void fillMvPartitionStorage(
             MvPartitionStorage storage,
             long lastAppliedIndex,
             long lastAppliedTerm,
@@ -297,7 +304,7 @@ public class IncomingSnapshotCopierTest {
 
             storage.lastApplied(lastAppliedIndex, lastAppliedTerm);
 
-            storage.committedGroupConfiguration(raftGroupConfig);
+            
storage.committedGroupConfiguration(raftGroupConfigurationConverter.toBytes(raftGroupConfig));
 
             return null;
         });
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotCommonTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotCommonTest.java
index e477dc65e5..d54789d8b8 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotCommonTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotCommonTest.java
@@ -25,8 +25,8 @@ import static org.mockito.Mockito.when;
 
 import java.util.List;
 import java.util.UUID;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.table.distributed.TableMessagesFactory;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccess;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.message.SnapshotMetaRequest;
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotReaderTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotReaderTest.java
index e74cfe45ed..0a610c224b 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotReaderTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotReaderTest.java
@@ -25,7 +25,7 @@ import static org.mockito.Mockito.when;
 
 import java.util.UUID;
 import java.util.concurrent.Executor;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccess;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionSnapshotStorage;
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotTxDataStreamingTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotTxDataStreamingTest.java
index 67be728a63..2d5b52e497 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotTxDataStreamingTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotTxDataStreamingTest.java
@@ -35,8 +35,8 @@ import java.util.List;
 import java.util.UUID;
 import org.apache.ignite.internal.hlc.HybridClock;
 import org.apache.ignite.internal.hlc.HybridClockImpl;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.table.distributed.TableMessagesFactory;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccess;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.message.SnapshotTxDataRequest;
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotsManagerTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotsManagerTest.java
index 9d19facc05..07b5b1da50 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotsManagerTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/OutgoingSnapshotsManagerTest.java
@@ -26,7 +26,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.util.UUID;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import 
org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionAccess;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import org.junit.jupiter.api.Test;
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorageTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorageTest.java
index 20c41b31f0..26bdbd396c 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorageTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotAwarePartitionDataStorageTest.java
@@ -37,8 +37,9 @@ import org.apache.ignite.internal.hlc.HybridClockImpl;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.RowId;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfigurationConverter;
 import org.apache.ignite.internal.table.distributed.raft.snapshot.PartitionKey;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -74,6 +75,8 @@ class SnapshotAwarePartitionDataStorageTest {
     @Mock
     private OutgoingSnapshot snapshot;
 
+    private final RaftGroupConfigurationConverter configurationConverter = new 
RaftGroupConfigurationConverter();
+
     @BeforeEach
     void configureMocks() {
         
lenient().when(partitionsSnapshots.partitionSnapshots(any())).thenReturn(partitionSnapshots);
@@ -125,21 +128,17 @@ class SnapshotAwarePartitionDataStorageTest {
     }
 
     @Test
-    void delegatesCommittedGroupConfigurationGetter() {
-        RaftGroupConfiguration config = mock(RaftGroupConfiguration.class);
-
-        
when(partitionStorage.committedGroupConfiguration()).thenReturn(config);
-
-        assertThat(testedStorage.committedGroupConfiguration(), 
is(sameInstance(config)));
-    }
-
-    @Test
-    void delegatesCommittedGroupConfigurationSetter() {
-        RaftGroupConfiguration config = mock(RaftGroupConfiguration.class);
+    void convertsCommittedGroupConfigurationOnSave() {
+        RaftGroupConfiguration config = new RaftGroupConfiguration(
+                List.of("peer"),
+                List.of("learner"),
+                List.of("old-peer"),
+                List.of("old-learner")
+        );
 
         testedStorage.committedGroupConfiguration(config);
 
-        verify(partitionStorage).committedGroupConfiguration(config);
+        
verify(partitionStorage).committedGroupConfiguration(configurationConverter.toBytes(config));
     }
 
     @Test
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtilsTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtilsTest.java
index 6d43678e44..e9ff6007fd 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtilsTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/snapshot/outgoing/SnapshotMetaUtilsTest.java
@@ -22,7 +22,7 @@ import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.nullValue;
 
 import java.util.List;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
 import org.apache.ignite.raft.jraft.entity.RaftOutter.SnapshotMeta;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
diff --git 
a/modules/table/src/testFixtures/java/org/apache/ignite/distributed/TestPartitionDataStorage.java
 
b/modules/table/src/testFixtures/java/org/apache/ignite/distributed/TestPartitionDataStorage.java
index 3391eff013..eb891ebeeb 100644
--- 
a/modules/table/src/testFixtures/java/org/apache/ignite/distributed/TestPartitionDataStorage.java
+++ 
b/modules/table/src/testFixtures/java/org/apache/ignite/distributed/TestPartitionDataStorage.java
@@ -25,12 +25,13 @@ import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.MvPartitionStorage.WriteClosure;
-import org.apache.ignite.internal.storage.RaftGroupConfiguration;
 import org.apache.ignite.internal.storage.ReadResult;
 import org.apache.ignite.internal.storage.RowId;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.TxIdMismatchException;
 import org.apache.ignite.internal.table.distributed.raft.PartitionDataStorage;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfiguration;
+import 
org.apache.ignite.internal.table.distributed.raft.RaftGroupConfigurationConverter;
 import org.apache.ignite.internal.util.Cursor;
 import org.jetbrains.annotations.Nullable;
 
@@ -42,6 +43,8 @@ public class TestPartitionDataStorage implements 
PartitionDataStorage {
 
     private final Lock partitionSnapshotsLock = new ReentrantLock();
 
+    private final RaftGroupConfigurationConverter configurationConverter = new 
RaftGroupConfigurationConverter();
+
     public TestPartitionDataStorage(MvPartitionStorage partitionStorage) {
         this.partitionStorage = partitionStorage;
     }
@@ -82,14 +85,9 @@ public class TestPartitionDataStorage implements 
PartitionDataStorage {
         partitionStorage.lastApplied(lastAppliedIndex, lastAppliedTerm);
     }
 
-    @Override
-    public @Nullable RaftGroupConfiguration committedGroupConfiguration() {
-        return partitionStorage.committedGroupConfiguration();
-    }
-
     @Override
     public void committedGroupConfiguration(RaftGroupConfiguration config) {
-        partitionStorage.committedGroupConfiguration(config);
+        
partitionStorage.committedGroupConfiguration(configurationConverter.toBytes(config));
     }
 
     @Override

Reply via email to