@@ -905,10 +905,7 @@ public void doInTransactionWithoutResult(TransactionStatus s) {
905
905
}
906
906
catch (RuntimeException e ) {
907
907
this .logger .error ("Transaction rolled back" , e );
908
- Map <TopicPartition , Long > seekOffsets = new HashMap <>();
909
- records .forEach (r -> seekOffsets .computeIfAbsent (new TopicPartition (r .topic (), r .partition ()),
910
- v -> r .offset ()));
911
- seekOffsets .entrySet ().forEach (entry -> this .consumer .seek (entry .getKey (), entry .getValue ()));
908
+ getAfterRollbackProcessor ().process (recordList , this .consumer );
912
909
}
913
910
}
914
911
@@ -954,7 +951,7 @@ private RuntimeException doInvokeBatchListener(final ConsumerRecords<K, V> recor
954
951
}
955
952
}
956
953
catch (RuntimeException e ) {
957
- if (this .containerProperties .isAckOnError () && !this .autoCommit ) {
954
+ if (this .containerProperties .isAckOnError () && !this .autoCommit && producer == null ) {
958
955
for (ConsumerRecord <K , V > record : getHighestOffsetRecords (recordList )) {
959
956
this .acks .add (record );
960
957
}
@@ -970,7 +967,11 @@ private RuntimeException doInvokeBatchListener(final ConsumerRecords<K, V> recor
970
967
else {
971
968
this .batchErrorHandler .handle (e , records , this .consumer );
972
969
}
970
+ // if the handler handled the error (no exception), go ahead and commit
973
971
if (producer != null ) {
972
+ for (ConsumerRecord <K , V > record : getHighestOffsetRecords (recordList )) {
973
+ this .acks .add (record );
974
+ }
974
975
sendOffsetsToTransaction (producer );
975
976
}
976
977
}
@@ -1030,8 +1031,12 @@ public void doInTransactionWithoutResult(TransactionStatus s) {
1030
1031
}
1031
1032
catch (RuntimeException e ) {
1032
1033
this .logger .error ("Transaction rolled back" , e );
1033
- this .consumer .seek (new TopicPartition (record .topic (), record .partition ()), record .offset ());
1034
- break ;
1034
+ List <ConsumerRecord <K , V >> unprocessed = new ArrayList <>();
1035
+ unprocessed .add (record );
1036
+ while (iterator .hasNext ()) {
1037
+ unprocessed .add (iterator .next ());
1038
+ }
1039
+ getAfterRollbackProcessor ().process (unprocessed , this .consumer );
1035
1040
}
1036
1041
}
1037
1042
}
@@ -1081,54 +1086,20 @@ private RuntimeException doInvokeRecordListener(final ConsumerRecord<K, V> recor
1081
1086
this .listener .onMessage (record );
1082
1087
break ;
1083
1088
}
1084
- if (this .isRecordAck ) {
1085
- Map <TopicPartition , OffsetAndMetadata > offsetsToCommit =
1086
- Collections .singletonMap (new TopicPartition (record .topic (), record .partition ()),
1087
- new OffsetAndMetadata (record .offset () + 1 ));
1088
- if (producer == null ) {
1089
- this .commitLogger .log (() -> "Committing: " + offsetsToCommit );
1090
- if (this .containerProperties .isSyncCommits ()) {
1091
- this .consumer .commitSync (offsetsToCommit );
1092
- }
1093
- else {
1094
- this .consumer .commitAsync (offsetsToCommit , this .commitCallback );
1095
- }
1096
- }
1097
- else {
1098
- this .acks .add (record );
1099
- }
1100
- }
1101
- else if (!this .isAnyManualAck && !this .autoCommit ) {
1102
- this .acks .add (record );
1103
- }
1104
- if (producer != null ) {
1105
- sendOffsetsToTransaction (producer );
1106
- }
1089
+ ackCurrent (record , producer );
1107
1090
}
1108
1091
catch (RuntimeException e ) {
1109
1092
if (this .containerProperties .isAckOnError () && !this .autoCommit && producer == null ) {
1110
- if (this .isRecordAck ) {
1111
- Map <TopicPartition , OffsetAndMetadata > offsetsToCommit =
1112
- Collections .singletonMap (new TopicPartition (record .topic (), record .partition ()),
1113
- new OffsetAndMetadata (record .offset () + 1 ));
1114
- this .commitLogger .log (() -> "Committing: " + offsetsToCommit );
1115
- if (this .containerProperties .isSyncCommits ()) {
1116
- this .consumer .commitSync (offsetsToCommit );
1117
- }
1118
- else {
1119
- this .consumer .commitAsync (offsetsToCommit , this .commitCallback );
1120
- }
1121
- }
1122
- else if (!this .isAnyManualAck ) {
1123
- this .acks .add (record );
1124
- }
1093
+ ackCurrent (record , producer );
1125
1094
}
1126
1095
if (this .errorHandler == null ) {
1127
1096
throw e ;
1128
1097
}
1129
1098
try {
1130
1099
if (this .errorHandler instanceof ContainerAwareErrorHandler ) {
1131
- processCommits ();
1100
+ if (producer == null ) {
1101
+ processCommits ();
1102
+ }
1132
1103
List <ConsumerRecord <?, ?>> records = new ArrayList <>();
1133
1104
records .add (record );
1134
1105
while (iterator .hasNext ()) {
@@ -1139,13 +1110,13 @@ else if (!this.isAnyManualAck) {
1139
1110
}
1140
1111
else {
1141
1112
this .errorHandler .handle (e , record , this .consumer );
1142
- if ( producer != null ) {
1143
- try {
1144
- sendOffsetsToTransaction ( producer );
1145
- }
1146
- catch ( Exception e1 ) {
1147
- this . logger . error ( "Send offsets to transaction failed" , e1 );
1148
- }
1113
+ }
1114
+ if ( producer != null ) {
1115
+ try {
1116
+ sendOffsetsToTransaction ( producer );
1117
+ }
1118
+ catch ( Exception e1 ) {
1119
+ this . logger . error ( "Send offsets to transaction failed" , e1 );
1149
1120
}
1150
1121
}
1151
1122
}
@@ -1161,6 +1132,37 @@ else if (!this.isAnyManualAck) {
1161
1132
return null ;
1162
1133
}
1163
1134
1135
+ public void ackCurrent (final ConsumerRecord <K , V > record , @ SuppressWarnings ("rawtypes" ) Producer producer ) {
1136
+ if (this .isRecordAck ) {
1137
+ Map <TopicPartition , OffsetAndMetadata > offsetsToCommit =
1138
+ Collections .singletonMap (new TopicPartition (record .topic (), record .partition ()),
1139
+ new OffsetAndMetadata (record .offset () + 1 ));
1140
+ if (producer == null ) {
1141
+ this .commitLogger .log (() -> "Committing: " + offsetsToCommit );
1142
+ if (this .containerProperties .isSyncCommits ()) {
1143
+ this .consumer .commitSync (offsetsToCommit );
1144
+ }
1145
+ else {
1146
+ this .consumer .commitAsync (offsetsToCommit , this .commitCallback );
1147
+ }
1148
+ }
1149
+ else {
1150
+ this .acks .add (record );
1151
+ }
1152
+ }
1153
+ else if (!this .isAnyManualAck && !this .autoCommit ) {
1154
+ this .acks .add (record );
1155
+ }
1156
+ if (producer != null ) {
1157
+ try {
1158
+ sendOffsetsToTransaction (producer );
1159
+ }
1160
+ catch (Exception e ) {
1161
+ this .logger .error ("Send offsets to transaction failed" , e );
1162
+ }
1163
+ }
1164
+ }
1165
+
1164
1166
@ SuppressWarnings ({ "unchecked" , "rawtypes" })
1165
1167
private void sendOffsetsToTransaction (Producer producer ) {
1166
1168
handleAcks ();
0 commit comments