package org.codelibs.elasticsearch.taste.writer;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.codelibs.elasticsearch.taste.TasteConstants;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
public class ResultWriter extends AbstractWriter {
private static final ESLogger logger = Loggers
.getLogger(ResultWriter.class);
protected volatile Queue<Map<String, Object>> resultQueue = new ConcurrentLinkedQueue<>();
protected String userIdField = TasteConstants.USER_ID_FIELD;
protected String itemIdField = TasteConstants.ITEM_ID_FIELD;
protected int maxQueueSize = 1000;
public ResultWriter(final Client client, final String index,
final String type) {
super(client, index, type);
}
@Override
public void close() throws IOException {
flush();
}
public void write(final String evaluatorId, final long userID,
final long itemID, final String resultType, final float actual,
final float estimate, final long time) {
final Map<String, Object> rootObj = new HashMap<>();
rootObj.put("result_type", resultType);
rootObj.put("evaluator_id", evaluatorId);
rootObj.put(userIdField, userID);
rootObj.put(itemIdField, itemID);
rootObj.put("actual", actual);
if (!Float.isNaN(estimate)) {
rootObj.put("estimate", estimate);
}
rootObj.put("computing_time", time);
resultQueue.add(rootObj);
if (resultQueue.size() > maxQueueSize) {
flush();
}
}
protected synchronized void flush() {
if (resultQueue.isEmpty()) {
return;
}
final Queue<Map<String, Object>> currentQueue = resultQueue;
resultQueue = new ConcurrentLinkedQueue<>();
final BulkRequestBuilder bulkRequest = client.prepareBulk();
for (final Map<String, Object> obj : currentQueue) {
bulkRequest.add(client.prepareIndex(index, type).setSource(obj));
}
bulkRequest.execute(new ActionListener<BulkResponse>() {
@Override
public void onResponse(final BulkResponse response) {
if (response.hasFailures()) {
logger.error("Failed to write a result on {}/{}: {}",
index, type, response.buildFailureMessage());
} else {
logger.info("Wrote {} results in {}/{}.",
currentQueue.size(), index, type);
}
}
@Override
public void onFailure(final Throwable e) {
logger.error("Failed to write a result on {}/{}.", e, index,
type);
}
});
}
public void setUserIdField(final String userIdField) {
this.userIdField = userIdField;
}
public void setItemIdField(final String itemIdField) {
this.itemIdField = itemIdField;
}
public void setMaxQueueSize(final int maxQueueSize) {
this.maxQueueSize = maxQueueSize;
}
}