未验证 提交 a2897db4 编写于 作者: K kezhenxu94 提交者: GitHub

Fix the so11y latency of persistence execution latency not correct in ElasticSearch storage (#8161)

The ES persistence execution is now asynchronous and the execution
latency only counts the time to insert the requests into the bulk
processor, instead of the time after the requests are flushed into the
storage, this patch fixes that issue.

There is the same issue in prepare latency but that needs more changes
so I'll leave it to another pull request.
上级 973fba08
...@@ -54,6 +54,7 @@ Release Notes. ...@@ -54,6 +54,7 @@ Release Notes.
* Add filter mechanism in MAL core to filter metrics. * Add filter mechanism in MAL core to filter metrics.
* Fix concurrency bug in MAL `increase`-related calculation. * Fix concurrency bug in MAL `increase`-related calculation.
* Fix a null pointer bug when building `SampleFamily`. * Fix a null pointer bug when building `SampleFamily`.
* Fix the so11y latency of persistence execution latency not correct in ElasticSearch storage.
#### UI #### UI
......
...@@ -179,14 +179,14 @@ public class MetricsPersistentWorker extends PersistenceWorker<Metrics> { ...@@ -179,14 +179,14 @@ public class MetricsPersistentWorker extends PersistenceWorker<Metrics> {
@Override @Override
public List<PrepareRequest> buildBatchRequests() { public List<PrepareRequest> buildBatchRequests() {
if (persistentCounter++ % persistentMod != 0) { if (persistentCounter++ % persistentMod != 0) {
return Collections.EMPTY_LIST; return Collections.emptyList();
} }
final List<Metrics> lastCollection = getCache().read(); final List<Metrics> lastCollection = getCache().read();
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
if (lastCollection.size() == 0) { if (lastCollection.size() == 0) {
return Collections.EMPTY_LIST; return Collections.emptyList();
} }
/* /*
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.core.storage; package org.apache.skywalking.oap.server.core.storage;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.apache.skywalking.oap.server.library.client.request.InsertRequest; import org.apache.skywalking.oap.server.library.client.request.InsertRequest;
import org.apache.skywalking.oap.server.library.client.request.PrepareRequest; import org.apache.skywalking.oap.server.library.client.request.PrepareRequest;
...@@ -43,5 +44,5 @@ public interface IBatchDAO extends DAO { ...@@ -43,5 +44,5 @@ public interface IBatchDAO extends DAO {
* *
* @param prepareRequests data to insert or update. No delete happens in streaming mode. * @param prepareRequests data to insert or update. No delete happens in streaming mode.
*/ */
void flush(List<PrepareRequest> prepareRequests); CompletableFuture<Void> flush(List<PrepareRequest> prepareRequests);
} }
...@@ -21,12 +21,11 @@ package org.apache.skywalking.oap.server.core.storage; ...@@ -21,12 +21,11 @@ package org.apache.skywalking.oap.server.core.storage;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.library.util.RunnableWithExceptionProtection;
import org.apache.skywalking.oap.server.core.CoreModuleConfig; import org.apache.skywalking.oap.server.core.CoreModuleConfig;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor; import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.PersistenceWorker; import org.apache.skywalking.oap.server.core.analysis.worker.PersistenceWorker;
...@@ -34,6 +33,7 @@ import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor ...@@ -34,6 +33,7 @@ import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor
import org.apache.skywalking.oap.server.library.client.request.PrepareRequest; import org.apache.skywalking.oap.server.library.client.request.PrepareRequest;
import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.CollectionUtils; import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.RunnableWithExceptionProtection;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule; import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics; import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics;
import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics;
...@@ -56,21 +56,25 @@ public enum PersistenceTimer { ...@@ -56,21 +56,25 @@ public enum PersistenceTimer {
public void start(ModuleManager moduleManager, CoreModuleConfig moduleConfig) { public void start(ModuleManager moduleManager, CoreModuleConfig moduleConfig) {
log.info("persistence timer start"); log.info("persistence timer start");
IBatchDAO batchDAO = moduleManager.find(StorageModule.NAME).provider().getService(IBatchDAO.class); IBatchDAO batchDAO =
moduleManager.find(StorageModule.NAME).provider().getService(IBatchDAO.class);
MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME) MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME)
.provider() .provider()
.getService(MetricsCreator.class); .getService(MetricsCreator.class);
errorCounter = metricsCreator.createCounter( errorCounter = metricsCreator.createCounter(
"persistence_timer_bulk_error_count", "Error execution of the prepare stage in persistence timer", "persistence_timer_bulk_error_count",
"Error execution of the prepare stage in persistence timer",
MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE
); );
prepareLatency = metricsCreator.createHistogramMetric( prepareLatency = metricsCreator.createHistogramMetric(
"persistence_timer_bulk_prepare_latency", "Latency of the prepare stage in persistence timer", "persistence_timer_bulk_prepare_latency",
"Latency of the prepare stage in persistence timer",
MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE
); );
executeLatency = metricsCreator.createHistogramMetric( executeLatency = metricsCreator.createHistogramMetric(
"persistence_timer_bulk_execute_latency", "Latency of the execute stage in persistence timer", "persistence_timer_bulk_execute_latency",
"Latency of the execute stage in persistence timer",
MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE
); );
allLatency = metricsCreator.createHistogramMetric( allLatency = metricsCreator.createHistogramMetric(
...@@ -82,69 +86,69 @@ public enum PersistenceTimer { ...@@ -82,69 +86,69 @@ public enum PersistenceTimer {
if (!isStarted) { if (!isStarted) {
Executors.newSingleThreadScheduledExecutor() Executors.newSingleThreadScheduledExecutor()
.scheduleWithFixedDelay( .scheduleWithFixedDelay(
new RunnableWithExceptionProtection(() -> extractDataAndSave(batchDAO), t -> log new RunnableWithExceptionProtection(
.error("Extract data and save failure.", t)), 5, moduleConfig.getPersistentPeriod(), () -> extractDataAndSave(batchDAO).join(),
TimeUnit.SECONDS t -> log.error("Extract data and save failure.", t)
), 5, moduleConfig.getPersistentPeriod(), TimeUnit.SECONDS
); );
this.isStarted = true; this.isStarted = true;
} }
} }
private void extractDataAndSave(IBatchDAO batchDAO) { private CompletableFuture<Void> extractDataAndSave(IBatchDAO batchDAO) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Extract data and save"); log.debug("Extract data and save");
} }
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
try (HistogramMetrics.Timer allTimer = allLatency.createTimer()) { HistogramMetrics.Timer allTimer = allLatency.createTimer();
List<PersistenceWorker<? extends StorageData>> persistenceWorkers = new ArrayList<>(); List<PersistenceWorker<? extends StorageData>> workers = new ArrayList<>();
persistenceWorkers.addAll(TopNStreamProcessor.getInstance().getPersistentWorkers()); workers.addAll(TopNStreamProcessor.getInstance().getPersistentWorkers());
persistenceWorkers.addAll(MetricsStreamProcessor.getInstance().getPersistentWorkers()); workers.addAll(MetricsStreamProcessor.getInstance().getPersistentWorkers());
CountDownLatch countDownLatch = new CountDownLatch(persistenceWorkers.size()); final CompletableFuture<Void> future =
persistenceWorkers.forEach(worker -> { CompletableFuture.allOf(workers.stream().map(worker -> {
prepareExecutorService.submit(() -> { return CompletableFuture.runAsync(() -> {
List<PrepareRequest> innerPrepareRequests = null; List<PrepareRequest> innerPrepareRequests;
try {
// Prepare stage // Prepare stage
try (HistogramMetrics.Timer timer = prepareLatency.createTimer()) { try (HistogramMetrics.Timer ignored = prepareLatency.createTimer()) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("extract {} worker data and save", worker.getClass().getName()); log.debug(
"extract {} worker data and save",
worker.getClass().getName()
);
} }
innerPrepareRequests = worker.buildBatchRequests(); innerPrepareRequests = worker.buildBatchRequests();
worker.endOfRound(); worker.endOfRound();
} catch (Throwable e) {
log.error(e.getMessage(), e);
} }
// Execution stage if (CollectionUtils.isEmpty(innerPrepareRequests)) {
try (HistogramMetrics.Timer executeLatencyTimer = executeLatency.createTimer()) { return;
if (CollectionUtils.isNotEmpty(innerPrepareRequests)) {
batchDAO.flush(innerPrepareRequests);
} }
} catch (Throwable e) {
log.error(e.getMessage(), e);
}
} finally {
countDownLatch.countDown();
}
});
});
countDownLatch.await(); // Execution stage
} catch (Throwable e) { HistogramMetrics.Timer executeLatencyTimer = executeLatency.createTimer();
errorCounter.inc(); batchDAO.flush(innerPrepareRequests)
log.error(e.getMessage(), e); .whenComplete(($1, $2) -> executeLatencyTimer.close());
} finally { }, prepareExecutorService);
}).toArray(CompletableFuture[]::new));
future.whenComplete((unused, throwable) -> {
allTimer.close();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Persistence data save finish"); log.debug(
"Batch persistence duration: {} ms",
System.currentTimeMillis() - startTime
);
} }
if (throwable != null) {
errorCounter.inc();
log.error(throwable.getMessage(), throwable);
} }
});
log.debug("Batch persistence duration: {} ms", System.currentTimeMillis() - startTime); return future;
} }
} }
...@@ -23,6 +23,7 @@ import java.util.HashSet; ...@@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import lombok.Data; import lombok.Data;
import org.apache.skywalking.oap.server.core.CoreModuleConfig; import org.apache.skywalking.oap.server.core.CoreModuleConfig;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsPersistentWorker; import org.apache.skywalking.oap.server.core.analysis.worker.MetricsPersistentWorker;
...@@ -61,10 +62,11 @@ public class PersistenceTimerTest { ...@@ -61,10 +62,11 @@ public class PersistenceTimerTest {
} }
@Override @Override
public void flush(final List<PrepareRequest> prepareRequests) { public CompletableFuture<Void> flush(final List<PrepareRequest> prepareRequests) {
synchronized (result) { synchronized (result) {
result.addAll(prepareRequests); result.addAll(prepareRequests);
} }
return CompletableFuture.completedFuture(null);
} }
}; };
for (int i = 0; i < workCount; i++) { for (int i = 0; i < workCount; i++) {
...@@ -79,7 +81,8 @@ public class PersistenceTimerTest { ...@@ -79,7 +81,8 @@ public class PersistenceTimerTest {
PersistenceTimer.INSTANCE.isStarted = true; PersistenceTimer.INSTANCE.isStarted = true;
PersistenceTimer.INSTANCE.start(moduleManager, moduleConfig); PersistenceTimer.INSTANCE.start(moduleManager, moduleConfig);
Whitebox.invokeMethod(PersistenceTimer.INSTANCE, "extractDataAndSave", iBatchDAO); CompletableFuture<Void> f = Whitebox.invokeMethod(PersistenceTimer.INSTANCE, "extractDataAndSave", iBatchDAO);
f.join();
Assert.assertEquals(count * workCount * 2, result.size()); Assert.assertEquals(count * workCount * 2, result.size());
} }
......
...@@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; ...@@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.library.elasticsearch.ElasticSearch; import org.apache.skywalking.library.elasticsearch.ElasticSearch;
...@@ -41,7 +42,7 @@ import static java.util.Objects.requireNonNull; ...@@ -41,7 +42,7 @@ import static java.util.Objects.requireNonNull;
@Slf4j @Slf4j
public final class BulkProcessor { public final class BulkProcessor {
private final ArrayBlockingQueue<Object> requests; private final ArrayBlockingQueue<Holder> requests;
private final AtomicReference<ElasticSearch> es; private final AtomicReference<ElasticSearch> es;
private final int bulkActions; private final int bulkActions;
...@@ -74,21 +75,21 @@ public final class BulkProcessor { ...@@ -74,21 +75,21 @@ public final class BulkProcessor {
this::flush, 0, flushInterval.getSeconds(), TimeUnit.SECONDS); this::flush, 0, flushInterval.getSeconds(), TimeUnit.SECONDS);
} }
public BulkProcessor add(IndexRequest request) { public CompletableFuture<Void> add(IndexRequest request) {
internalAdd(request); return internalAdd(request);
return this;
} }
public BulkProcessor add(UpdateRequest request) { public CompletableFuture<Void> add(UpdateRequest request) {
internalAdd(request); return internalAdd(request);
return this;
} }
@SneakyThrows @SneakyThrows
private void internalAdd(Object request) { private CompletableFuture<Void> internalAdd(Object request) {
requireNonNull(request, "request"); requireNonNull(request, "request");
requests.put(request); final CompletableFuture<Void> f = new CompletableFuture<>();
requests.put(new Holder(f, request));
flushIfNeeded(); flushIfNeeded();
return f;
} }
@SneakyThrows @SneakyThrows
...@@ -110,7 +111,7 @@ public final class BulkProcessor { ...@@ -110,7 +111,7 @@ public final class BulkProcessor {
return; return;
} }
final List<Object> batch = new ArrayList<>(requests.size()); final List<Holder> batch = new ArrayList<>(requests.size());
requests.drainTo(batch); requests.drainTo(batch);
final CompletableFuture<Void> flush = doFlush(batch); final CompletableFuture<Void> flush = doFlush(batch);
...@@ -118,7 +119,7 @@ public final class BulkProcessor { ...@@ -118,7 +119,7 @@ public final class BulkProcessor {
flush.join(); flush.join();
} }
private CompletableFuture<Void> doFlush(final List<Object> batch) { private CompletableFuture<Void> doFlush(final List<Holder> batch) {
log.debug("Executing bulk with {} requests", batch.size()); log.debug("Executing bulk with {} requests", batch.size());
if (batch.isEmpty()) { if (batch.isEmpty()) {
...@@ -129,8 +130,8 @@ public final class BulkProcessor { ...@@ -129,8 +130,8 @@ public final class BulkProcessor {
try { try {
final RequestFactory rf = v.requestFactory(); final RequestFactory rf = v.requestFactory();
final List<byte[]> bs = new ArrayList<>(); final List<byte[]> bs = new ArrayList<>();
for (final Object request : batch) { for (final Holder holder : batch) {
bs.add(v.codec().encode(request)); bs.add(v.codec().encode(holder.request));
bs.add("\n".getBytes()); bs.add("\n".getBytes());
} }
final ByteBuf content = Unpooled.wrappedBuffer(bs.toArray(new byte[0][])); final ByteBuf content = Unpooled.wrappedBuffer(bs.toArray(new byte[0][]));
...@@ -147,11 +148,20 @@ public final class BulkProcessor { ...@@ -147,11 +148,20 @@ public final class BulkProcessor {
}); });
future.whenComplete((ignored, exception) -> { future.whenComplete((ignored, exception) -> {
if (exception != null) { if (exception != null) {
batch.stream().map(it -> it.future)
.forEach(it -> it.completeExceptionally(exception));
log.error("Failed to execute requests in bulk", exception); log.error("Failed to execute requests in bulk", exception);
} else { } else {
log.debug("Succeeded to execute {} requests in bulk", batch.size()); log.debug("Succeeded to execute {} requests in bulk", batch.size());
batch.stream().map(it -> it.future).forEach(it -> it.complete(null));
} }
}); });
return future; return future;
} }
@RequiredArgsConstructor
static class Holder {
private final CompletableFuture<Void> future;
private final Object request;
}
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base; package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.library.elasticsearch.bulk.BulkProcessor; import org.apache.skywalking.library.elasticsearch.bulk.BulkProcessor;
import org.apache.skywalking.oap.server.core.storage.IBatchDAO; import org.apache.skywalking.oap.server.core.storage.IBatchDAO;
...@@ -56,19 +57,20 @@ public class BatchProcessEsDAO extends EsDAO implements IBatchDAO { ...@@ -56,19 +57,20 @@ public class BatchProcessEsDAO extends EsDAO implements IBatchDAO {
} }
@Override @Override
public void flush(List<PrepareRequest> prepareRequests) { public CompletableFuture<Void> flush(List<PrepareRequest> prepareRequests) {
if (bulkProcessor == null) { if (bulkProcessor == null) {
this.bulkProcessor = getClient().createBulkProcessor(bulkActions, flushInterval, concurrentRequests); this.bulkProcessor = getClient().createBulkProcessor(bulkActions, flushInterval, concurrentRequests);
} }
if (CollectionUtils.isNotEmpty(prepareRequests)) { if (CollectionUtils.isNotEmpty(prepareRequests)) {
for (PrepareRequest prepareRequest : prepareRequests) { return CompletableFuture.allOf(prepareRequests.stream().map(prepareRequest -> {
if (prepareRequest instanceof InsertRequest) { if (prepareRequest instanceof InsertRequest) {
this.bulkProcessor.add(((IndexRequestWrapper) prepareRequest).getRequest()); return bulkProcessor.add(((IndexRequestWrapper) prepareRequest).getRequest());
} else { } else {
this.bulkProcessor.add(((UpdateRequestWrapper) prepareRequest).getRequest()); return bulkProcessor.add(((UpdateRequestWrapper) prepareRequest).getRequest());
}
} }
}).toArray(CompletableFuture[]::new));
} }
return CompletableFuture.completedFuture(null);
} }
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.storage.plugin.influxdb.base; package org.apache.skywalking.oap.server.storage.plugin.influxdb.base;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.storage.IBatchDAO; import org.apache.skywalking.oap.server.core.storage.IBatchDAO;
import org.apache.skywalking.oap.server.library.client.request.InsertRequest; import org.apache.skywalking.oap.server.library.client.request.InsertRequest;
...@@ -41,9 +42,9 @@ public class BatchDAO implements IBatchDAO { ...@@ -41,9 +42,9 @@ public class BatchDAO implements IBatchDAO {
} }
@Override @Override
public void flush(List<PrepareRequest> prepareRequests) { public CompletableFuture<Void> flush(List<PrepareRequest> prepareRequests) {
if (CollectionUtils.isEmpty(prepareRequests)) { if (CollectionUtils.isEmpty(prepareRequests)) {
return; return CompletableFuture.completedFuture(null);
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
...@@ -51,10 +52,9 @@ public class BatchDAO implements IBatchDAO { ...@@ -51,10 +52,9 @@ public class BatchDAO implements IBatchDAO {
} }
final BatchPoints.Builder builder = BatchPoints.builder(); final BatchPoints.Builder builder = BatchPoints.builder();
prepareRequests.forEach(e -> { prepareRequests.forEach(e -> builder.point(((InfluxInsertRequest) e).getPoint()));
builder.point(((InfluxInsertRequest) e).getPoint());
});
client.write(builder.build()); client.write(builder.build());
return CompletableFuture.completedFuture(null);
} }
} }
...@@ -23,6 +23,7 @@ import java.sql.SQLException; ...@@ -23,6 +23,7 @@ import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -54,9 +55,9 @@ public class H2BatchDAO implements IBatchDAO { ...@@ -54,9 +55,9 @@ public class H2BatchDAO implements IBatchDAO {
} }
@Override @Override
public void flush(List<PrepareRequest> prepareRequests) { public CompletableFuture<Void> flush(List<PrepareRequest> prepareRequests) {
if (CollectionUtils.isEmpty(prepareRequests)) { if (CollectionUtils.isEmpty(prepareRequests)) {
return; return CompletableFuture.completedFuture(null);
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("to execute sql statements execute, data size: {}, maxBatchSqlSize: {}", prepareRequests.size(), maxBatchSqlSize); log.debug("to execute sql statements execute, data size: {}, maxBatchSqlSize: {}", prepareRequests.size(), maxBatchSqlSize);
...@@ -80,6 +81,7 @@ public class H2BatchDAO implements IBatchDAO { ...@@ -80,6 +81,7 @@ public class H2BatchDAO implements IBatchDAO {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("execute sql statements done, data size: {}, maxBatchSqlSize: {}", prepareRequests.size(), maxBatchSqlSize); log.debug("execute sql statements done, data size: {}, maxBatchSqlSize: {}", prepareRequests.size(), maxBatchSqlSize);
} }
return CompletableFuture.completedFuture(null);
} }
@Override @Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册