Fixed JPA Async methods

This commit is contained in:
Andrew Shvayka 2017-07-18 18:42:20 +03:00
parent 4525174b0e
commit e0f753025d
3 changed files with 63 additions and 24 deletions

View File

@ -18,11 +18,13 @@ package org.thingsboard.server;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import springfox.documentation.swagger2.annotations.EnableSwagger2; import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Arrays; import java.util.Arrays;
@SpringBootConfiguration @SpringBootConfiguration
@EnableAsync
@EnableSwagger2 @EnableSwagger2
@ComponentScan({"org.thingsboard.server"}) @ComponentScan({"org.thingsboard.server"})
public class ThingsboardServerApplication { public class ThingsboardServerApplication {

View File

@ -19,6 +19,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
@ -39,6 +40,8 @@ import org.thingsboard.server.dao.util.SqlDao;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
@ -80,7 +83,7 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
return findAllAsyncWithLimit(entityId, query); return findAllAsyncWithLimit(entityId, query);
} else { } else {
long stepTs = query.getStartTs(); long stepTs = query.getStartTs();
List<ListenableFuture<TsKvEntry>> futures = new ArrayList<>(); List<ListenableFuture<Optional<TsKvEntry>>> futures = new ArrayList<>();
while (stepTs < query.getEndTs()) { while (stepTs < query.getEndTs()) {
long startTs = stepTs; long startTs = stepTs;
long endTs = stepTs + query.getInterval(); long endTs = stepTs + query.getInterval();
@ -88,16 +91,30 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
futures.add(findAndAggregateAsync(entityId, query.getKey(), startTs, endTs, ts, query.getAggregation())); futures.add(findAndAggregateAsync(entityId, query.getKey(), startTs, endTs, ts, query.getAggregation()));
stepTs = endTs; stepTs = endTs;
} }
return Futures.allAsList(futures); ListenableFuture<List<Optional<TsKvEntry>>> future = Futures.allAsList(futures);
return Futures.transform(future, new Function<List<Optional<TsKvEntry>>, List<TsKvEntry>>() {
@Nullable
@Override
public List<TsKvEntry> apply(@Nullable List<Optional<TsKvEntry>> results) {
if (results == null || results.isEmpty()) {
return null;
}
return results.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
}, service);
} }
} }
private ListenableFuture<TsKvEntry> findAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) { private ListenableFuture<Optional<TsKvEntry>> findAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) {
TsKvEntity entity; CompletableFuture<TsKvEntity> entity;
String entityIdStr = fromTimeUUID(entityId.getId());
switch (aggregation) { switch (aggregation) {
case AVG: case AVG:
entity = tsKvRepository.findAvg( entity = tsKvRepository.findAvg(
fromTimeUUID(entityId.getId()), entityIdStr,
entityId.getEntityType(), entityId.getEntityType(),
key, key,
startTs, startTs,
@ -106,7 +123,7 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
break; break;
case MAX: case MAX:
entity = tsKvRepository.findMax( entity = tsKvRepository.findMax(
fromTimeUUID(entityId.getId()), entityIdStr,
entityId.getEntityType(), entityId.getEntityType(),
key, key,
startTs, startTs,
@ -115,7 +132,7 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
break; break;
case MIN: case MIN:
entity = tsKvRepository.findMin( entity = tsKvRepository.findMin(
fromTimeUUID(entityId.getId()), entityIdStr,
entityId.getEntityType(), entityId.getEntityType(),
key, key,
startTs, startTs,
@ -124,7 +141,7 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
break; break;
case SUM: case SUM:
entity = tsKvRepository.findSum( entity = tsKvRepository.findSum(
fromTimeUUID(entityId.getId()), entityIdStr,
entityId.getEntityType(), entityId.getEntityType(),
key, key,
startTs, startTs,
@ -133,7 +150,7 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
break; break;
case COUNT: case COUNT:
entity = tsKvRepository.findCount( entity = tsKvRepository.findCount(
fromTimeUUID(entityId.getId()), entityIdStr,
entityId.getEntityType(), entityId.getEntityType(),
key, key,
startTs, startTs,
@ -141,12 +158,32 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
break; break;
default: default:
entity = null; throw new IllegalArgumentException("Not supported aggregation type: " + aggregation);
} }
if (entity != null) {
SettableFuture<TsKvEntity> listenableFuture = SettableFuture.create();
entity.whenComplete((tsKvEntity, throwable) -> {
if (throwable != null) {
listenableFuture.setException(throwable);
} else {
listenableFuture.set(tsKvEntity);
}
});
return Futures.transform(listenableFuture, new Function<TsKvEntity, Optional<TsKvEntry>>() {
@Nullable
@Override
public Optional<TsKvEntry> apply(@Nullable TsKvEntity entity) {
if (entity != null && entity.isNotEmpty()) {
entity.setEntityId(entityIdStr);
entity.setEntityType(entityId.getEntityType());
entity.setKey(key);
entity.setTs(ts); entity.setTs(ts);
return Optional.of(DaoUtil.getData(entity));
} else {
return Optional.empty();
} }
return service.submit(() -> DaoUtil.getData(entity)); }
});
} }
private ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(EntityId entityId, TsKvQuery query) { private ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(EntityId entityId, TsKvQuery query) {

View File

@ -26,7 +26,7 @@ import org.thingsboard.server.dao.model.sql.TsKvEntity;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.List; import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.CompletableFuture;
@SqlDao @SqlDao
public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvCompositeKey> { public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvCompositeKey> {
@ -45,7 +45,7 @@ public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvComposite
@Query("SELECT new TsKvEntity(MAX(tskv.strValue), MAX(tskv.longValue), MAX(tskv.doubleValue)) FROM TsKvEntity tskv " + @Query("SELECT new TsKvEntity(MAX(tskv.strValue), MAX(tskv.longValue), MAX(tskv.doubleValue)) FROM TsKvEntity tskv " +
"WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " + "WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " +
"AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs") "AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs")
Future<TsKvEntity> findMax(@Param("entityId") String entityId, CompletableFuture<TsKvEntity> findMax(@Param("entityId") String entityId,
@Param("entityType") EntityType entityType, @Param("entityType") EntityType entityType,
@Param("entityKey") String entityKey, @Param("entityKey") String entityKey,
@Param("startTs") long startTs, @Param("startTs") long startTs,
@ -55,7 +55,7 @@ public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvComposite
@Query("SELECT new TsKvEntity(MIN(tskv.strValue), MIN(tskv.longValue), MIN(tskv.doubleValue)) FROM TsKvEntity tskv " + @Query("SELECT new TsKvEntity(MIN(tskv.strValue), MIN(tskv.longValue), MIN(tskv.doubleValue)) FROM TsKvEntity tskv " +
"WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " + "WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " +
"AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs") "AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs")
Future<TsKvEntity> findMin(@Param("entityId") String entityId, CompletableFuture<TsKvEntity> findMin(@Param("entityId") String entityId,
@Param("entityType") EntityType entityType, @Param("entityType") EntityType entityType,
@Param("entityKey") String entityKey, @Param("entityKey") String entityKey,
@Param("startTs") long startTs, @Param("startTs") long startTs,
@ -65,7 +65,7 @@ public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvComposite
@Query("SELECT new TsKvEntity(COUNT(tskv.booleanValue), COUNT(tskv.strValue), COUNT(tskv.longValue), COUNT(tskv.doubleValue)) FROM TsKvEntity tskv " + @Query("SELECT new TsKvEntity(COUNT(tskv.booleanValue), COUNT(tskv.strValue), COUNT(tskv.longValue), COUNT(tskv.doubleValue)) FROM TsKvEntity tskv " +
"WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " + "WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " +
"AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs") "AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs")
Future<TsKvEntity> findCount(@Param("entityId") String entityId, CompletableFuture<TsKvEntity> findCount(@Param("entityId") String entityId,
@Param("entityType") EntityType entityType, @Param("entityType") EntityType entityType,
@Param("entityKey") String entityKey, @Param("entityKey") String entityKey,
@Param("startTs") long startTs, @Param("startTs") long startTs,
@ -75,7 +75,7 @@ public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvComposite
@Query("SELECT new TsKvEntity(AVG(tskv.longValue), AVG(tskv.doubleValue)) FROM TsKvEntity tskv " + @Query("SELECT new TsKvEntity(AVG(tskv.longValue), AVG(tskv.doubleValue)) FROM TsKvEntity tskv " +
"WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " + "WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " +
"AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs") "AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs")
Future<TsKvEntity> findAvg(@Param("entityId") String entityId, CompletableFuture<TsKvEntity> findAvg(@Param("entityId") String entityId,
@Param("entityType") EntityType entityType, @Param("entityType") EntityType entityType,
@Param("entityKey") String entityKey, @Param("entityKey") String entityKey,
@Param("startTs") long startTs, @Param("startTs") long startTs,
@ -86,7 +86,7 @@ public interface TsKvRepository extends CrudRepository<TsKvEntity, TsKvComposite
@Query("SELECT new TsKvEntity(SUM(tskv.longValue), SUM(tskv.doubleValue)) FROM TsKvEntity tskv " + @Query("SELECT new TsKvEntity(SUM(tskv.longValue), SUM(tskv.doubleValue)) FROM TsKvEntity tskv " +
"WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " + "WHERE tskv.entityId = :entityId AND tskv.entityType = :entityType " +
"AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs") "AND tskv.key = :entityKey AND tskv.ts > :startTs AND tskv.ts < :endTs")
Future<TsKvEntity> findSum(@Param("entityId") String entityId, CompletableFuture<TsKvEntity> findSum(@Param("entityId") String entityId,
@Param("entityType") EntityType entityType, @Param("entityType") EntityType entityType,
@Param("entityKey") String entityKey, @Param("entityKey") String entityKey,
@Param("startTs") long startTs, @Param("startTs") long startTs,