Improvements to Storage Days calculation
This commit is contained in:
parent
8385d18c3a
commit
a87956ebfd
@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.Customer;
|
|||||||
import org.thingsboard.server.common.data.DataConstants;
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||||
import org.thingsboard.server.common.data.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
@ -510,14 +511,25 @@ class DefaultTbContext implements TbContext {
|
|||||||
mainCtx.getRuleNodeStateService().removeByRuleNodeIdAndEntityId(getTenantId(), getSelfId(), entityId);
|
mainCtx.getRuleNodeStateService().removeByRuleNodeIdAndEntityId(getTenantId(), getSelfId(), entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTenantProfileListener(Consumer<TenantProfile> listener) {
|
||||||
|
mainCtx.getTenantProfileCache().addListener(getTenantId(), getSelfId(), listener);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDeviceProfileListeners(Consumer<DeviceProfile> profileListener, BiConsumer<DeviceId, DeviceProfile> deviceListener) {
|
public void addDeviceProfileListeners(Consumer<DeviceProfile> profileListener, BiConsumer<DeviceId, DeviceProfile> deviceListener) {
|
||||||
mainCtx.getDeviceProfileCache().addListener(getTenantId(), getSelfId(), profileListener, deviceListener);
|
mainCtx.getDeviceProfileCache().addListener(getTenantId(), getSelfId(), profileListener, deviceListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeProfileListener() {
|
public void removeListeners() {
|
||||||
mainCtx.getDeviceProfileCache().removeListener(getTenantId(), getSelfId());
|
mainCtx.getDeviceProfileCache().removeListener(getTenantId(), getSelfId());
|
||||||
|
mainCtx.getTenantProfileCache().removeListener(getTenantId(), getSelfId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TenantProfile getTenantProfile() {
|
||||||
|
return mainCtx.getTenantProfileCache().get(getTenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TbMsgMetaData getActionMetaData(RuleNodeId ruleNodeId) {
|
private TbMsgMetaData getActionMetaData(RuleNodeId ruleNodeId) {
|
||||||
|
|||||||
@ -45,6 +45,7 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory;
|
|||||||
import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
|
import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
|
||||||
import org.thingsboard.server.common.data.DataConstants;
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
import org.thingsboard.server.common.data.audit.ActionType;
|
import org.thingsboard.server.common.data.audit.ActionType;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
@ -69,6 +70,7 @@ import org.thingsboard.server.common.data.kv.LongDataEntry;
|
|||||||
import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
|
import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
|
||||||
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||||
|
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||||
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
|
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
|
||||||
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
@ -93,6 +95,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
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.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,7 +208,7 @@ public class TelemetryController extends BaseController {
|
|||||||
@RequestParam(name = "interval", defaultValue = "0") Long interval,
|
@RequestParam(name = "interval", defaultValue = "0") Long interval,
|
||||||
@RequestParam(name = "limit", defaultValue = "100") Integer limit,
|
@RequestParam(name = "limit", defaultValue = "100") Integer limit,
|
||||||
@RequestParam(name = "agg", defaultValue = "NONE") String aggStr,
|
@RequestParam(name = "agg", defaultValue = "NONE") String aggStr,
|
||||||
@RequestParam(name= "orderBy", defaultValue = "DESC") String orderBy,
|
@RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy,
|
||||||
@RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
|
@RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
|
||||||
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
|
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
|
||||||
(result, tenantId, entityId) -> {
|
(result, tenantId, entityId) -> {
|
||||||
@ -392,7 +395,7 @@ public class TelemetryController extends BaseController {
|
|||||||
if (attributes.isEmpty()) {
|
if (attributes.isEmpty()) {
|
||||||
return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST);
|
return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
for (AttributeKvEntry attributeKvEntry: attributes) {
|
for (AttributeKvEntry attributeKvEntry : attributes) {
|
||||||
if (attributeKvEntry.getKey().isEmpty() || attributeKvEntry.getKey().trim().length() == 0) {
|
if (attributeKvEntry.getKey().isEmpty() || attributeKvEntry.getKey().trim().length() == 0) {
|
||||||
return getImmediateDeferredResult("Key cannot be empty or contains only spaces", HttpStatus.BAD_REQUEST);
|
return getImmediateDeferredResult("Key cannot be empty or contains only spaces", HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
@ -440,9 +443,13 @@ public class TelemetryController extends BaseController {
|
|||||||
if (entries.isEmpty()) {
|
if (entries.isEmpty()) {
|
||||||
return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST);
|
return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
SecurityUser user = getCurrentUser();
|
|
||||||
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> {
|
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> {
|
||||||
tsSubService.saveAndNotify(tenantId, entityId, entries, ttl, new FutureCallback<Void>() {
|
long tenantTtl = ttl;
|
||||||
|
if (!TenantId.SYS_TENANT_ID.equals(tenantId) && tenantTtl == 0) {
|
||||||
|
TenantProfile tenantProfile = tenantProfileCache.get(tenantId);
|
||||||
|
tenantTtl = TimeUnit.DAYS.toSeconds(((DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration()).getDefaultStorageTtlDays());
|
||||||
|
}
|
||||||
|
tsSubService.saveAndNotify(tenantId, entityId, entries, tenantTtl, new FutureCallback<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable Void tmp) {
|
public void onSuccess(@Nullable Void tmp) {
|
||||||
result.setResult(new ResponseEntity(HttpStatus.OK));
|
result.setResult(new ResponseEntity(HttpStatus.OK));
|
||||||
|
|||||||
@ -521,27 +521,27 @@ public class DefaultDeviceStateService implements DeviceStateService {
|
|||||||
|
|
||||||
private void save(DeviceId deviceId, String key, long value) {
|
private void save(DeviceId deviceId, String key, long value) {
|
||||||
if (persistToTelemetry) {
|
if (persistToTelemetry) {
|
||||||
tsSubService.saveAndNotify(
|
tsSubService.saveAndNotifyInternal(
|
||||||
TenantId.SYS_TENANT_ID, deviceId,
|
TenantId.SYS_TENANT_ID, deviceId,
|
||||||
Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new LongDataEntry(key, value))),
|
Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new LongDataEntry(key, value))),
|
||||||
new AttributeSaveCallback(deviceId, key, value));
|
new AttributeSaveCallback<>(deviceId, key, value));
|
||||||
} else {
|
} else {
|
||||||
tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(deviceId, key, value));
|
tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback<>(deviceId, key, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void save(DeviceId deviceId, String key, boolean value) {
|
private void save(DeviceId deviceId, String key, boolean value) {
|
||||||
if (persistToTelemetry) {
|
if (persistToTelemetry) {
|
||||||
tsSubService.saveAndNotify(
|
tsSubService.saveAndNotifyInternal(
|
||||||
TenantId.SYS_TENANT_ID, deviceId,
|
TenantId.SYS_TENANT_ID, deviceId,
|
||||||
Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new BooleanDataEntry(key, value))),
|
Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new BooleanDataEntry(key, value))),
|
||||||
new AttributeSaveCallback(deviceId, key, value));
|
new AttributeSaveCallback<>(deviceId, key, value));
|
||||||
} else {
|
} else {
|
||||||
tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(deviceId, key, value));
|
tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback<>(deviceId, key, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AttributeSaveCallback implements FutureCallback<Void> {
|
private static class AttributeSaveCallback<T> implements FutureCallback<T> {
|
||||||
private final DeviceId deviceId;
|
private final DeviceId deviceId;
|
||||||
private final String key;
|
private final String key;
|
||||||
private final Object value;
|
private final Object value;
|
||||||
@ -553,7 +553,7 @@ public class DefaultDeviceStateService implements DeviceStateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable Void result) {
|
public void onSuccess(@Nullable T result) {
|
||||||
log.trace("[{}] Successfully updated attribute [{}] with value [{}]", deviceId, key, value);
|
log.trace("[{}] Successfully updated attribute [{}] with value [{}]", deviceId, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory;
|
|||||||
import org.thingsboard.server.common.data.ApiUsageRecordKey;
|
import org.thingsboard.server.common.data.ApiUsageRecordKey;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
import org.thingsboard.server.common.data.EntityView;
|
import org.thingsboard.server.common.data.EntityView;
|
||||||
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
import org.thingsboard.server.common.data.id.EntityId;
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
||||||
@ -34,13 +35,14 @@ import org.thingsboard.server.common.data.kv.DoubleDataEntry;
|
|||||||
import org.thingsboard.server.common.data.kv.LongDataEntry;
|
import org.thingsboard.server.common.data.kv.LongDataEntry;
|
||||||
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||||
|
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||||
import org.thingsboard.server.common.msg.queue.ServiceType;
|
import org.thingsboard.server.common.msg.queue.ServiceType;
|
||||||
import org.thingsboard.server.common.msg.queue.TbCallback;
|
import org.thingsboard.server.common.msg.queue.TbCallback;
|
||||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
|
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
|
||||||
import org.thingsboard.server.dao.attributes.AttributesService;
|
import org.thingsboard.server.dao.attributes.AttributesService;
|
||||||
import org.thingsboard.server.dao.entityview.EntityViewService;
|
import org.thingsboard.server.dao.entityview.EntityViewService;
|
||||||
|
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
||||||
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
||||||
import org.thingsboard.server.dao.usagerecord.ApiUsageStateService;
|
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.discovery.PartitionService;
|
import org.thingsboard.server.queue.discovery.PartitionService;
|
||||||
import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
|
import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
|
||||||
@ -119,11 +121,12 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
|||||||
@Override
|
@Override
|
||||||
public void saveAndNotify(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Void> callback) {
|
public void saveAndNotify(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Void> callback) {
|
||||||
checkInternalEntity(entityId);
|
checkInternalEntity(entityId);
|
||||||
if (apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) {
|
boolean sysTenant = TenantId.SYS_TENANT_ID.equals(tenantId) || tenantId == null;
|
||||||
|
if (sysTenant || apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) {
|
||||||
saveAndNotifyInternal(tenantId, entityId, ts, ttl, new FutureCallback<Integer>() {
|
saveAndNotifyInternal(tenantId, entityId, ts, ttl, new FutureCallback<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Integer result) {
|
public void onSuccess(Integer result) {
|
||||||
if (result != null && result > 0) {
|
if (!sysTenant && result != null && result > 0) {
|
||||||
apiUsageClient.report(tenantId, ApiUsageRecordKey.STORAGE_DP_COUNT, result);
|
apiUsageClient.report(tenantId, ApiUsageRecordKey.STORAGE_DP_COUNT, result);
|
||||||
}
|
}
|
||||||
callback.onSuccess(null);
|
callback.onSuccess(null);
|
||||||
@ -134,7 +137,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
|||||||
callback.onFailure(t);
|
callback.onFailure(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else{
|
} else {
|
||||||
callback.onFailure(new RuntimeException("DB storage writes are disabled due to API limits!"));
|
callback.onFailure(new RuntimeException("DB storage writes are disabled due to API limits!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,9 +16,12 @@
|
|||||||
package org.thingsboard.server.dao.tenant;
|
package org.thingsboard.server.dao.tenant;
|
||||||
|
|
||||||
import org.thingsboard.server.common.data.TenantProfile;
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.id.TenantProfileId;
|
import org.thingsboard.server.common.data.id.TenantProfileId;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public interface TbTenantProfileCache {
|
public interface TbTenantProfileCache {
|
||||||
|
|
||||||
TenantProfile get(TenantId tenantId);
|
TenantProfile get(TenantId tenantId);
|
||||||
@ -31,4 +34,8 @@ public interface TbTenantProfileCache {
|
|||||||
|
|
||||||
void evict(TenantId id);
|
void evict(TenantId id);
|
||||||
|
|
||||||
|
void addListener(TenantId tenantId, EntityId listenerId, Consumer<TenantProfile> profileListener);
|
||||||
|
|
||||||
|
void removeListener(TenantId tenantId, EntityId listenerId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,16 +19,15 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
import org.thingsboard.server.common.data.TenantProfile;
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.id.TenantProfileId;
|
import org.thingsboard.server.common.data.id.TenantProfileId;
|
||||||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
|
||||||
import org.thingsboard.server.dao.tenant.TenantProfileService;
|
|
||||||
import org.thingsboard.server.dao.tenant.TenantService;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -40,6 +39,7 @@ public class DefaultTbTenantProfileCache implements TbTenantProfileCache {
|
|||||||
|
|
||||||
private final ConcurrentMap<TenantProfileId, TenantProfile> tenantProfilesMap = new ConcurrentHashMap<>();
|
private final ConcurrentMap<TenantProfileId, TenantProfile> tenantProfilesMap = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentMap<TenantId, TenantProfileId> tenantsMap = new ConcurrentHashMap<>();
|
private final ConcurrentMap<TenantId, TenantProfileId> tenantsMap = new ConcurrentHashMap<>();
|
||||||
|
private final ConcurrentMap<TenantId, ConcurrentMap<EntityId, Consumer<TenantProfile>>> profileListeners = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public DefaultTbTenantProfileCache(TenantProfileService tenantProfileService, TenantService tenantService) {
|
public DefaultTbTenantProfileCache(TenantProfileService tenantProfileService, TenantService tenantService) {
|
||||||
this.tenantProfileService = tenantProfileService;
|
this.tenantProfileService = tenantProfileService;
|
||||||
@ -85,17 +85,56 @@ public class DefaultTbTenantProfileCache implements TbTenantProfileCache {
|
|||||||
public void put(TenantProfile profile) {
|
public void put(TenantProfile profile) {
|
||||||
if (profile.getId() != null) {
|
if (profile.getId() != null) {
|
||||||
tenantProfilesMap.put(profile.getId(), profile);
|
tenantProfilesMap.put(profile.getId(), profile);
|
||||||
|
notifyTenantListeners(profile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evict(TenantProfileId profileId) {
|
public void evict(TenantProfileId profileId) {
|
||||||
tenantProfilesMap.remove(profileId);
|
tenantProfilesMap.remove(profileId);
|
||||||
|
notifyTenantListeners(get(profileId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyTenantListeners(TenantProfile tenantProfile) {
|
||||||
|
if (tenantProfile != null) {
|
||||||
|
tenantsMap.forEach(((tenantId, tenantProfileId) -> {
|
||||||
|
if (tenantProfileId.equals(tenantProfile.getId())) {
|
||||||
|
ConcurrentMap<EntityId, Consumer<TenantProfile>> tenantListeners = profileListeners.get(tenantId);
|
||||||
|
if (tenantListeners != null) {
|
||||||
|
tenantListeners.forEach((id, listener) -> listener.accept(tenantProfile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evict(TenantId tenantId) {
|
public void evict(TenantId tenantId) {
|
||||||
tenantsMap.remove(tenantId);
|
tenantsMap.remove(tenantId);
|
||||||
|
TenantProfile tenantProfile = get(tenantId);
|
||||||
|
if (tenantProfile != null) {
|
||||||
|
ConcurrentMap<EntityId, Consumer<TenantProfile>> tenantListeners = profileListeners.get(tenantId);
|
||||||
|
if (tenantListeners != null) {
|
||||||
|
tenantListeners.forEach((id, listener) -> listener.accept(tenantProfile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(TenantId tenantId, EntityId listenerId, Consumer<TenantProfile> profileListener) {
|
||||||
|
//Force cache of the tenant id.
|
||||||
|
get(tenantId);
|
||||||
|
if (profileListener != null) {
|
||||||
|
profileListeners.computeIfAbsent(tenantId, id -> new ConcurrentHashMap<>()).put(listenerId, profileListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeListener(TenantId tenantId, EntityId listenerId) {
|
||||||
|
ConcurrentMap<EntityId, Consumer<TenantProfile>> tenantListeners = profileListeners.get(tenantId);
|
||||||
|
if (tenantListeners != null) {
|
||||||
|
tenantListeners.remove(listenerId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.ApiUsageRecordKey;
|
|||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||||
import org.thingsboard.server.common.data.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
@ -237,7 +238,11 @@ public interface TbContext {
|
|||||||
|
|
||||||
void clearRuleNodeStates();
|
void clearRuleNodeStates();
|
||||||
|
|
||||||
|
void addTenantProfileListener(Consumer<TenantProfile> listener);
|
||||||
|
|
||||||
void addDeviceProfileListeners(Consumer<DeviceProfile> listener, BiConsumer<DeviceId, DeviceProfile> deviceListener);
|
void addDeviceProfileListeners(Consumer<DeviceProfile> listener, BiConsumer<DeviceId, DeviceProfile> deviceListener);
|
||||||
|
|
||||||
void removeProfileListener();
|
void removeListeners();
|
||||||
|
|
||||||
|
TenantProfile getTenantProfile();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,7 +149,7 @@ public class TbDeviceProfileNode implements TbNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
ctx.removeProfileListener();
|
ctx.removeListeners();
|
||||||
deviceStates.clear();
|
deviceStates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import org.thingsboard.rule.engine.api.TbContext;
|
|||||||
import org.thingsboard.rule.engine.api.TbNode;
|
import org.thingsboard.rule.engine.api.TbNode;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeException;
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
|
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
|
||||||
import org.thingsboard.server.common.data.kv.KvEntry;
|
import org.thingsboard.server.common.data.kv.KvEntry;
|
||||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||||
@ -31,10 +32,12 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
|
|||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
import org.thingsboard.server.common.msg.session.SessionMsgType;
|
import org.thingsboard.server.common.msg.session.SessionMsgType;
|
||||||
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
|
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
|
||||||
|
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RuleNode(
|
@RuleNode(
|
||||||
@ -50,12 +53,20 @@ import java.util.Map;
|
|||||||
public class TbMsgTimeseriesNode implements TbNode {
|
public class TbMsgTimeseriesNode implements TbNode {
|
||||||
|
|
||||||
private TbMsgTimeseriesNodeConfiguration config;
|
private TbMsgTimeseriesNodeConfiguration config;
|
||||||
|
private TbContext ctx;
|
||||||
private long tenantProfileDefaultStorageTtl;
|
private long tenantProfileDefaultStorageTtl;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
||||||
this.config = TbNodeUtils.convert(configuration, TbMsgTimeseriesNodeConfiguration.class);
|
this.config = TbNodeUtils.convert(configuration, TbMsgTimeseriesNodeConfiguration.class);
|
||||||
|
this.ctx = ctx;
|
||||||
|
ctx.addTenantProfileListener(this::onTenantProfileUpdate);
|
||||||
|
onTenantProfileUpdate(ctx.getTenantProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onTenantProfileUpdate(TenantProfile tenantProfile) {
|
||||||
|
DefaultTenantProfileConfiguration configuration = (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration();
|
||||||
|
tenantProfileDefaultStorageTtl = TimeUnit.DAYS.toSeconds(configuration.getDefaultStorageTtlDays());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,6 +112,7 @@ public class TbMsgTimeseriesNode implements TbNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
ctx.removeListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user