Commit e6e9be18ea62f697ea0e5bf780ed78cb247786ac

Authored by Igor Kulikov
1 parent b8608bed

Entity data query fixes

@@ -401,9 +401,14 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc @@ -401,9 +401,14 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc
401 new EntityDataUpdate(ctx.getCmdId(), SubscriptionErrorCode.INTERNAL_ERROR.getCode(), "Failed to fetch historical data!")); 401 new EntityDataUpdate(ctx.getCmdId(), SubscriptionErrorCode.INTERNAL_ERROR.getCode(), "Failed to fetch historical data!"));
402 } 402 }
403 }); 403 });
404 - EntityDataUpdate update = new EntityDataUpdate(ctx.getCmdId(), ctx.getData(), null); 404 + EntityDataUpdate update;
  405 + if (!ctx.isInitialDataSent()) {
  406 + update = new EntityDataUpdate(ctx.getCmdId(), ctx.getData(), null);
  407 + ctx.setInitialDataSent(true);
  408 + } else {
  409 + update = new EntityDataUpdate(ctx.getCmdId(), null, ctx.getData().getData());
  410 + }
405 wsService.sendWsMsg(ctx.getSessionId(), update); 411 wsService.sendWsMsg(ctx.getSessionId(), update);
406 - ctx.setInitialDataSent(true);  
407 return ctx; 412 return ctx;
408 }, wsCallBackExecutor); 413 }, wsCallBackExecutor);
409 } 414 }
@@ -191,12 +191,14 @@ public class TbEntityDataSubCtx { @@ -191,12 +191,14 @@ public class TbEntityDataSubCtx {
191 if (latestCtxValues != null) { 191 if (latestCtxValues != null) {
192 latestCtxValues.forEach((k, v) -> { 192 latestCtxValues.forEach((k, v) -> {
193 TsValue update = latestUpdate.get(k); 193 TsValue update = latestUpdate.get(k);
194 - if (update.getTs() < v.getTs()) {  
195 - log.trace("[{}][{}][{}] Removed stale update for key: {} and ts: {}", sessionId, cmdId, subscriptionUpdate.getSubscriptionId(), k, update.getTs());  
196 - latestUpdate.remove(k);  
197 - } else if ((update.getTs() == v.getTs() && update.getValue().equals(v.getValue()))) {  
198 - log.trace("[{}][{}][{}] Removed duplicate update for key: {} and ts: {}", sessionId, cmdId, subscriptionUpdate.getSubscriptionId(), k, update.getTs());  
199 - latestUpdate.remove(k); 194 + if (update != null) {
  195 + if (update.getTs() < v.getTs()) {
  196 + log.trace("[{}][{}][{}] Removed stale update for key: {} and ts: {}", sessionId, cmdId, subscriptionUpdate.getSubscriptionId(), k, update.getTs());
  197 + latestUpdate.remove(k);
  198 + } else if ((update.getTs() == v.getTs() && update.getValue().equals(v.getValue()))) {
  199 + log.trace("[{}][{}][{}] Removed duplicate update for key: {} and ts: {}", sessionId, cmdId, subscriptionUpdate.getSubscriptionId(), k, update.getTs());
  200 + latestUpdate.remove(k);
  201 + }
200 } 202 }
201 }); 203 });
202 //Setting new values 204 //Setting new values
@@ -204,8 +206,16 @@ public class TbEntityDataSubCtx { @@ -204,8 +206,16 @@ public class TbEntityDataSubCtx {
204 } 206 }
205 } 207 }
206 if (!latestUpdate.isEmpty()) { 208 if (!latestUpdate.isEmpty()) {
207 - Map<EntityKeyType, Map<String, TsValue>> latestMap = Collections.singletonMap(keyType, latestUpdate);  
208 - entityData = new EntityData(entityId, latestMap, null); 209 + if (resultToLatestValues) {
  210 + Map<EntityKeyType, Map<String, TsValue>> latestMap = Collections.singletonMap(keyType, latestUpdate);
  211 + entityData = new EntityData(entityId, latestMap, null);
  212 + } else {
  213 + Map<String, TsValue[]> tsMap = new HashMap<>();
  214 + latestUpdate.forEach((key, tsValue) -> {
  215 + tsMap.put(key, new TsValue[]{tsValue});
  216 + });
  217 + entityData = new EntityData(entityId, null, tsMap);
  218 + }
209 wsService.sendWsMsg(sessionId, new EntityDataUpdate(cmdId, null, Collections.singletonList(entityData))); 219 wsService.sendWsMsg(sessionId, new EntityDataUpdate(cmdId, null, Collections.singletonList(entityData)));
210 } 220 }
211 } else { 221 } else {
@@ -206,25 +206,31 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { @@ -206,25 +206,31 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
206 case RELATIONS_QUERY: 206 case RELATIONS_QUERY:
207 case DEVICE_SEARCH_QUERY: 207 case DEVICE_SEARCH_QUERY:
208 case ASSET_SEARCH_QUERY: 208 case ASSET_SEARCH_QUERY:
209 - ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());  
210 - ctx.addUuidParameter("permissions_customer_id", customerId.getId());  
211 - return "e.tenant_id=:permissions_tenant_id and e.customer_id=:permissions_customer_id"; 209 + return this.defaultPermissionQuery(ctx, tenantId, customerId, entityType);
212 default: 210 default:
213 if (entityType == EntityType.TENANT) { 211 if (entityType == EntityType.TENANT) {
214 ctx.addUuidParameter("permissions_tenant_id", tenantId.getId()); 212 ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());
215 return "e.id=:permissions_tenant_id"; 213 return "e.id=:permissions_tenant_id";
216 - } else if (entityType == EntityType.CUSTOMER) {  
217 - ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());  
218 - ctx.addUuidParameter("permissions_customer_id", customerId.getId());  
219 - return "e.tenant_id=:permissions_tenant_id and e.id=:permissions_customer_id";  
220 } else { 214 } else {
221 - ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());  
222 - ctx.addUuidParameter("permissions_customer_id", customerId.getId());  
223 - return "e.tenant_id=:permissions_tenant_id and e.customer_id=:permissions_customer_id"; 215 + return this.defaultPermissionQuery(ctx, tenantId, customerId, entityType);
224 } 216 }
225 } 217 }
226 } 218 }
227 219
  220 + private String defaultPermissionQuery(EntityQueryContext ctx, TenantId tenantId, CustomerId customerId, EntityType entityType) {
  221 + ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());
  222 + if (customerId != null && !customerId.isNullUid()) {
  223 + ctx.addUuidParameter("permissions_customer_id", customerId.getId());
  224 + if (entityType == EntityType.CUSTOMER) {
  225 + return "e.tenant_id=:permissions_tenant_id and e.id=:permissions_customer_id";
  226 + } else {
  227 + return "e.tenant_id=:permissions_tenant_id and e.customer_id=:permissions_customer_id";
  228 + }
  229 + } else {
  230 + return "e.tenant_id=:permissions_tenant_id";
  231 + }
  232 + }
  233 +
