This is an automated email from the ASF dual-hosted git repository. hubcio pushed a commit to branch perf/task-per-partition in repository https://gitbox.apache.org/repos/asf/iggy.git
commit ec47f67fcce46a5074a2ba903e2088dcc20f10c1 Author: Hubert Gruszecki <[email protected]> AuthorDate: Wed Oct 7 23:00:32 2026 +0200 fix(sdk): recognize partition history changes across clients Go, Node and Java did not recognize the history-change error returned by stale DeleteSegments requests. Add code 3014 to their existing tables and pin its metadata result mapping with regression tests. --- core/metadata/src/stm/result.rs | 4 ++++ foreign/go/errors/errors.yaml | 4 ++++ foreign/go/errors/errors_gen.go | 17 +++++++++++++++++ foreign/go/errors/errors_test.go | 6 ++++++ .../java/org/apache/iggy/exception/IggyErrorCode.java | 1 + .../org/apache/iggy/exception/IggyErrorCodeTest.java | 1 + foreign/node/src/wire/error.code.test.ts | 4 ++++ foreign/node/src/wire/error.code.ts | 1 + 8 files changed, 38 insertions(+) diff --git a/core/metadata/src/stm/result.rs b/core/metadata/src/stm/result.rs index 5d4b49a12..2f75c85a2 100644 --- a/core/metadata/src/stm/result.rs +++ b/core/metadata/src/stm/result.rs @@ -682,6 +682,10 @@ mod tests { partition_id_space_exhausted, IggyError::TooManyPartitions.as_code(), ); + assert_eq!( + u32::from(TruncatePartitionResult::HistoryChanged), + IggyError::PartitionHistoryChanged.as_code(), + ); // Unauthorized (41) - the global in-apply RBAC denial code. assert_eq!(UNAUTHORIZED_CODE, IggyError::Unauthorized.as_code()); diff --git a/foreign/go/errors/errors.yaml b/foreign/go/errors/errors.yaml index 7a6b588d2..5fd40989e 100644 --- a/foreign/go/errors/errors.yaml +++ b/foreign/go/errors/errors.yaml @@ -791,6 +791,10 @@ code: 3013 format: "partition id space exhausted for this topic" fields: [] +- name: PartitionHistoryChanged + code: 3014 + format: "partition history changed after the request was resolved" + fields: [] - name: SegmentNotFound code: 4000 format: "segment not found" diff --git a/foreign/go/errors/errors_gen.go b/foreign/go/errors/errors_gen.go index ce151e65e..a9613e494 100644 --- a/foreign/go/errors/errors_gen.go +++ b/foreign/go/errors/errors_gen.go @@ -1628,6 +1628,17 @@ func (e PartitionIdSpaceExhausted) Is(target error) bool { return ok } +type PartitionHistoryChanged struct{} + +func (e PartitionHistoryChanged) Error() string { + return "partition history changed after the request was resolved" +} +func (e PartitionHistoryChanged) Code() Code { return 3014 } +func (e PartitionHistoryChanged) Is(target error) bool { + _, ok := target.(PartitionHistoryChanged) + return ok +} + type SegmentNotFound struct{} func (e SegmentNotFound) Error() string { return "segment not found" } @@ -2844,6 +2855,7 @@ var ( ErrCannotOpenConsumerOffsetsFile = CannotOpenConsumerOffsetsFile{} ErrTooManyConsumerOffsets = TooManyConsumerOffsets{} ErrPartitionIdSpaceExhausted = PartitionIdSpaceExhausted{} + ErrPartitionHistoryChanged = PartitionHistoryChanged{} ErrSegmentNotFound = SegmentNotFound{} ErrSegmentClosed = SegmentClosed{} ErrInvalidSegmentSize = InvalidSegmentSize{} @@ -3092,6 +3104,7 @@ const ( CannotOpenConsumerOffsetsFileCode Code = 3023 TooManyConsumerOffsetsCode Code = 3024 PartitionIdSpaceExhaustedCode Code = 3013 + PartitionHistoryChangedCode Code = 3014 SegmentNotFoundCode Code = 4000 SegmentClosedCode Code = 4001 InvalidSegmentSizeCode Code = 4002 @@ -3483,6 +3496,8 @@ func (c Code) String() string { return "TooManyConsumerOffsets" case PartitionIdSpaceExhaustedCode: return "PartitionIdSpaceExhausted" + case PartitionHistoryChangedCode: + return "PartitionHistoryChanged" case SegmentNotFoundCode: return "SegmentNotFound" case SegmentClosedCode: @@ -3976,6 +3991,8 @@ func FromCode(code Code) IggyError { return ErrTooManyConsumerOffsets case PartitionIdSpaceExhaustedCode: return ErrPartitionIdSpaceExhausted + case PartitionHistoryChangedCode: + return ErrPartitionHistoryChanged case SegmentNotFoundCode: return ErrSegmentNotFound case SegmentClosedCode: diff --git a/foreign/go/errors/errors_test.go b/foreign/go/errors/errors_test.go index 70a33c4ed..8648a57b6 100644 --- a/foreign/go/errors/errors_test.go +++ b/foreign/go/errors/errors_test.go @@ -70,6 +70,12 @@ func TestIggyError_ConsensusErrors(t *testing.T) { code: RequestTooOldCode, message: "request is below the deduplication window; outcome unknown, resending may duplicate the write", }, + { + err: PartitionHistoryChanged{}, + sentinel: ErrPartitionHistoryChanged, + code: Code(3014), + message: "partition history changed after the request was resolved", + }, { err: ConsumerGroupPartitionNotOwned{ClientId: 4, PartitionId: 9}, sentinel: ErrConsumerGroupPartitionNotOwned, diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/exception/IggyErrorCode.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/exception/IggyErrorCode.java index 752402570..e3c290e65 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/exception/IggyErrorCode.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/exception/IggyErrorCode.java @@ -100,6 +100,7 @@ public enum IggyErrorCode { // Partition errors PARTITION_NOT_FOUND(3007), PARTITION_ID_SPACE_EXHAUSTED(3013), + PARTITION_HISTORY_CHANGED(3014), // Consumer offset errors TOO_MANY_CONSUMER_OFFSETS(3024), diff --git a/foreign/java/java-sdk/src/test/java/org/apache/iggy/exception/IggyErrorCodeTest.java b/foreign/java/java-sdk/src/test/java/org/apache/iggy/exception/IggyErrorCodeTest.java index 0aea979fb..30c0609d3 100644 --- a/foreign/java/java-sdk/src/test/java/org/apache/iggy/exception/IggyErrorCodeTest.java +++ b/foreign/java/java-sdk/src/test/java/org/apache/iggy/exception/IggyErrorCodeTest.java @@ -217,6 +217,7 @@ class IggyErrorCodeTest { // Partition errors "3007, PARTITION_NOT_FOUND", "3013, PARTITION_ID_SPACE_EXHAUSTED", + "3014, PARTITION_HISTORY_CHANGED", "3024, TOO_MANY_CONSUMER_OFFSETS", // Segment errors diff --git a/foreign/node/src/wire/error.code.test.ts b/foreign/node/src/wire/error.code.test.ts index 8ea8123e0..30c260690 100644 --- a/foreign/node/src/wire/error.code.test.ts +++ b/foreign/node/src/wire/error.code.test.ts @@ -34,6 +34,10 @@ it('translates the consumer-offset capacity error', () => { assert.equal(translateErrorCode(3024), 'Consumer offset limit reached for partition, raise [partition] consumer_offsets_max'); }); +it('translates a partition history change', () => { + assert.equal(translateErrorCode(3014), 'Partition history changed after the request was resolved'); +}); + it('translates the consumer-group error range', () => { assert.equal( translateErrorCode(5000), diff --git a/foreign/node/src/wire/error.code.ts b/foreign/node/src/wire/error.code.ts index d05fc9d8e..5fd61dcfc 100644 --- a/foreign/node/src/wire/error.code.ts +++ b/foreign/node/src/wire/error.code.ts @@ -169,6 +169,7 @@ export const translateErrorCode = (code: number): string => { case '3023': return "Cannot open consumer offsets file for path: {0}"; case '3024': return "Consumer offset limit reached for partition, raise [partition] consumer_offsets_max"; case '3013': return "Partition id space exhausted for this topic"; + case '3014': return "Partition history changed after the request was resolved"; // MESSAGE case '4000': return "Segment not found";
