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";

Reply via email to