228 private String buildEntityFilterQuery(EntityQueryContext ctx, EntityFilter entityFilter) { 234 private String buildEntityFilterQuery(EntityQueryContext ctx, EntityFilter entityFilter) {
229 switch (entityFilter.getType()) { 235 switch (entityFilter.getType()) {
230 case SINGLE_ENTITY: 236 case SINGLE_ENTITY:
@@ -222,21 +222,26 @@ export class EntityDataSubscription { @@ -222,21 +222,26 @@ export class EntityDataSubscription {
222 ); 222 );
223 223
224 this.subscriber.reconnect$.subscribe(() => { 224 this.subscriber.reconnect$.subscribe(() => {
225 - const newSubsTw: SubscriptionTimewindow = this.listener.updateRealtimeSubscription();  
226 - this.listener.setRealtimeSubscription(newSubsTw);  
227 - this.subsTw = newSubsTw;  
228 if (this.started && !this.entityDataSubscriptionOptions.isLatestDataSubscription) { 225 if (this.started && !this.entityDataSubscriptionOptions.isLatestDataSubscription) {
229 - this.subsCommand.tsCmd.startTs = this.subsTw.startTs;  
230 - this.subsCommand.tsCmd.timeWindow = this.subsTw.aggregation.timeWindow;  
231 - this.subsCommand.tsCmd.interval = this.subsTw.aggregation.interval;  
232 - this.subsCommand.tsCmd.limit = this.subsTw.aggregation.limit;  
233 - this.subsCommand.tsCmd.agg = this.subsTw.aggregation.type;  
234 - if (this.subsTw.aggregation.stateData) {  
235 - this.subsCommand.historyCmd.startTs = this.subsTw.startTs - YEAR;  
236 - this.subsCommand.historyCmd.endTs = this.subsTw.startTs;  
237 - this.subsCommand.historyCmd.interval = this.subsTw.aggregation.interval;  
238 - this.subsCommand.historyCmd.limit = this.subsTw.aggregation.limit;  
239 - this.subsCommand.historyCmd.agg = this.subsTw.aggregation.type; 226 + if (this.entityDataSubscriptionOptions.type === widgetType.timeseries &&
  227 + !this.history && this.tsFields.length) {
  228 + const newSubsTw: SubscriptionTimewindow = this.listener.updateRealtimeSubscription();
  229 + this.subsTw = newSubsTw;
  230 + this.subsCommand.tsCmd.startTs = this.subsTw.startTs;
  231 + this.subsCommand.tsCmd.timeWindow = this.subsTw.aggregation.timeWindow;
  232 + this.subsCommand.tsCmd.interval = this.subsTw.aggregation.interval;
  233 + this.subsCommand.tsCmd.limit = this.subsTw.aggregation.limit;
  234 + this.subsCommand.tsCmd.agg = this.subsTw.aggregation.type;
  235 + if (this.subsTw.aggregation.stateData) {
  236 + this.subsCommand.historyCmd.startTs = this.subsTw.startTs - YEAR;
  237 + this.subsCommand.historyCmd.endTs = this.subsTw.startTs;
  238 + this.subsCommand.historyCmd.interval = this.subsTw.aggregation.interval;
  239 + this.subsCommand.historyCmd.limit = this.subsTw.aggregation.limit;
  240 + this.subsCommand.historyCmd.agg = this.subsTw.aggregation.type;
  241 + }
  242 + this.dataAggregators.forEach((dataAggregator) => {
  243 + dataAggregator.reset(newSubsTw.startTs, newSubsTw.aggregation.timeWindow, newSubsTw.aggregation.interval);
  244 + });
240 } 245 }
241 this.subsCommand.query = this.dataCommand.query; 246 this.subsCommand.query = this.dataCommand.query;
242 this.subscriber.subscriptionCommands = [this.subsCommand]; 247 this.subscriber.subscriptionCommands = [this.subsCommand];
@@ -370,8 +375,10 @@ export class EntityDataSubscription { @@ -370,8 +375,10 @@ export class EntityDataSubscription {
370 }; 375 };
371 } 376 }
372 } 377 }
373 - this.subscriber.subscriptionCommands = [this.subsCommand];  
374 - this.subscriber.update(); 378 + if (!this.subsCommand.isEmpty()) {
  379 + this.subscriber.subscriptionCommands = [this.subsCommand];
  380 + this.subscriber.update();
  381 + }
375 } else if (this.datasourceType === DatasourceType.function) { 382 } else if (this.datasourceType === DatasourceType.function) {
376 this.frequency = 1000; 383 this.frequency = 1000;
377 if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { 384 if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) {
@@ -480,7 +487,7 @@ export class EntityDataSubscription { @@ -480,7 +487,7 @@ export class EntityDataSubscription {
480 } 487 }
481 if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && entityData.timeseries) { 488 if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && entityData.timeseries) {
482 const subscriptionData = this.toSubscriptionData(entityData.timeseries, true); 489 const subscriptionData = this.toSubscriptionData(entityData.timeseries, true);
483 - if (aggregate) { 490 + if (!this.history && aggregate) {
484 this.dataAggregators[dataIndex].onData({data: subscriptionData}, false, false, true); 491 this.dataAggregators[dataIndex].onData({data: subscriptionData}, false, false, true);
485 } else { 492 } else {
486 this.onData(subscriptionData, DataKeyType.timeseries, dataIndex, true, dataUpdatedCb); 493 this.onData(subscriptionData, DataKeyType.timeseries, dataIndex, true, dataUpdatedCb);
@@ -157,6 +157,10 @@ export class EntityDataCmd implements WebsocketCmd { @@ -157,6 +157,10 @@ export class EntityDataCmd implements WebsocketCmd {
157 historyCmd?: EntityHistoryCmd; 157 historyCmd?: EntityHistoryCmd;
158 latestCmd?: LatestValueCmd; 158 latestCmd?: LatestValueCmd;
159 tsCmd?: TimeSeriesCmd; 159 tsCmd?: TimeSeriesCmd;
  160 +
  161 + public isEmpty(): boolean {
  162 + return !this.query && !this.historyCmd && !this.latestCmd && !this.tsCmd;
  163 + }
160 } 164 }
161 165
162 export class EntityDataUnsubscribeCmd implements WebsocketCmd { 166 export class EntityDataUnsubscribeCmd implements WebsocketCmd {