|
132 | 132 | import org.apache.pulsar.common.naming.NamespaceName;
|
133 | 133 | import org.apache.pulsar.common.naming.TopicName;
|
134 | 134 | import org.apache.pulsar.common.policies.data.BacklogQuota;
|
| 135 | +import org.apache.pulsar.common.policies.data.BacklogQuota.BacklogQuotaType; |
135 | 136 | import org.apache.pulsar.common.policies.data.NamespaceOperation;
|
136 | 137 | import org.apache.pulsar.common.policies.data.TopicOperation;
|
137 | 138 | import org.apache.pulsar.common.policies.data.stats.ConsumerStatsImpl;
|
@@ -1189,65 +1190,70 @@ protected void handleProducer(final CommandProducer cmdProducer) {
|
1189 | 1190 | service.getOrCreateTopic(topicName.toString()).thenAccept((Topic topic) -> {
|
1190 | 1191 | // Before creating producer, check if backlog quota exceeded
|
1191 | 1192 | // on topic for size based limit and time based limit
|
1192 |
| - for (BacklogQuota.BacklogQuotaType backlogQuotaType : BacklogQuota.BacklogQuotaType.values()) { |
1193 |
| - if (topic.isBacklogQuotaExceeded(producerName, backlogQuotaType)) { |
1194 |
| - IllegalStateException illegalStateException = new IllegalStateException( |
1195 |
| - "Cannot create producer on topic with backlog quota exceeded"); |
1196 |
| - BacklogQuota.RetentionPolicy retentionPolicy = topic |
1197 |
| - .getBacklogQuota(backlogQuotaType).getPolicy(); |
1198 |
| - if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_request_hold) { |
1199 |
| - commandSender.sendErrorResponse(requestId, |
1200 |
| - ServerError.ProducerBlockedQuotaExceededError, |
1201 |
| - illegalStateException.getMessage()); |
1202 |
| - } else if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_exception) { |
1203 |
| - commandSender.sendErrorResponse(requestId, |
1204 |
| - ServerError.ProducerBlockedQuotaExceededException, |
1205 |
| - illegalStateException.getMessage()); |
1206 |
| - } |
1207 |
| - producerFuture.completeExceptionally(illegalStateException); |
1208 |
| - producers.remove(producerId, producerFuture); |
1209 |
| - return; |
| 1193 | + CompletableFuture<Void> backlogQuotaCheckFuture = CompletableFuture.allOf( |
| 1194 | + topic.checkBacklogQuotaExceeded(producerName, BacklogQuotaType.destination_storage), |
| 1195 | + topic.checkBacklogQuotaExceeded(producerName, BacklogQuotaType.message_age)); |
| 1196 | + backlogQuotaCheckFuture.exceptionally(throwable -> { |
| 1197 | + //throwable should be CompletionException holding TopicBacklogQuotaExceededException |
| 1198 | + BrokerServiceException.TopicBacklogQuotaExceededException exception = |
| 1199 | + (BrokerServiceException.TopicBacklogQuotaExceededException) throwable.getCause(); |
| 1200 | + IllegalStateException illegalStateException = new IllegalStateException(exception); |
| 1201 | + BacklogQuota.RetentionPolicy retentionPolicy = exception.getRetentionPolicy(); |
| 1202 | + if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_request_hold) { |
| 1203 | + commandSender.sendErrorResponse(requestId, |
| 1204 | + ServerError.ProducerBlockedQuotaExceededError, |
| 1205 | + illegalStateException.getMessage()); |
| 1206 | + } else if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_exception) { |
| 1207 | + commandSender.sendErrorResponse(requestId, |
| 1208 | + ServerError.ProducerBlockedQuotaExceededException, |
| 1209 | + illegalStateException.getMessage()); |
1210 | 1210 | }
|
1211 |
| - } |
1212 |
| - // Check whether the producer will publish encrypted messages or not |
1213 |
| - if ((topic.isEncryptionRequired() || encryptionRequireOnProducer) && !isEncrypted) { |
1214 |
| - String msg = String.format("Encryption is required in %s", topicName); |
1215 |
| - log.warn("[{}] {}", remoteAddress, msg); |
1216 |
| - commandSender.sendErrorResponse(requestId, ServerError.MetadataError, msg); |
| 1211 | + producerFuture.completeExceptionally(illegalStateException); |
1217 | 1212 | producers.remove(producerId, producerFuture);
|
1218 |
| - return; |
1219 |
| - } |
| 1213 | + return null; |
| 1214 | + }); |
1220 | 1215 |
|
1221 |
| - disableTcpNoDelayIfNeeded(topicName.toString(), producerName); |
| 1216 | + backlogQuotaCheckFuture.thenRun(() -> { |
| 1217 | + // Check whether the producer will publish encrypted messages or not |
| 1218 | + if ((topic.isEncryptionRequired() || encryptionRequireOnProducer) && !isEncrypted) { |
| 1219 | + String msg = String.format("Encryption is required in %s", topicName); |
| 1220 | + log.warn("[{}] {}", remoteAddress, msg); |
| 1221 | + commandSender.sendErrorResponse(requestId, ServerError.MetadataError, msg); |
| 1222 | + producers.remove(producerId, producerFuture); |
| 1223 | + return; |
| 1224 | + } |
1222 | 1225 |
|
1223 |
| - CompletableFuture<SchemaVersion> schemaVersionFuture = tryAddSchema(topic, schema); |
| 1226 | + disableTcpNoDelayIfNeeded(topicName.toString(), producerName); |
1224 | 1227 |
|
1225 |
| - schemaVersionFuture.exceptionally(exception -> { |
1226 |
| - String message = exception.getMessage(); |
1227 |
| - if (exception.getCause() != null) { |
1228 |
| - message += (" caused by " + exception.getCause()); |
1229 |
| - } |
1230 |
| - commandSender.sendErrorResponse(requestId, |
1231 |
| - BrokerServiceException.getClientErrorCode(exception), |
1232 |
| - message); |
1233 |
| - producers.remove(producerId, producerFuture); |
1234 |
| - return null; |
1235 |
| - }); |
| 1228 | + CompletableFuture<SchemaVersion> schemaVersionFuture = tryAddSchema(topic, schema); |
1236 | 1229 |
|
1237 |
| - schemaVersionFuture.thenAccept(schemaVersion -> { |
1238 |
| - topic.checkIfTransactionBufferRecoverCompletely(isTxnEnabled).thenAccept(future -> { |
1239 |
| - buildProducerAndAddTopic(topic, producerId, producerName, requestId, isEncrypted, |
1240 |
| - metadata, schemaVersion, epoch, userProvidedProducerName, topicName, |
1241 |
| - producerAccessMode, topicEpoch, producerFuture); |
1242 |
| - }).exceptionally(exception -> { |
1243 |
| - Throwable cause = exception.getCause(); |
1244 |
| - log.error("producerId {}, requestId {} : TransactionBuffer recover failed", |
1245 |
| - producerId, requestId, exception); |
| 1230 | + schemaVersionFuture.exceptionally(exception -> { |
| 1231 | + String message = exception.getMessage(); |
| 1232 | + if (exception.getCause() != null) { |
| 1233 | + message += (" caused by " + exception.getCause()); |
| 1234 | + } |
1246 | 1235 | commandSender.sendErrorResponse(requestId,
|
1247 |
| - ServiceUnitNotReadyException.getClientErrorCode(cause), |
1248 |
| - cause.getMessage()); |
| 1236 | + BrokerServiceException.getClientErrorCode(exception), |
| 1237 | + message); |
| 1238 | + producers.remove(producerId, producerFuture); |
1249 | 1239 | return null;
|
1250 | 1240 | });
|
| 1241 | + |
| 1242 | + schemaVersionFuture.thenAccept(schemaVersion -> { |
| 1243 | + topic.checkIfTransactionBufferRecoverCompletely(isTxnEnabled).thenAccept(future -> { |
| 1244 | + buildProducerAndAddTopic(topic, producerId, producerName, requestId, isEncrypted, |
| 1245 | + metadata, schemaVersion, epoch, userProvidedProducerName, topicName, |
| 1246 | + producerAccessMode, topicEpoch, producerFuture); |
| 1247 | + }).exceptionally(exception -> { |
| 1248 | + Throwable cause = exception.getCause(); |
| 1249 | + log.error("producerId {}, requestId {} : TransactionBuffer recover failed", |
| 1250 | + producerId, requestId, exception); |
| 1251 | + commandSender.sendErrorResponse(requestId, |
| 1252 | + ServiceUnitNotReadyException.getClientErrorCode(cause), |
| 1253 | + cause.getMessage()); |
| 1254 | + return null; |
| 1255 | + }); |
| 1256 | + }); |
1251 | 1257 | });
|
1252 | 1258 | }).exceptionally(exception -> {
|
1253 | 1259 | Throwable cause = exception.getCause();
|
|
0 commit comments