HDDS-15145. Use enum for the ID type in SequenceIdGenerator#10211
HDDS-15145. Use enum for the ID type in SequenceIdGenerator#10211navinko wants to merge 11 commits into
Conversation
| public void testNumberOfEnumConstants() { | ||
| // If a new SequenceIdType is added, this test will fail. | ||
| // This serves as a reminder to the developer to verify RocksDB backward | ||
| // compatibility and update this test class accordingly. | ||
| assertEquals(5, SequenceIdType.values().length); | ||
| } |
There was a problem hiding this comment.
Here testNumberOfEnumConstants (assertEquals(5, SequenceIdType.values().length)) is fully subsumed by testIfNewEnumConstantGetsAdded. Every failure scenario that testNumberOfEnumConstants catches is also caught by testIfNewEnumConstantGetsAdded, which additionally catches renames (count stays 5 but a name changes), and provides a far more descriptive failure message with the "ACTION REQUIRED" instruction.
There was a problem hiding this comment.
Thanks , it make sense!
removed this one.
| @Test | ||
| public void testReturnsNullIfEnumConstantNotAvailable() { | ||
| assertNull(SequenceIdType.fromDbKey("unmapped-key-string")); | ||
| assertNull(SequenceIdType.fromDbKey(null)); | ||
| } |
There was a problem hiding this comment.
We can in a different test consider asserting assertSame(type, fromDbKey(type.getDbKey())) for every constant so the static map stays aligned with getDbKey(), not covered by the unknown/null case alone.
There was a problem hiding this comment.
Thanks @sreejasahithi for review, to align with current review comments i ahve removed the unused method fromDbKey completely.
| /** | ||
| * Returns the {@link SequenceIdType} corresponding to the provided RocksDB key string, or null if unmapped. | ||
| */ | ||
| public static SequenceIdType fromDbKey(String dbKey) { |
There was a problem hiding this comment.
This method is unused except testReturnsNullIfEnumConstantNotAvailable(). Let's remove it and also DB_KEY_MAP.
Indeed, we should always use SequenceIdType and never convert a String to SequenceIdType.
| public static final String LOCAL_ID = SequenceIdType.LOCAL_ID.getDbKey(); | ||
| public static final String DEL_TXN_ID = SequenceIdType.DEL_TXN_ID.getDbKey(); | ||
| public static final String CONTAINER_ID = SequenceIdType.CONTAINER_ID.getDbKey(); | ||
|
|
||
| // Certificate ID for all services, including root certificates, whose ID | ||
| // were using "rootCertificateId" before. | ||
| public static final String CERTIFICATE_ID = "CertificateId"; | ||
| public static final String CERTIFICATE_ID = SequenceIdType.CERTIFICATE_ID.getDbKey(); | ||
| @Deprecated | ||
| public static final String ROOT_CERTIFICATE_ID = "rootCertificateId"; | ||
| public static final String ROOT_CERTIFICATE_ID = SequenceIdType.ROOT_CERTIFICATE_ID.getDbKey(); |
| public SequenceIdGenerator(ConfigurationSource conf, | ||
| SCMHAManager scmhaManager, Table<String, Long> sequenceIdTable) { | ||
| this.sequenceIdToBatchMap = new HashMap<>(); | ||
| this.sequenceIdToBatchMap = new EnumMap<>(SequenceIdType.class); |
There was a problem hiding this comment.
Make it unmodifiable:
this.sequenceIdToBatchMap = newSequenceIdToBatchMap(); static Map<SequenceIdType, Batch> newSequenceIdToBatchMap() {
final EnumMap<SequenceIdType, Batch> map = new EnumMap<>(SequenceIdType.class);
for (SequenceIdType type : SequenceIdType.values()) {
map.put(type, new Batch());
}
return Collections.unmodifiableMap(map);
}| Batch batch = sequenceIdToBatchMap.computeIfAbsent( | ||
| sequenceIdName, key -> new Batch()); | ||
| idType, key -> new Batch()); |
There was a problem hiding this comment.
Use get()
final Batch batch = sequenceIdToBatchMap.get(idType);|
|
||
| // reload lastId from RocksDB. | ||
| batch.lastId = stateManager.getLastId(sequenceIdName); | ||
| batch.lastId = stateManager.getLastId(idType.getDbKey()); |
There was a problem hiding this comment.
- Change the parameter to SequenceIdType
- Change StateManagerImpl.sequenceIdToLastIdMap key to SequenceIdType
There was a problem hiding this comment.
Thanks @sreejasahithi @szetszwo for the suggestion!
I have removed the unused method fromDbKey and DB_KEY_MAP and made all constant under SequenceIdGenerator private alongwith EnumMap as unmodifiable and dis suggested changes in test classes.
I've updated code for StateManagerImpl too , the parameters and map keys to use SequenceIdType instead of Strings. Further , to handle how these new Enums are serialized across the Ratis and safely deserialized from existing RocksDB bytes, I implemented the ScmSequenceIdTypeCodec and registered with ScmCodecFactory. This ensures the Enums translate perfectly into our legacy byte format .
Also referred existing TestPipelineIDCodec to create new unit test for codec and verifies the serialization and deserialzation. In the LegacyStringSequenceIdCodecForTesting class simulated, how Sequence IDs were serialized before the Enum refactoring.
|
Thanks @szetszwo @sreejasahithi for the review , tried addressing review suggestions . |
szetszwo
left a comment
There was a problem hiding this comment.
- Change the parameter to SequenceIdType
- Change StateManagerImpl.sequenceIdToLastIdMap key to SequenceIdType
@navinko , my suggestions above actually need a lot of changes. Sorry that I was not aware of it!
Could you revert them here and do it in a separated JIRA, revert all the changes for StateManager and StateManagerImpl and keep using String?
| */ | ||
| @Replicate | ||
| Boolean allocateBatch(String sequenceIdName, | ||
| Boolean allocateBatch(SequenceIdType idType, |
There was a problem hiding this comment.
We cannot change the parameter class for compatibility. Otherwise, the SCM in old version cannot talk to the SCM in new version. Let's do it in a separated JIRA.
There was a problem hiding this comment.
Thanks @szetszwo will update the PR as suggested .
|
@navinko , thanks for the update! Please remove |
|
Thanks @szetszwo , reverted all the changes for StateManager and StateManagerImpl and keep using String. |
What changes were proposed in this pull request?
HDDS-15145. Use enum for the ID type in SequenceIdGenerator
Please describe your PR in detail:
This PR introduces "SequenceIdType" to replace String based ID type arguments in "SequenceIdGenerator".
SequenceIdGenerator#getNextId now accepts "SequenceIdType" instead of String values, and its in-memory batch cache uses an EnumMap<SequenceIdType, Batch>.
This gives compile-time safety for supported sequence ID types while preserving the existing RocksDB key strings through "SequenceIdType#getDbKey()".
The existing String constants in
SequenceIdGeneratorare retained and now mapped with Enum .[Reverted]Updated StateManager and StateManagerImpl to use Enum instead of String as sequenceID and created new codec for it. parameters for allocateBatch and getLastId are now updated to adapt Enum.
Added unit tests for SequenceIdType and updated existing SequenceIdGenerator and RootCARotationManager
tests
[Removed] Last Created new test for Codec
TestScmSequenceIdTypeCodec
LegacyStringSequenceIdCodecForTesting
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-15145
How was this patch tested?
Validated with unit test and Also verified the change in a local Docker compose secure HA cluster. The SCM logs show enum-based allocation paths:
Latest progressing CI : https://github.com/navinko/ozone/actions/runs/25717961667