Merge remote-tracking branch 'upstream/develop/3.4' into bug/fix-active-flag-on-cloud
This commit is contained in:
commit
e068faf6f9
@ -80,6 +80,7 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
|
|||||||
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
|
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
|
||||||
import org.thingsboard.server.service.component.ComponentDiscoveryService;
|
import org.thingsboard.server.service.component.ComponentDiscoveryService;
|
||||||
import org.thingsboard.server.service.edge.rpc.EdgeRpcService;
|
import org.thingsboard.server.service.edge.rpc.EdgeRpcService;
|
||||||
|
import org.thingsboard.server.service.entitiy.entityView.TbEntityViewService;
|
||||||
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
||||||
import org.thingsboard.server.service.executors.ExternalCallExecutorService;
|
import org.thingsboard.server.service.executors.ExternalCallExecutorService;
|
||||||
import org.thingsboard.server.service.executors.SharedEventLoopGroupService;
|
import org.thingsboard.server.service.executors.SharedEventLoopGroupService;
|
||||||
@ -220,6 +221,11 @@ public class ActorSystemContext {
|
|||||||
@Getter
|
@Getter
|
||||||
private EntityViewService entityViewService;
|
private EntityViewService entityViewService;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Autowired(required = false)
|
||||||
|
@Getter
|
||||||
|
private TbEntityViewService tbEntityViewService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Getter
|
@Getter
|
||||||
private TelemetrySubscriptionService tsSubService;
|
private TelemetrySubscriptionService tsSubService;
|
||||||
|
|||||||
@ -72,6 +72,7 @@ import org.thingsboard.server.gen.edge.v1.RelationRequestMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg;
|
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg;
|
||||||
import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg;
|
import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg;
|
||||||
import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg;
|
import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg;
|
||||||
|
import org.thingsboard.server.service.entitiy.entityView.TbEntityViewService;
|
||||||
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -101,7 +102,7 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
|
|||||||
private DeviceService deviceService;
|
private DeviceService deviceService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EntityViewService entityViewService;
|
private TbEntityViewService entityViewService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceProfileService deviceProfileService;
|
private DeviceProfileService deviceProfileService;
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import lombok.Getter;
|
|||||||
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.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.thingsboard.server.cluster.TbClusterService;
|
import org.thingsboard.server.cluster.TbClusterService;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
import org.thingsboard.server.common.data.HasName;
|
import org.thingsboard.server.common.data.HasName;
|
||||||
@ -93,13 +94,13 @@ public abstract class AbstractTbEntityService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected DbCallbackExecutorService dbExecutor;
|
protected DbCallbackExecutorService dbExecutor;
|
||||||
@Autowired
|
@Autowired(required = false)
|
||||||
protected TbNotificationEntityService notificationEntityService;
|
protected TbNotificationEntityService notificationEntityService;
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
protected EdgeService edgeService;
|
protected EdgeService edgeService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected AlarmService alarmService;
|
protected AlarmService alarmService;
|
||||||
@Autowired
|
@Autowired(required = false)
|
||||||
protected EntityActionService entityActionService;
|
protected EntityActionService entityActionService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected DeviceService deviceService;
|
protected DeviceService deviceService;
|
||||||
@ -111,24 +112,27 @@ public abstract class AbstractTbEntityService {
|
|||||||
protected TenantService tenantService;
|
protected TenantService tenantService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected CustomerService customerService;
|
protected CustomerService customerService;
|
||||||
@Autowired
|
@Lazy
|
||||||
|
@Autowired(required = false)
|
||||||
protected ClaimDevicesService claimDevicesService;
|
protected ClaimDevicesService claimDevicesService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected TbTenantProfileCache tenantProfileCache;
|
protected TbTenantProfileCache tenantProfileCache;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected RuleChainService ruleChainService;
|
protected RuleChainService ruleChainService;
|
||||||
@Autowired
|
@Autowired(required = false)
|
||||||
protected TbRuleChainService tbRuleChainService;
|
protected TbRuleChainService tbRuleChainService;
|
||||||
@Autowired
|
@Autowired(required = false)
|
||||||
protected EdgeNotificationService edgeNotificationService;
|
protected EdgeNotificationService edgeNotificationService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected QueueService queueService;
|
protected QueueService queueService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected DashboardService dashboardService;
|
protected DashboardService dashboardService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected EntitiesVersionControlService vcService;
|
protected EntitiesVersionControlService vcService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected EntityViewService entityViewService;
|
protected EntityViewService entityViewService;
|
||||||
|
@Lazy
|
||||||
@Autowired
|
@Autowired
|
||||||
protected TelemetrySubscriptionService tsSubService;
|
protected TelemetrySubscriptionService tsSubService;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -149,7 +153,7 @@ public abstract class AbstractTbEntityService {
|
|||||||
protected InstallScripts installScripts;
|
protected InstallScripts installScripts;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected UserService userService;
|
protected UserService userService;
|
||||||
@Autowired
|
@Autowired(required = false)
|
||||||
protected TbResourceService resourceService;
|
protected TbResourceService resourceService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected WidgetsBundleService widgetsBundleService;
|
protected WidgetsBundleService widgetsBundleService;
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import com.google.common.util.concurrent.SettableFuture;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
import org.thingsboard.server.common.data.Customer;
|
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.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
@ -40,8 +41,9 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
|||||||
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
|
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
|
||||||
import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
|
import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
|
||||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||||
|
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
|
||||||
|
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
|
||||||
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.service.entitiy.AbstractTbEntityService;
|
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
|
||||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||||
|
|
||||||
@ -50,19 +52,22 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@TbCoreComponent
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DefaultTbEntityViewService extends AbstractTbEntityService implements TbEntityViewService {
|
public class DefaultTbEntityViewService extends AbstractTbEntityService implements TbEntityViewService {
|
||||||
|
|
||||||
private final TimeseriesService tsService;
|
private final TimeseriesService tsService;
|
||||||
|
|
||||||
|
final Map<TenantId, Map<EntityId, List<EntityView>>> localCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityView save(EntityView entityView, EntityView existingEntityView, SecurityUser user) throws ThingsboardException {
|
public EntityView save(EntityView entityView, EntityView existingEntityView, SecurityUser user) throws ThingsboardException {
|
||||||
ActionType actionType = entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
|
ActionType actionType = entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
|
||||||
@ -71,6 +76,9 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
|
|||||||
this.updateEntityViewAttributes(user, savedEntityView, existingEntityView);
|
this.updateEntityViewAttributes(user, savedEntityView, existingEntityView);
|
||||||
notificationEntityService.notifyCreateOrUpdateEntity(savedEntityView.getTenantId(), savedEntityView.getId(), savedEntityView,
|
notificationEntityService.notifyCreateOrUpdateEntity(savedEntityView.getTenantId(), savedEntityView.getId(), savedEntityView,
|
||||||
null, actionType, user);
|
null, actionType, user);
|
||||||
|
localCache.computeIfAbsent(savedEntityView.getTenantId(), (k) -> new ConcurrentReferenceHashMap<>()).clear();
|
||||||
|
tbClusterService.broadcastEntityStateChangeEvent(savedEntityView.getTenantId(), savedEntityView.getId(),
|
||||||
|
entityView.getId() == null ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
|
||||||
return savedEntityView;
|
return savedEntityView;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
notificationEntityService.notifyEntity(user.getTenantId(), emptyId(EntityType.ENTITY_VIEW), entityView, null, actionType, user, e);
|
notificationEntityService.notifyEntity(user.getTenantId(), emptyId(EntityType.ENTITY_VIEW), entityView, null, actionType, user, e);
|
||||||
@ -122,6 +130,9 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
|
|||||||
entityViewService.deleteEntityView(tenantId, entityViewId);
|
entityViewService.deleteEntityView(tenantId, entityViewId);
|
||||||
notificationEntityService.notifyDeleteEntity(tenantId, entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED,
|
notificationEntityService.notifyDeleteEntity(tenantId, entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED,
|
||||||
relatedEdgeIds, user, entityViewId.toString());
|
relatedEdgeIds, user, entityViewId.toString());
|
||||||
|
|
||||||
|
localCache.computeIfAbsent(tenantId, (k) -> new ConcurrentReferenceHashMap<>()).clear();
|
||||||
|
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityViewId, ComponentLifecycleEvent.DELETED);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null,
|
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null,
|
||||||
ActionType.DELETED, user, e, entityViewId.toString());
|
ActionType.DELETED, user, e, entityViewId.toString());
|
||||||
@ -214,6 +225,51 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId) {
|
||||||
|
Map<EntityId, List<EntityView>> localCacheByTenant = localCache.computeIfAbsent(tenantId, (k) -> new ConcurrentReferenceHashMap<>());
|
||||||
|
List<EntityView> fromLocalCache = localCacheByTenant.get(entityId);
|
||||||
|
if (fromLocalCache != null) {
|
||||||
|
return Futures.immediateFuture(fromLocalCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListenableFuture<List<EntityView>> future = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId);
|
||||||
|
|
||||||
|
return Futures.transform(future, (entityViewList) -> {
|
||||||
|
localCacheByTenant.put(entityId, entityViewList);
|
||||||
|
return entityViewList;
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComponentLifecycleMsg(ComponentLifecycleMsg componentLifecycleMsg) {
|
||||||
|
Map<EntityId, List<EntityView>> localCacheByTenant = localCache.computeIfAbsent(componentLifecycleMsg.getTenantId(), (k) -> new ConcurrentReferenceHashMap<>());
|
||||||
|
EntityViewId entityViewId = new EntityViewId(componentLifecycleMsg.getEntityId().getId());
|
||||||
|
deleteOldCacheValue(localCacheByTenant, entityViewId);
|
||||||
|
if (componentLifecycleMsg.getEvent() != ComponentLifecycleEvent.DELETED) {
|
||||||
|
EntityView entityView = entityViewService.findEntityViewById(componentLifecycleMsg.getTenantId(), entityViewId);
|
||||||
|
if (entityView != null) {
|
||||||
|
localCacheByTenant.remove(entityView.getEntityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteOldCacheValue(Map<EntityId, List<EntityView>> localCacheByTenant, EntityViewId entityViewId) {
|
||||||
|
for (var entry : localCacheByTenant.entrySet()) {
|
||||||
|
EntityView toDelete = null;
|
||||||
|
for (EntityView view : entry.getValue()) {
|
||||||
|
if (entityViewId.equals(view.getId())) {
|
||||||
|
toDelete = view;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toDelete != null) {
|
||||||
|
entry.getValue().remove(toDelete);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys, SecurityUser user) throws ThingsboardException {
|
private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys, SecurityUser user) throws ThingsboardException {
|
||||||
EntityViewId entityId = entityView.getId();
|
EntityViewId entityId = entityView.getId();
|
||||||
if (keys != null && !keys.isEmpty()) {
|
if (keys != null && !keys.isEmpty()) {
|
||||||
@ -229,8 +285,8 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
|
|||||||
long lastUpdateTs = attributeKvEntry.getLastUpdateTs();
|
long lastUpdateTs = attributeKvEntry.getLastUpdateTs();
|
||||||
return startTime == 0 && endTime == 0 ||
|
return startTime == 0 && endTime == 0 ||
|
||||||
(endTime == 0 && startTime < lastUpdateTs) ||
|
(endTime == 0 && startTime < lastUpdateTs) ||
|
||||||
(startTime == 0 && endTime > lastUpdateTs)
|
(startTime == 0 && endTime > lastUpdateTs) ||
|
||||||
? true : startTime < lastUpdateTs && endTime > lastUpdateTs;
|
(startTime < lastUpdateTs && endTime > lastUpdateTs);
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
tsSubService.saveAndNotify(entityView.getTenantId(), entityId, scope, attributes, new FutureCallback<Void>() {
|
tsSubService.saveAndNotify(entityView.getTenantId(), entityId, scope, attributes, new FutureCallback<Void>() {
|
||||||
@Override
|
@Override
|
||||||
@ -345,7 +401,7 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
|
|||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void onFailure(Throwable t) {
|
||||||
try {
|
try {
|
||||||
logTimeseriesDeleted(entityView.getTenantId(),user, entityId, keys, t);
|
logTimeseriesDeleted(entityView.getTenantId(), user, entityId, keys, t);
|
||||||
} catch (ThingsboardException e) {
|
} catch (ThingsboardException e) {
|
||||||
log.error("Failed to log timeseries delete", e);
|
log.error("Failed to log timeseries delete", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,22 +15,27 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.entitiy.entityView;
|
package org.thingsboard.server.service.entitiy.entityView;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
import org.thingsboard.server.common.data.EntityView;
|
import org.thingsboard.server.common.data.EntityView;
|
||||||
import org.thingsboard.server.common.data.edge.Edge;
|
import org.thingsboard.server.common.data.edge.Edge;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
import org.thingsboard.server.common.data.id.EntityViewId;
|
import org.thingsboard.server.common.data.id.EntityViewId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleListener;
|
||||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||||
|
|
||||||
public interface TbEntityViewService {
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface TbEntityViewService extends ComponentLifecycleListener {
|
||||||
|
|
||||||
EntityView save(EntityView entityView, EntityView existingEntityView, SecurityUser user) throws ThingsboardException;
|
EntityView save(EntityView entityView, EntityView existingEntityView, SecurityUser user) throws ThingsboardException;
|
||||||
|
|
||||||
void updateEntityViewAttributes(SecurityUser user, EntityView savedEntityView, EntityView oldEntityView) throws ThingsboardException;
|
void updateEntityViewAttributes(SecurityUser user, EntityView savedEntityView, EntityView oldEntityView) throws ThingsboardException;
|
||||||
|
|
||||||
void delete (EntityView entity, SecurityUser user) throws ThingsboardException;
|
void delete (EntityView entity, SecurityUser user) throws ThingsboardException;
|
||||||
|
|
||||||
EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer,
|
EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer,
|
||||||
SecurityUser user) throws ThingsboardException;
|
SecurityUser user) throws ThingsboardException;
|
||||||
@ -46,4 +51,6 @@ public interface TbEntityViewService {
|
|||||||
|
|
||||||
EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer,
|
EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer,
|
||||||
SecurityUser user) throws ThingsboardException;
|
SecurityUser user) throws ThingsboardException;
|
||||||
|
|
||||||
|
ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -364,13 +364,14 @@ public class DefaultTbClusterService implements TbClusterService {
|
|||||||
private void broadcast(ComponentLifecycleMsg msg) {
|
private void broadcast(ComponentLifecycleMsg msg) {
|
||||||
byte[] msgBytes = encodingService.encode(msg);
|
byte[] msgBytes = encodingService.encode(msg);
|
||||||
TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer();
|
TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer();
|
||||||
Set<String> tbRuleEngineServices = new HashSet<>(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE));
|
Set<String> tbRuleEngineServices = partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE);
|
||||||
EntityType entityType = msg.getEntityId().getEntityType();
|
EntityType entityType = msg.getEntityId().getEntityType();
|
||||||
if (entityType.equals(EntityType.TENANT)
|
if (entityType.equals(EntityType.TENANT)
|
||||||
|| entityType.equals(EntityType.TENANT_PROFILE)
|
|| entityType.equals(EntityType.TENANT_PROFILE)
|
||||||
|| entityType.equals(EntityType.DEVICE_PROFILE)
|
|| entityType.equals(EntityType.DEVICE_PROFILE)
|
||||||
|| entityType.equals(EntityType.API_USAGE_STATE)
|
|| entityType.equals(EntityType.API_USAGE_STATE)
|
||||||
|| (entityType.equals(EntityType.DEVICE) && msg.getEvent() == ComponentLifecycleEvent.UPDATED)
|
|| (entityType.equals(EntityType.DEVICE) && msg.getEvent() == ComponentLifecycleEvent.UPDATED)
|
||||||
|
|| entityType.equals(EntityType.ENTITY_VIEW)
|
||||||
|| entityType.equals(EntityType.EDGE)) {
|
|| entityType.equals(EntityType.EDGE)) {
|
||||||
TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer();
|
TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer();
|
||||||
Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE);
|
Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE);
|
||||||
|
|||||||
@ -180,6 +180,8 @@ public abstract class AbstractConsumerService<N extends com.google.protobuf.Gene
|
|||||||
deviceProfileCache.evict(componentLifecycleMsg.getTenantId(), new DeviceProfileId(componentLifecycleMsg.getEntityId().getId()));
|
deviceProfileCache.evict(componentLifecycleMsg.getTenantId(), new DeviceProfileId(componentLifecycleMsg.getEntityId().getId()));
|
||||||
} else if (EntityType.DEVICE.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
} else if (EntityType.DEVICE.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
||||||
deviceProfileCache.evict(componentLifecycleMsg.getTenantId(), new DeviceId(componentLifecycleMsg.getEntityId().getId()));
|
deviceProfileCache.evict(componentLifecycleMsg.getTenantId(), new DeviceId(componentLifecycleMsg.getEntityId().getId()));
|
||||||
|
} else if (EntityType.ENTITY_VIEW.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
||||||
|
actorContext.getTbEntityViewService().onComponentLifecycleMsg(componentLifecycleMsg);
|
||||||
} else if (EntityType.API_USAGE_STATE.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
} else if (EntityType.API_USAGE_STATE.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
||||||
apiUsageStateService.onApiUsageStateUpdate(componentLifecycleMsg.getTenantId());
|
apiUsageStateService.onApiUsageStateUpdate(componentLifecycleMsg.getTenantId());
|
||||||
} else if (EntityType.CUSTOMER.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
} else if (EntityType.CUSTOMER.equals(componentLifecycleMsg.getEntityId().getEntityType())) {
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.common.util.ThingsBoardThreadFactory;
|
import org.thingsboard.common.util.ThingsBoardThreadFactory;
|
||||||
import org.thingsboard.server.cluster.TbClusterService;
|
import org.thingsboard.server.cluster.TbClusterService;
|
||||||
@ -43,12 +44,12 @@ 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.timeseries.TimeseriesService;
|
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
||||||
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;
|
||||||
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
|
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
|
||||||
|
import org.thingsboard.server.service.entitiy.entityView.TbEntityViewService;
|
||||||
import org.thingsboard.server.service.subscription.TbSubscriptionUtils;
|
import org.thingsboard.server.service.subscription.TbSubscriptionUtils;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -75,7 +76,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
|||||||
|
|
||||||
private final AttributesService attrService;
|
private final AttributesService attrService;
|
||||||
private final TimeseriesService tsService;
|
private final TimeseriesService tsService;
|
||||||
private final EntityViewService entityViewService;
|
private final TbEntityViewService tbEntityViewService;
|
||||||
private final TbApiUsageClient apiUsageClient;
|
private final TbApiUsageClient apiUsageClient;
|
||||||
private final TbApiUsageStateService apiUsageStateService;
|
private final TbApiUsageStateService apiUsageStateService;
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
|||||||
|
|
||||||
public DefaultTelemetrySubscriptionService(AttributesService attrService,
|
public DefaultTelemetrySubscriptionService(AttributesService attrService,
|
||||||
TimeseriesService tsService,
|
TimeseriesService tsService,
|
||||||
EntityViewService entityViewService,
|
@Lazy TbEntityViewService tbEntityViewService,
|
||||||
TbClusterService clusterService,
|
TbClusterService clusterService,
|
||||||
PartitionService partitionService,
|
PartitionService partitionService,
|
||||||
TbApiUsageClient apiUsageClient,
|
TbApiUsageClient apiUsageClient,
|
||||||
@ -91,7 +92,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
|||||||
super(clusterService, partitionService);
|
super(clusterService, partitionService);
|
||||||
this.attrService = attrService;
|
this.attrService = attrService;
|
||||||
this.tsService = tsService;
|
this.tsService = tsService;
|
||||||
this.entityViewService = entityViewService;
|
this.tbEntityViewService = tbEntityViewService;
|
||||||
this.apiUsageClient = apiUsageClient;
|
this.apiUsageClient = apiUsageClient;
|
||||||
this.apiUsageStateService = apiUsageStateService;
|
this.apiUsageStateService = apiUsageStateService;
|
||||||
}
|
}
|
||||||
@ -182,11 +183,11 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
|||||||
addMainCallback(saveFuture, callback);
|
addMainCallback(saveFuture, callback);
|
||||||
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts));
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts));
|
||||||
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) {
|
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) {
|
||||||
Futures.addCallback(this.entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId),
|
Futures.addCallback(this.tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId),
|
||||||
new FutureCallback<List<EntityView>>() {
|
new FutureCallback<List<EntityView>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable List<EntityView> result) {
|
public void onSuccess(@Nullable List<EntityView> result) {
|
||||||
if (result != null) {
|
if (result != null && !result.isEmpty()) {
|
||||||
Map<String, List<TsKvEntry>> tsMap = new HashMap<>();
|
Map<String, List<TsKvEntry>> tsMap = new HashMap<>();
|
||||||
for (TsKvEntry entry : ts) {
|
for (TsKvEntry entry : ts) {
|
||||||
tsMap.computeIfAbsent(entry.getKey(), s -> new ArrayList<>()).add(entry);
|
tsMap.computeIfAbsent(entry.getKey(), s -> new ArrayList<>()).add(entry);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ import java.util.List;
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class BaseEntityRelationControllerTest extends AbstractControllerTest {
|
public abstract class BaseEntityRelationControllerTest extends AbstractControllerTest {
|
||||||
|
|
||||||
public static final String BASE_DEVICE_NAME = "Test dummy device";
|
public static final String BASE_DEVICE_NAME = "Test dummy device";
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import org.thingsboard.server.common.data.id.EntityViewId;
|
|||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
import org.thingsboard.server.common.data.page.PageLink;
|
||||||
import org.thingsboard.server.common.data.page.TimePageLink;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.common.msg.plugin;
|
||||||
|
|
||||||
|
public interface ComponentLifecycleListener {
|
||||||
|
void onComponentLifecycleMsg(ComponentLifecycleMsg componentLifecycleMsg);
|
||||||
|
}
|
||||||
@ -15,8 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.common.msg.tools;
|
package org.thingsboard.server.common.msg.tools;
|
||||||
|
|
||||||
|
import org.awaitility.pollinterval.FixedPollInterval;
|
||||||
|
import org.awaitility.pollinterval.PollInterval;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -39,10 +42,11 @@ public class RateLimitsTest {
|
|||||||
assertThat(rateLimits.tryConsume()).as("new token is available").isFalse();
|
assertThat(rateLimits.tryConsume()).as("new token is available").isFalse();
|
||||||
|
|
||||||
int expectedRefillTime = (int) (((double) period / capacity) * 1000);
|
int expectedRefillTime = (int) (((double) period / capacity) * 1000);
|
||||||
int gap = 100;
|
int gap = 500;
|
||||||
|
|
||||||
for (int i = 0; i < capacity; i++) {
|
for (int i = 0; i < capacity; i++) {
|
||||||
await("token refill for rate limit " + rateLimitConfig)
|
await("token refill for rate limit " + rateLimitConfig)
|
||||||
|
.pollInterval(new FixedPollInterval(10, TimeUnit.MILLISECONDS))
|
||||||
.atLeast(expectedRefillTime - gap, TimeUnit.MILLISECONDS)
|
.atLeast(expectedRefillTime - gap, TimeUnit.MILLISECONDS)
|
||||||
.atMost(expectedRefillTime + gap, TimeUnit.MILLISECONDS)
|
.atMost(expectedRefillTime + gap, TimeUnit.MILLISECONDS)
|
||||||
.untilAsserted(() -> {
|
.untilAsserted(() -> {
|
||||||
@ -70,6 +74,7 @@ public class RateLimitsTest {
|
|||||||
int gap = 500;
|
int gap = 500;
|
||||||
|
|
||||||
await("tokens refill for rate limit " + rateLimitConfig)
|
await("tokens refill for rate limit " + rateLimitConfig)
|
||||||
|
.pollInterval(new FixedPollInterval(10, TimeUnit.MILLISECONDS))
|
||||||
.atLeast(expectedRefillTime - gap, TimeUnit.MILLISECONDS)
|
.atLeast(expectedRefillTime - gap, TimeUnit.MILLISECONDS)
|
||||||
.atMost(expectedRefillTime + gap, TimeUnit.MILLISECONDS)
|
.atMost(expectedRefillTime + gap, TimeUnit.MILLISECONDS)
|
||||||
.untilAsserted(() -> {
|
.untilAsserted(() -> {
|
||||||
|
|||||||
@ -19,7 +19,7 @@ version: '2.2'
|
|||||||
services:
|
services:
|
||||||
kafka:
|
kafka:
|
||||||
restart: always
|
restart: always
|
||||||
image: "wurstmeister/kafka:2.13-2.6.0"
|
image: "bitnami/kafka:3.2.0"
|
||||||
ports:
|
ports:
|
||||||
- "9092:9092"
|
- "9092:9092"
|
||||||
env_file:
|
env_file:
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
|
ALLOW_PLAINTEXT_LISTENER=yes
|
||||||
KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
|
KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
|
||||||
KAFKA_LISTENERS=INSIDE://:9093,OUTSIDE://:9092
|
KAFKA_CFG_LISTENERS=INSIDE://:9093,OUTSIDE://:9092
|
||||||
KAFKA_ADVERTISED_LISTENERS=INSIDE://:9093,OUTSIDE://kafka:9092
|
KAFKA_CFG_ADVERTISED_LISTENERS=INSIDE://:9093,OUTSIDE://kafka:9092
|
||||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
|
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
|
||||||
KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE
|
KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
|
||||||
KAFKA_CREATE_TOPICS=js_eval.requests:100:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb_transport.api.requests:3:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600
|
KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INSIDE
|
||||||
KAFKA_AUTO_CREATE_TOPICS_ENABLE=false
|
KAFKA_CFG_LOG_RETENTION_BYTES=1073741824
|
||||||
KAFKA_LOG_RETENTION_BYTES=1073741824
|
KAFKA_CFG_SEGMENT_BYTES=268435456
|
||||||
KAFKA_LOG_SEGMENT_BYTES=268435456
|
KAFKA_CFG_LOG_RETENTION_MS=300000
|
||||||
KAFKA_LOG_RETENTION_MS=300000
|
KAFKA_CFG_LOG_CLEANUP_POLICY=delete
|
||||||
KAFKA_LOG_CLEANUP_POLICY=delete
|
|
||||||
|
|||||||
5
pom.xml
5
pom.xml
@ -98,8 +98,9 @@
|
|||||||
<elasticsearch.version>5.0.2</elasticsearch.version>
|
<elasticsearch.version>5.0.2</elasticsearch.version>
|
||||||
<delight-nashorn-sandbox.version>0.2.1</delight-nashorn-sandbox.version>
|
<delight-nashorn-sandbox.version>0.2.1</delight-nashorn-sandbox.version>
|
||||||
<!-- IMPORTANT: If you change the version of the kafka client, make sure to synchronize our overwritten implementation of the
|
<!-- IMPORTANT: If you change the version of the kafka client, make sure to synchronize our overwritten implementation of the
|
||||||
org.apache.kafka.common.network.NetworkReceive class in the application module. It addresses the issue https://issues.apache.org/jira/browse/KAFKA-4090. -->
|
org.apache.kafka.common.network.NetworkReceive class in the application module. It addresses the issue https://issues.apache.org/jira/browse/KAFKA-4090.
|
||||||
<kafka.version>2.8.0</kafka.version>
|
Here is the source to track https://github.com/apache/kafka/tree/trunk/clients/src/main/java/org/apache/kafka/common/network -->
|
||||||
|
<kafka.version>3.2.0</kafka.version>
|
||||||
<bucket4j.version>4.1.1</bucket4j.version>
|
<bucket4j.version>4.1.1</bucket4j.version>
|
||||||
<fst.version>2.57</fst.version>
|
<fst.version>2.57</fst.version>
|
||||||
<antlr.version>2.7.7</antlr.version>
|
<antlr.version>2.7.7</antlr.version>
|
||||||
|
|||||||
@ -50,7 +50,6 @@ import { WidgetTypeId } from '@shared/models/id/widget-type-id';
|
|||||||
import { TenantId } from '@shared/models/id/tenant-id';
|
import { TenantId } from '@shared/models/id/tenant-id';
|
||||||
import { WidgetLayout } from '@shared/models/dashboard.models';
|
import { WidgetLayout } from '@shared/models/dashboard.models';
|
||||||
import { formatValue, isDefined } from '@core/utils';
|
import { formatValue, isDefined } from '@core/utils';
|
||||||
import { forkJoin, of } from 'rxjs';
|
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
import {
|
import {
|
||||||
@ -79,7 +78,9 @@ import { PageLink } from '@shared/models/page/page-link';
|
|||||||
import { SortOrder } from '@shared/models/page/sort-order';
|
import { SortOrder } from '@shared/models/page/sort-order';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { catchError, map, mergeMap, switchMap } from 'rxjs/operators';
|
import { EdgeService } from '@core/http/edge.service';
|
||||||
|
import * as RxJS from 'rxjs';
|
||||||
|
import * as RxJSOperators from 'rxjs/operators';
|
||||||
import { TbPopoverComponent } from '@shared/components/popover.component';
|
import { TbPopoverComponent } from '@shared/components/popover.component';
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
|
|
||||||
@ -160,6 +161,7 @@ export class WidgetContext {
|
|||||||
deviceService: DeviceService;
|
deviceService: DeviceService;
|
||||||
assetService: AssetService;
|
assetService: AssetService;
|
||||||
entityViewService: EntityViewService;
|
entityViewService: EntityViewService;
|
||||||
|
edgeService: EdgeService;
|
||||||
customerService: CustomerService;
|
customerService: CustomerService;
|
||||||
dashboardService: DashboardService;
|
dashboardService: DashboardService;
|
||||||
userService: UserService;
|
userService: UserService;
|
||||||
@ -203,7 +205,7 @@ export class WidgetContext {
|
|||||||
if (this.defaultSubscription) {
|
if (this.defaultSubscription) {
|
||||||
return this.defaultSubscription.sendOneWayCommand(method, params, timeout, persistent, retries, additionalInfo, requestUUID);
|
return this.defaultSubscription.sendOneWayCommand(method, params, timeout, persistent, retries, additionalInfo, requestUUID);
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return RxJS.of(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sendTwoWayCommand: (method, params, timeout, persistent,
|
sendTwoWayCommand: (method, params, timeout, persistent,
|
||||||
@ -211,14 +213,14 @@ export class WidgetContext {
|
|||||||
if (this.defaultSubscription) {
|
if (this.defaultSubscription) {
|
||||||
return this.defaultSubscription.sendTwoWayCommand(method, params, timeout, persistent, retries, additionalInfo, requestUUID);
|
return this.defaultSubscription.sendTwoWayCommand(method, params, timeout, persistent, retries, additionalInfo, requestUUID);
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return RxJS.of(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
completedCommand: () => {
|
completedCommand: () => {
|
||||||
if (this.defaultSubscription) {
|
if (this.defaultSubscription) {
|
||||||
return this.defaultSubscription.completedCommand();
|
return this.defaultSubscription.completedCommand();
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return RxJS.of(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -266,12 +268,9 @@ export class WidgetContext {
|
|||||||
private popoverComponents: TbPopoverComponent[] = [];
|
private popoverComponents: TbPopoverComponent[] = [];
|
||||||
|
|
||||||
rxjs = {
|
rxjs = {
|
||||||
forkJoin,
|
|
||||||
of,
|
...RxJS,
|
||||||
map,
|
...RxJSOperators
|
||||||
mergeMap,
|
|
||||||
switchMap,
|
|
||||||
catchError
|
|
||||||
};
|
};
|
||||||
|
|
||||||
registerPopoverComponent(popoverComponent: TbPopoverComponent) {
|
registerPopoverComponent(popoverComponent: TbPopoverComponent) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user