Merge pull request #12611 from dskarzh/copy-latest-to-view-fix

Do not copy latest to entity views when data was not saved on the main entity
This commit is contained in:
Viacheslav Klimov 2025-03-20 15:46:33 +02:00 committed by GitHub
commit ef0a0a2d50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 86 additions and 48 deletions

View File

@ -177,8 +177,8 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
if (strategy.sendWsUpdate()) {
addWsCallback(resultFuture, success -> onTimeSeriesUpdate(tenantId, entityId, request.getEntries()));
}
if (strategy.saveLatest()) {
copyLatestToEntityViews(tenantId, entityId, request.getEntries());
if (strategy.saveLatest() && entityId.getEntityType().isOneOf(EntityType.DEVICE, EntityType.ASSET)) {
addMainCallback(resultFuture, __ -> copyLatestToEntityViews(tenantId, entityId, request.getEntries()));
}
return resultFuture;
}
@ -333,8 +333,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
}
private void copyLatestToEntityViews(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts) {
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) {
Futures.addCallback(this.tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId),
Futures.addCallback(tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId),
new FutureCallback<>() {
@Override
public void onSuccess(@Nullable List<EntityView> result) {
@ -385,7 +384,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
}
}, MoreExecutors.directExecutor());
}
}
private void onAttributesUpdate(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes) {
forwardToSubscriptionManagerService(tenantId, entityId,

View File

@ -359,6 +359,45 @@ class DefaultTelemetrySubscriptionServiceTest {
then(subscriptionManagerService).shouldHaveNoInteractions();
}
@Test
void shouldNotCopyLatestToEntityViewWhenTimeseriesSaveFailedOnMainEntity() {
// GIVEN
var entityView = new EntityView(new EntityViewId(UUID.randomUUID()));
entityView.setTenantId(tenantId);
entityView.setCustomerId(customerId);
entityView.setEntityId(entityId);
entityView.setKeys(new TelemetryEntityView(sampleTimeseries.stream().map(KvEntry::getKey).toList(), new AttributesEntityView()));
// mock that there is one entity view
lenient().when(tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId)).thenReturn(immediateFuture(List.of(entityView)));
// mock that save latest call for entity view is successful
lenient().when(tsService.saveLatest(tenantId, entityView.getId(), sampleTimeseries)).thenReturn(immediateFuture(TimeseriesSaveResult.of(sampleTimeseries.size(), listOfNNumbers(sampleTimeseries.size()))));
// mock TPI for entity view
lenient().when(partitionService.resolve(ServiceType.TB_CORE, tenantId, entityView.getId())).thenReturn(tpi);
var request = TimeseriesSaveRequest.builder()
.tenantId(tenantId)
.customerId(customerId)
.entityId(entityId)
.entries(sampleTimeseries)
.ttl(sampleTtl)
.strategy(new TimeseriesSaveRequest.Strategy(true, true, false, false))
.build();
given(tsService.save(tenantId, entityId, sampleTimeseries, sampleTtl)).willReturn(immediateFailedFuture(new RuntimeException("failed to save data on main entity")));
// WHEN
telemetryService.saveTimeseries(request);
// THEN
// should save only time series for the main entity
then(tsService).should().save(tenantId, entityId, sampleTimeseries, sampleTtl);
then(tsService).shouldHaveNoMoreInteractions();
// should not send any WS updates
then(subscriptionManagerService).shouldHaveNoInteractions();
}
@ParameterizedTest
@MethodSource("allCombinationsOfFourBooleans")
void shouldCallCorrectSaveTimeseriesApiBasedOnBooleanFlagsInTheSaveRequest(boolean saveTimeseries, boolean saveLatest, boolean sendWsUpdate, boolean processCalculatedFields) {

View File

@ -97,4 +97,5 @@ public enum EntityType {
}
return false;
}
}