PHOENIX-7906 :- Add UNKNOWN forward-compat sentinel for TransformType#2563
Open
lokiore wants to merge 1 commit into
Open
PHOENIX-7906 :- Add UNKNOWN forward-compat sentinel for TransformType#2563lokiore wants to merge 1 commit into
lokiore wants to merge 1 commit into
Conversation
Add a TransformType.UNKNOWN((byte) -1) sentinel so a binary that reads a SYSTEM.TRANSFORM row written by a newer binary (one that introduced a new transform type this binary does not recognize) resolves the unknown serialized value to UNKNOWN instead of throwing or silently mis-mapping it. fromSerializedValue returns UNKNOWN for any unrecognized byte; UNKNOWN is never produced through its own serialized value on the normal write path. Callers that can observe UNKNOWN now handle it defensively rather than proceeding against a record they cannot reason about: - Transform.doCutover: skip with an operator-readable WARN and return, so the monitor task stays alive and other transforms are not starved. - Transform.doForceCutover: the COMPLETED update + commit is factored into a package-private finishForceCutover, which skips when the type is UNKNOWN so an unrun cutover is not falsely marked COMPLETED. - TransformTool.validateTransform: fail fast with an actionable message instructing the operator to upgrade the binary or remove the row. - TransformMonitorTask: skip the record (SKIPPED result) with an operator message via package-private skipIfUnknownTransformType. Unit tests cover the enum resolution and each guard site. Generated-by: Claude Code (Opus 4.8 (1M context))
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
This PR adds a
TransformType.UNKNOWN((byte) -1)forward-compatibility sentinel and wires the call sites that can observe it to behave defensively.SystemTransformRecordreads the persisted transform type from theSYSTEM.TRANSFORMrow. Today, a serialized transform-type value that this binary does not recognize (because it was written by a newer binary that introduced a newTransformTypeconstant) has no safe representation. This PR introducesUNKNOWNso the resolution path can map any unrecognized serialized value to it:TransformType.fromSerializedValue(...)returnsUNKNOWNfor any byte that does not correspond to a known constant.UNKNOWNis never produced via its own serialized value on the normal write path.Call sites that may observe
UNKNOWNnow skip or fail fast with an operator-readable message rather than proceeding against a record they cannot reason about:Transform.doCutover— skips with aWARNand returns, keeping the monitor task alive so other transforms are not starved.Transform.doForceCutover— theupdateTransformRecord(COMPLETED)+commit()step is factored into a package-privatefinishForceCutover, which skips when the type isUNKNOWN. BecausedoCutovershort-circuits onUNKNOWN, marking the recordCOMPLETEDwould otherwise falsely report success for a cutover that never ran.TransformTool.validateTransform— fails fast with an actionableIllegalStateExceptioninstructing the operator to upgrade the binary to a version that recognizes the type, or remove theSYSTEM.TRANSFORMrow, before retrying.TransformMonitorTask— skips the record (returns aSKIPPEDtask result) with an operator-readable message, via package-privateskipIfUnknownTransformType.Why are the changes needed?
Without a sentinel, a binary that encounters a transform type written by a newer binary would either throw from an unexpected place or silently mis-handle the row. A new constant added later (the realistic next serialized values are small positive bytes) must degrade safely on older binaries: skip or fail fast with a clear operator message, and in particular never mark a transform
COMPLETEDwhen no cutover was performed. This keeps mixed-version clusters safe during rollout.Does this PR introduce any user-facing change?
No. This is an internal forward-compatibility guard. The added
UNKNOWNconstant is not reachable through normal writes; on current binaries noSYSTEM.TRANSFORMrow resolves to it, so existing behavior is unchanged.How was this patch tested?
New unit tests, all green (19 tests, 0 failures, 0 errors, 0 skipped across the six classes):
TransformTypeTest— enum resolution: unrecognized serialized values resolve toUNKNOWN; round-trip of known values is preserved;UNKNOWNis not produced via its own serialized value.TransformDoCutoverUnknownTypeTest—doCutovershort-circuits and performs no work on the connection for anUNKNOWNrecord.TransformForceCutoverUnknownTypeTest—finishForceCutoverdoes not markCOMPLETEDand does not commit for anUNKNOWNrecord; a recognized type is still markedCOMPLETEDand committed.TransformToolValidateTransformUnknownTypeTest—validateTransformfails fast for anUNKNOWNrecord.TransformMonitorTaskUnknownTypeTest— the monitor returns aSKIPPEDresult for anUNKNOWNrecord and proceeds normally otherwise.mvn spotless:applyis clean on the affected modules.Known / deferred
Two pre-existing low-severity items are intentionally deferred to a follow-up PR to keep this change focused on the sentinel and its guards:
SystemTransformRecordreads the transform type withgetByte()on anINTEGERcolumn. The currently used and realistic next values are small and safe; a future value>= 128could alias under the signed-byte read. The read path should move togetInt().UNKNOWNpath logs aWARNon every task-scan cycle while such a record persists, which can be noisy. This should be rate-limited or logged once per record.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8 (1M context))