io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.core.support.SimpleBatchingStrategy Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.core.support;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.core.Message;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.core.MessageProperties;
import io.bitsensor.plugins.shaded.org.springframework.util.Assert;
/**
* A simple batching strategy that supports only one exchange/routingKey; includes a batch
* size, a batched message size limit and a timeout. The message properties from the first
* message in the batch is used in the batch message. Each message is preceded by a 4 byte
* length field.
*
* @author Gary Russell
* @since 1.4.1
*
*/
public class SimpleBatchingStrategy implements BatchingStrategy {
private final int batchSize;
private final int bufferLimit;
private final long timeout;
private final List messages = new ArrayList();
private String exchange;
private String routingKey;
private int currentSize;
/**
* @param batchSize the batch size.
* @param bufferLimit the max buffer size; could trigger a short batch. Does not apply
* to a single message.
* @param timeout the batch timeout.
*/
public SimpleBatchingStrategy(int batchSize, int bufferLimit, long timeout) {
this.batchSize = batchSize;
this.bufferLimit = bufferLimit;
this.timeout = timeout;
}
@Override
public MessageBatch addToBatch(String exchange, String routingKey, Message message) {
if (this.exchange != null) {
Assert.isTrue(this.exchange.equals(exchange), "Cannot send to different exchanges in the same batch");
}
else {
this.exchange = exchange;
}
if (this.routingKey != null) {
Assert.isTrue(this.routingKey.equals(routingKey), "Cannot send with different routing keys in the same batch");
}
else {
this.routingKey = routingKey;
}
int bufferUse = 4 + message.getBody().length;
MessageBatch batch = null;
if (this.messages.size() > 0 && this.currentSize + bufferUse > this.bufferLimit) {
batch = doReleaseBatch();
this.exchange = exchange;
this.routingKey = routingKey;
}
this.currentSize += bufferUse;
this.messages.add(message);
if (batch == null && (this.messages.size() >= this.batchSize
|| this.currentSize >= this.bufferLimit)) {
batch = doReleaseBatch();
}
return batch;
}
@Override
public Date nextRelease() {
if (this.messages.size() == 0 || this.timeout <= 0) {
return null;
}
else if (this.currentSize >= this.bufferLimit) {
// release immediately, we're already over the limit
return new Date();
}
else {
return new Date(System.currentTimeMillis() + this.timeout);
}
}
@Override
public Collection releaseBatches() {
MessageBatch batch = doReleaseBatch();
if (batch == null) {
return Collections.emptyList();
}
else {
return Collections.singletonList(batch);
}
}
private MessageBatch doReleaseBatch() {
if (this.messages.size() < 1) {
return null;
}
Message message = assembleMessage();
MessageBatch messageBatch = new MessageBatch(this.exchange, this.routingKey, message);
this.messages.clear();
this.currentSize = 0;
this.exchange = null;
this.routingKey = null;
return messageBatch;
}
private Message assembleMessage() {
if (this.messages.size() == 1) {
return this.messages.get(0);
}
MessageProperties messageProperties = this.messages.get(0).getMessageProperties();
byte[] body = new byte[this.currentSize];
ByteBuffer bytes = ByteBuffer.wrap(body);
for (Message message : this.messages) {
bytes.putInt(message.getBody().length);
bytes.put(message.getBody());
}
messageProperties.getHeaders().put(MessageProperties.SPRING_BATCH_FORMAT, MessageProperties.BATCH_FORMAT_LENGTH_HEADER4);
return new Message(body, messageProperties);
}
}