fix go jobId schema bug

This commit is contained in:
Rongsong Shen 2026-05-03 11:45:14 +08:00
parent d7afd72e5b
commit 3ed7ef011a
2 changed files with 39 additions and 3 deletions

View file

@ -10,7 +10,7 @@ import (
//
// |63 62|61 56|55 52|51 20|19 15|14 0|
// | TAG | CLUSTER_ID | APISERVER_ID| TIMESTAMP | SEQ_HIGH | ARRAY_IDX |
// | 2 bits | 6 bits | 4 bits | 32 bits | 15 bits | 15 bits |
// | 2 bits | 6 bits | 4 bits | 32 bits | 5 bits | 15 bits |
const (
nTagBits = 2
tagShift = 62
@ -21,8 +21,8 @@ const (
nTimestampBits = 32
timestampShift = 20
nArrayIdxBits = 15
sequenceHighShift = 15 // mirrors SEQUENCE_HIGH_SHIFT in config.h
nSequenceBits = 30 // mirrors N_SEQUENCE_BITS in config.h
sequenceHighShift = 15 // mirrors SEQUENCE_HIGH_SHIFT in config.h (== N_ARRAY_IDX_BITS)
nSequenceBits = 20 // N_JOBID_BITS(64) - N_CLUSTER_ID_BITS(6) - N_APISERVER_ID_BITS(4) - N_TIMESTAMP_BITS(32) - N_TAG_BITS(2) = 20
tagJobArray = 0x01 // mirrors TAG_JOB_ARRAY in config.h
)

View file

@ -367,6 +367,42 @@ func TestRawJobToModel_ArrayChildrenShareBaseID(t *testing.T) {
}
}
// TestExtractArrayBaseID_LargeTimestamp verifies that ExtractArrayBaseID does not
// leak timestamp bits into the extracted sequence when the timestamp field has
// large values. This would fail with nSequenceBits=30 (extracts 15 bits from
// position 15, bleeding into the timestamp at bits 20-51) but passes with the
// correct nSequenceBits=20 (extracts 5 bits from position 15).
func TestExtractArrayBaseID_LargeTimestamp(t *testing.T) {
jobNumber := uint64(7)
arrayIdx := uint64(3)
sequence := jobNumber<<sequenceHighShift + arrayIdx
// Use a typical Unix-epoch timestamp (bits 20-51 should stay in timestamp)
id := makeJobID(1, 0, 1714560000, tagJobArray, sequence)
base := ExtractArrayBaseID(id)
// The base ID must have the same cluster, apiserver, and timestamp —
// no timestamp bits should leak into the sequence field.
gotCluster := extractBits(base, clusterIDShift, nClusterIDBits)
gotApiserver := extractBits(base, apiserverIDShift, nApiserverIDBits)
gotTimestamp := extractBits(base, timestampShift, nTimestampBits)
if gotCluster != 1 {
t.Errorf("cluster ID leaked: got %d, want 1", gotCluster)
}
if gotApiserver != 0 {
t.Errorf("apiserver ID leaked: got %d, want 0", gotApiserver)
}
if gotTimestamp != 1714560000 {
t.Errorf("timestamp corrupted: got %d, want 1714560000", gotTimestamp)
}
// The base ID's sequence should be just jobNumber<<sequenceHighShift (idx=0, tag=0)
expectedBase := makeJobID(1, 0, 1714560000, 0, jobNumber<<sequenceHighShift)
if base != expectedBase {
t.Errorf("base ID mismatch with large timestamp: got %d, want %d", base, expectedBase)
}
}
func TestIsArrayJob(t *testing.T) {
// Non-array job (tag=0x00): IsArrayJob returns false
nonArrayID := makeJobID(1, 0, 1700000000, 0, 5)