use of org.thingsboard.server.common.data.kv.BaseReadTsKvQuery in project thingsboard by thingsboard.
the class BaseTimeseriesServiceTest method testDeleteDeviceTsDataWithOverwritingLatest.
@Test
public void testDeleteDeviceTsDataWithOverwritingLatest() throws Exception {
DeviceId deviceId = new DeviceId(Uuids.timeBased());
saveEntries(deviceId, 10000);
saveEntries(deviceId, 20000);
saveEntries(deviceId, 30000);
saveEntries(deviceId, 40000);
tsService.remove(tenantId, deviceId, Collections.singletonList(new BaseDeleteTsKvQuery(STRING_KEY, 25000, 45000, true))).get(MAX_TIMEOUT, TimeUnit.SECONDS);
List<TsKvEntry> list = tsService.findAll(tenantId, deviceId, Collections.singletonList(new BaseReadTsKvQuery(STRING_KEY, 5000, 45000, 10000, 10, Aggregation.NONE))).get(MAX_TIMEOUT, TimeUnit.SECONDS);
Assert.assertEquals(2, list.size());
List<TsKvEntry> latest = tsService.findLatest(tenantId, deviceId, Collections.singletonList(STRING_KEY)).get(MAX_TIMEOUT, TimeUnit.SECONDS);
Assert.assertEquals(20000, latest.get(0).getTs());
}
use of org.thingsboard.server.common.data.kv.BaseReadTsKvQuery in project thingsboard by thingsboard.
the class DefaultSubscriptionManagerService method handleNewTelemetrySubscription.
private void handleNewTelemetrySubscription(TbTimeseriesSubscription subscription) {
log.trace("[{}][{}][{}] Processing remote telemetry subscription for entity [{}]", serviceId, subscription.getSessionId(), subscription.getSubscriptionId(), subscription.getEntityId());
long curTs = System.currentTimeMillis();
if (subscription.isLatestValues()) {
DonAsynchron.withCallback(tsService.findLatest(subscription.getTenantId(), subscription.getEntityId(), subscription.getKeyStates().keySet()), missedUpdates -> {
if (missedUpdates != null && !missedUpdates.isEmpty()) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, subscription.getServiceId());
toCoreNotificationsProducer.send(tpi, toProto(subscription, missedUpdates), null);
}
}, e -> log.error("Failed to fetch missed updates.", e), tsCallBackExecutor);
} else {
List<ReadTsKvQuery> queries = new ArrayList<>();
subscription.getKeyStates().forEach((key, value) -> {
if (curTs > value) {
long startTs = subscription.getStartTime() > 0 ? Math.max(subscription.getStartTime(), value + 1L) : (value + 1L);
long endTs = subscription.getEndTime() > 0 ? Math.min(subscription.getEndTime(), curTs) : curTs;
queries.add(new BaseReadTsKvQuery(key, startTs, endTs, 0, 1000, Aggregation.NONE));
}
});
if (!queries.isEmpty()) {
DonAsynchron.withCallback(tsService.findAll(subscription.getTenantId(), subscription.getEntityId(), queries), missedUpdates -> {
if (missedUpdates != null && !missedUpdates.isEmpty()) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, subscription.getServiceId());
toCoreNotificationsProducer.send(tpi, toProto(subscription, missedUpdates), null);
}
}, e -> log.error("Failed to fetch missed updates.", e), tsCallBackExecutor);
}
}
}
use of org.thingsboard.server.common.data.kv.BaseReadTsKvQuery in project thingsboard by thingsboard.
the class EntityViewController method copyLatestFromEntityToEntityView.
private ListenableFuture<List<Void>> copyLatestFromEntityToEntityView(EntityView entityView, SecurityUser user) {
EntityViewId entityId = entityView.getId();
List<String> keys = entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null ? entityView.getKeys().getTimeseries() : Collections.emptyList();
long startTs = entityView.getStartTimeMs();
long endTs = entityView.getEndTimeMs() == 0 ? Long.MAX_VALUE : entityView.getEndTimeMs();
ListenableFuture<List<String>> keysFuture;
if (keys.isEmpty()) {
keysFuture = Futures.transform(tsService.findAllLatest(user.getTenantId(), entityView.getEntityId()), latest -> latest.stream().map(TsKvEntry::getKey).collect(Collectors.toList()), MoreExecutors.directExecutor());
} else {
keysFuture = Futures.immediateFuture(keys);
}
ListenableFuture<List<TsKvEntry>> latestFuture = Futures.transformAsync(keysFuture, fetchKeys -> {
List<ReadTsKvQuery> queries = fetchKeys.stream().filter(key -> !isBlank(key)).map(key -> new BaseReadTsKvQuery(key, startTs, endTs, 1, "DESC")).collect(Collectors.toList());
if (!queries.isEmpty()) {
return tsService.findAll(user.getTenantId(), entityView.getEntityId(), queries);
} else {
return Futures.immediateFuture(null);
}
}, MoreExecutors.directExecutor());
return Futures.transform(latestFuture, latestValues -> {
if (latestValues != null && !latestValues.isEmpty()) {
tsSubService.saveLatestAndNotify(entityView.getTenantId(), entityId, latestValues, new FutureCallback<Void>() {
@Override
public void onSuccess(@Nullable Void tmp) {
}
@Override
public void onFailure(Throwable t) {
}
});
}
return null;
}, MoreExecutors.directExecutor());
}
use of org.thingsboard.server.common.data.kv.BaseReadTsKvQuery in project thingsboard by thingsboard.
the class DefaultTelemetryWebSocketService method handleWsHistoryCmd.
private void handleWsHistoryCmd(TelemetryWebSocketSessionRef sessionRef, GetHistoryCmd cmd) {
String sessionId = sessionRef.getSessionId();
WsSessionMetaData sessionMD = wsSessionsMap.get(sessionId);
if (sessionMD == null) {
log.warn("[{}] Session meta data not found. ", sessionId);
TelemetrySubscriptionUpdate update = new TelemetrySubscriptionUpdate(cmd.getCmdId(), SubscriptionErrorCode.INTERNAL_ERROR, SESSION_META_DATA_NOT_FOUND);
sendWsMsg(sessionRef, update);
return;
}
if (cmd.getEntityId() == null || cmd.getEntityId().isEmpty() || cmd.getEntityType() == null || cmd.getEntityType().isEmpty()) {
TelemetrySubscriptionUpdate update = new TelemetrySubscriptionUpdate(cmd.getCmdId(), SubscriptionErrorCode.BAD_REQUEST, "Device id is empty!");
sendWsMsg(sessionRef, update);
return;
}
if (cmd.getKeys() == null || cmd.getKeys().isEmpty()) {
TelemetrySubscriptionUpdate update = new TelemetrySubscriptionUpdate(cmd.getCmdId(), SubscriptionErrorCode.BAD_REQUEST, "Keys are empty!");
sendWsMsg(sessionRef, update);
return;
}
EntityId entityId = EntityIdFactory.getByTypeAndId(cmd.getEntityType(), cmd.getEntityId());
List<String> keys = new ArrayList<>(getKeys(cmd).orElse(Collections.emptySet()));
List<ReadTsKvQuery> queries = keys.stream().map(key -> new BaseReadTsKvQuery(key, cmd.getStartTs(), cmd.getEndTs(), cmd.getInterval(), getLimit(cmd.getLimit()), getAggregation(cmd.getAgg()))).collect(Collectors.toList());
FutureCallback<List<TsKvEntry>> callback = new FutureCallback<List<TsKvEntry>>() {
@Override
public void onSuccess(List<TsKvEntry> data) {
sendWsMsg(sessionRef, new TelemetrySubscriptionUpdate(cmd.getCmdId(), data));
}
@Override
public void onFailure(Throwable e) {
TelemetrySubscriptionUpdate update;
if (UnauthorizedException.class.isInstance(e)) {
update = new TelemetrySubscriptionUpdate(cmd.getCmdId(), SubscriptionErrorCode.UNAUTHORIZED, SubscriptionErrorCode.UNAUTHORIZED.getDefaultMsg());
} else {
update = new TelemetrySubscriptionUpdate(cmd.getCmdId(), SubscriptionErrorCode.INTERNAL_ERROR, FAILED_TO_FETCH_DATA);
}
sendWsMsg(sessionRef, update);
}
};
accessValidator.validate(sessionRef.getSecurityCtx(), Operation.READ_TELEMETRY, entityId, on(r -> Futures.addCallback(tsService.findAll(sessionRef.getSecurityCtx().getTenantId(), entityId, queries), callback, executor), callback::onFailure));
}
use of org.thingsboard.server.common.data.kv.BaseReadTsKvQuery in project thingsboard by thingsboard.
the class DefaultTbEntityDataSubscriptionService method handleGetTsCmd.
private ListenableFuture<TbEntityDataSubCtx> handleGetTsCmd(TbEntityDataSubCtx ctx, GetTsCmd cmd, boolean subscribe) {
List<String> keys = cmd.getKeys();
List<ReadTsKvQuery> finalTsKvQueryList;
List<ReadTsKvQuery> tsKvQueryList = cmd.getKeys().stream().map(key -> new BaseReadTsKvQuery(key, cmd.getStartTs(), cmd.getEndTs(), cmd.getInterval(), getLimit(cmd.getLimit()), cmd.getAgg())).collect(Collectors.toList());
if (cmd.isFetchLatestPreviousPoint()) {
finalTsKvQueryList = new ArrayList<>(tsKvQueryList);
finalTsKvQueryList.addAll(cmd.getKeys().stream().map(key -> new BaseReadTsKvQuery(key, cmd.getStartTs() - TimeUnit.DAYS.toMillis(365), cmd.getStartTs(), cmd.getInterval(), 1, cmd.getAgg())).collect(Collectors.toList()));
} else {
finalTsKvQueryList = tsKvQueryList;
}
Map<EntityData, ListenableFuture<List<TsKvEntry>>> fetchResultMap = new HashMap<>();
ctx.getData().getData().forEach(entityData -> fetchResultMap.put(entityData, tsService.findAll(ctx.getTenantId(), entityData.getEntityId(), finalTsKvQueryList)));
return Futures.transform(Futures.allAsList(fetchResultMap.values()), f -> {
fetchResultMap.forEach((entityData, future) -> {
Map<String, List<TsValue>> keyData = new LinkedHashMap<>();
cmd.getKeys().forEach(key -> keyData.put(key, new ArrayList<>()));
try {
List<TsKvEntry> entityTsData = future.get();
if (entityTsData != null) {
entityTsData.forEach(entry -> keyData.get(entry.getKey()).add(new TsValue(entry.getTs(), entry.getValueAsString())));
}
keyData.forEach((k, v) -> entityData.getTimeseries().put(k, v.toArray(new TsValue[v.size()])));
if (cmd.isFetchLatestPreviousPoint()) {
entityData.getTimeseries().values().forEach(dataArray -> {
Arrays.sort(dataArray, (o1, o2) -> Long.compare(o2.getTs(), o1.getTs()));
});
}
} catch (InterruptedException | ExecutionException e) {
log.warn("[{}][{}][{}] Failed to fetch historical data", ctx.getSessionId(), ctx.getCmdId(), entityData.getEntityId(), e);
wsService.sendWsMsg(ctx.getSessionId(), new EntityDataUpdate(ctx.getCmdId(), SubscriptionErrorCode.INTERNAL_ERROR.getCode(), "Failed to fetch historical data!"));
}
});
EntityDataUpdate update;
if (!ctx.isInitialDataSent()) {
update = new EntityDataUpdate(ctx.getCmdId(), ctx.getData(), null, ctx.getMaxEntitiesPerDataSubscription());
ctx.setInitialDataSent(true);
} else {
update = new EntityDataUpdate(ctx.getCmdId(), null, ctx.getData().getData(), ctx.getMaxEntitiesPerDataSubscription());
}
wsService.sendWsMsg(ctx.getSessionId(), update);
if (subscribe) {
ctx.createTimeseriesSubscriptions(keys.stream().map(key -> new EntityKey(EntityKeyType.TIME_SERIES, key)).collect(Collectors.toList()), cmd.getStartTs(), cmd.getEndTs());
}
ctx.getData().getData().forEach(ed -> ed.getTimeseries().clear());
return ctx;
}, wsCallBackExecutor);
}
Aggregations