Tmp commit for merge
This commit is contained in:
parent
f0a71aa3bd
commit
6b9d374a5f
@ -21,6 +21,17 @@ import org.thingsboard.server.service.cf.telemetry.CalculatedFieldTelemetryUpdat
|
||||
|
||||
public interface CalculatedFieldExecutionService {
|
||||
|
||||
/**
|
||||
* Push incoming telemetry to the CF processing queue for async processing.
|
||||
* @param request - telemetry request;
|
||||
* @param callback - callback to be executed when the message is ack by the queue.
|
||||
*/
|
||||
void pushRequestToQueue(CalculatedFieldTelemetryUpdateRequest request, TbCallback callback);
|
||||
|
||||
void pushEntityUpdateMsg(TransportProtos.CalculatedFieldEntityUpdateMsgProto proto, TbCallback callback);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
void onCalculatedFieldMsg(TransportProtos.CalculatedFieldMsgProto proto, TbCallback callback);
|
||||
|
||||
void onTelemetryUpdate(CalculatedFieldTelemetryUpdateRequest calculatedFieldTelemetryUpdateRequest);
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
package org.thingsboard.server.service.queue;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent;
|
||||
|
||||
public interface TbCalculatedFieldConsumerService extends ApplicationListener<PartitionChangeEvent> {
|
||||
|
||||
}
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.service.telemetry;
|
||||
|
||||
import com.google.common.util.concurrent.AsyncFunction;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
@ -128,8 +129,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
||||
KvUtils.validate(request.getEntries(), valueNoXssValidation);
|
||||
ListenableFuture<Integer> future = saveTimeseriesInternal(request);
|
||||
if (!request.isOnlyLatest()) {
|
||||
FutureCallback<Integer> callback = getApiUsageCallback(tenantId, request.getCustomerId(), sysTenant, request.getCallback());
|
||||
Futures.addCallback(future, callback, tsCallBackExecutor);
|
||||
Futures.addCallback(future, getApiUsageCallback(tenantId, request.getCustomerId(), sysTenant), tsCallBackExecutor);
|
||||
}
|
||||
} else {
|
||||
request.getCallback().onFailure(new RuntimeException("DB storage writes are disabled due to API limits!"));
|
||||
@ -148,7 +148,14 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
||||
} else {
|
||||
saveFuture = tsService.saveWithoutLatest(tenantId, entityId, request.getEntries(), request.getTtl());
|
||||
}
|
||||
|
||||
// We need to guarantee, that the message is successfully pushed to the calculated fields service before we execute any callbacks.
|
||||
saveFuture = Futures.transformAsync(saveFuture, new AsyncFunction<Integer, Integer>() {
|
||||
@Override
|
||||
public ListenableFuture<Integer> apply(Integer input) throws Exception {
|
||||
calculatedFieldExecutionService.onTelemetryUpdate(new CalculatedFieldTimeSeriesUpdateRequest(request));
|
||||
return input;
|
||||
}
|
||||
});
|
||||
addMainCallback(saveFuture, request.getCallback());
|
||||
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, request.getEntries()));
|
||||
if (request.isSaveLatest() && !request.isOnlyLatest()) {
|
||||
@ -326,19 +333,18 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
|
||||
}
|
||||
}
|
||||
|
||||
private FutureCallback<Integer> getApiUsageCallback(TenantId tenantId, CustomerId customerId, boolean sysTenant, FutureCallback<Void> callback) {
|
||||
private FutureCallback<Integer> getApiUsageCallback(TenantId tenantId, CustomerId customerId, boolean sysTenant) {
|
||||
return new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(Integer result) {
|
||||
if (!sysTenant && result != null && result > 0) {
|
||||
apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.STORAGE_DP_COUNT, result);
|
||||
}
|
||||
callback.onSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
callback.onFailure(t);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1692,7 +1692,6 @@ queue:
|
||||
enabled: "${TB_HOUSEKEEPER_STATS_ENABLED:true}"
|
||||
# Statistics printing interval for Housekeeper
|
||||
print-interval-ms: "${TB_HOUSEKEEPER_STATS_PRINT_INTERVAL_MS:60000}"
|
||||
|
||||
vc:
|
||||
# Default topic name
|
||||
topic: "${TB_QUEUE_VC_TOPIC:tb_version_control}"
|
||||
@ -1739,6 +1738,17 @@ queue:
|
||||
topic-deletion-delay: "${TB_QUEUE_RULE_ENGINE_TOPIC_DELETION_DELAY_SEC:15}"
|
||||
# Size of the thread pool that handles such operations as partition changes, config updates, queue deletion
|
||||
management-thread-pool-size: "${TB_QUEUE_RULE_ENGINE_MGMT_THREAD_POOL_SIZE:12}"
|
||||
calculated-fields:
|
||||
# Topic name for Calculated Field (CF) tasks
|
||||
topic: "${TB_QUEUE_CF_TOPIC:tb_calculated_fields}"
|
||||
# Interval in milliseconds to poll messages by CF (Rule Engine) microservices
|
||||
poll-interval: "${TB_QUEUE_CF_POLL_INTERVAL_MS:25}"
|
||||
# Amount of partitions used by CF microservices
|
||||
partitions: "${TB_QUEUE_CF_PARTITIONS:10}"
|
||||
# Timeout for processing a message pack by CF microservices
|
||||
pack-processing-timeout: "${TB_QUEUE_CF_PACK_PROCESSING_TIMEOUT_MS:2000}"
|
||||
# Enable/disable a separate consumer per partition for CF queue
|
||||
consumer-per-partition: "${TB_QUEUE_CF_CONSUMER_PER_PARTITION:true}"
|
||||
transport:
|
||||
# For high-priority notifications that require minimum latency and processing time
|
||||
notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}"
|
||||
|
||||
@ -145,4 +145,6 @@ public class DataConstants {
|
||||
public static final String EDGE_QUEUE_NAME = "Edge";
|
||||
public static final String EDGE_EVENT_QUEUE_NAME = "EdgeEvent";
|
||||
|
||||
public static final String CF_QUEUE_NAME = "CalculatedFields";
|
||||
|
||||
}
|
||||
|
||||
@ -26,7 +26,8 @@ public enum ServiceType {
|
||||
TB_RULE_ENGINE("TB Rule Engine"),
|
||||
TB_TRANSPORT("TB Transport"),
|
||||
JS_EXECUTOR("JS Executor"),
|
||||
TB_VC_EXECUTOR("TB VC Executor");
|
||||
TB_VC_EXECUTOR("TB VC Executor"),
|
||||
TB_CF_ENGINE("TB Calculated Fields Engine");
|
||||
|
||||
private final String label;
|
||||
|
||||
|
||||
@ -183,18 +183,6 @@ message TsKvListProto {
|
||||
repeated KeyValueProto kv = 2;
|
||||
}
|
||||
|
||||
message AttributeKvProto {
|
||||
AttributeKey key = 1;
|
||||
AttributeValueProto value = 2;
|
||||
}
|
||||
|
||||
message TelemetryProto {
|
||||
oneof proto {
|
||||
AttributeKvProto attrKv = 1;
|
||||
TsKvProto tsKv = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message DeviceInfoProto {
|
||||
int64 tenantIdMSB = 1;
|
||||
int64 tenantIdLSB = 2;
|
||||
@ -785,17 +773,7 @@ message DeviceInactivityProto {
|
||||
int64 lastInactivityTime = 5;
|
||||
}
|
||||
|
||||
message CalculatedFieldMsgProto {
|
||||
int64 tenantIdMSB = 1;
|
||||
int64 tenantIdLSB = 2;
|
||||
int64 calculatedFieldIdMSB = 3;
|
||||
int64 calculatedFieldIdLSB = 4;
|
||||
bool added = 5;
|
||||
bool updated = 6;
|
||||
bool deleted = 7;
|
||||
}
|
||||
|
||||
message EntityProfileUpdateMsgProto {
|
||||
message CalculatedFieldEntityUpdateMsgProto {
|
||||
int64 tenantIdMSB = 1;
|
||||
int64 tenantIdLSB = 2;
|
||||
string entityType = 3;
|
||||
@ -806,31 +784,26 @@ message EntityProfileUpdateMsgProto {
|
||||
int64 oldProfileIdLSB = 8;
|
||||
int64 newProfileIdMSB = 9;
|
||||
int64 newProfileIdLSB = 10;
|
||||
bool added = 11;
|
||||
bool updated = 12;
|
||||
bool deleted = 13;
|
||||
}
|
||||
|
||||
message ProfileEntityMsgProto {
|
||||
message CalculatedFieldTelemetryMsgProto {
|
||||
int64 tenantIdMSB = 1;
|
||||
int64 tenantIdLSB = 2;
|
||||
string entityType = 3;
|
||||
int64 entityIdMSB = 4;
|
||||
int64 entityIdLSB = 5;
|
||||
string entityProfileType = 6;
|
||||
int64 profileIdMSB = 7;
|
||||
int64 profileIdLSB = 8;
|
||||
bool added = 9;
|
||||
bool deleted = 10;
|
||||
}
|
||||
|
||||
message TelemetryUpdateMsgProto {
|
||||
int64 tenantIdMSB = 1;
|
||||
int64 tenantIdLSB = 2;
|
||||
string entityType = 3;
|
||||
int64 entityIdMSB = 4;
|
||||
int64 entityIdLSB = 5;
|
||||
repeated CalculatedFieldEntityCtxIdProto links = 6;
|
||||
repeated CalculatedFieldIdProto previousCalculatedFields = 7;
|
||||
string scope = 8;
|
||||
repeated TelemetryProto updatedTelemetry = 9;
|
||||
repeated TsKvProto tsData = 9;
|
||||
AttributeScopeProto scope = 10;
|
||||
repeated AttributeValueProto attrData = 11;
|
||||
}
|
||||
|
||||
message CalculatedFieldLinkedTelemetryMsgProto {
|
||||
CalculatedFieldTelemetryMsgProto msg = 1;
|
||||
repeated CalculatedFieldEntityCtxIdProto links = 2;
|
||||
}
|
||||
|
||||
message CalculatedFieldEntityCtxIdProto {
|
||||
@ -1589,9 +1562,8 @@ message ToCoreMsg {
|
||||
DeviceConnectProto deviceConnectMsg = 50;
|
||||
DeviceDisconnectProto deviceDisconnectMsg = 51;
|
||||
DeviceInactivityProto deviceInactivityMsg = 52;
|
||||
CalculatedFieldMsgProto calculatedFieldMsg = 53;
|
||||
EntityProfileUpdateMsgProto entityProfileUpdateMsg = 54;
|
||||
ProfileEntityMsgProto profileEntityMsg = 55;
|
||||
// CalculatedFieldMsgProto calculatedFieldMsg = 53;
|
||||
// EntityProfileUpdateMsgProto entityProfileUpdateMsg = 54;
|
||||
}
|
||||
|
||||
/* High priority messages with low latency are handled by ThingsBoard Core Service separately */
|
||||
@ -1611,8 +1583,8 @@ message ToCoreNotificationMsg {
|
||||
FromEdgeSyncResponseMsgProto fromEdgeSyncResponse = 12 [deprecated = true];
|
||||
ResourceCacheInvalidateMsg resourceCacheInvalidateMsg = 13;
|
||||
RestApiCallResponseMsgProto restApiCallResponseMsg = 50;
|
||||
EntityProfileUpdateMsgProto entityProfileUpdateMsg = 51;
|
||||
ProfileEntityMsgProto profileEntityMsg = 52;
|
||||
// EntityProfileUpdateMsgProto entityProfileUpdateMsg = 51;
|
||||
// ProfileEntityMsgProto profileEntityMsg = 52;
|
||||
}
|
||||
|
||||
/* Messages to Edge queue that are handled by ThingsBoard Core Service */
|
||||
@ -1632,6 +1604,16 @@ message ToEdgeEventNotificationMsg {
|
||||
EdgeEventMsgProto edgeEventMsg = 1;
|
||||
}
|
||||
|
||||
message ToCalculatedFieldMsg {
|
||||
CalculatedFieldTelemetryMsgProto telemetryMsg = 1;
|
||||
CalculatedFieldLinkedTelemetryMsgProto linkedTelemetryMsg = 2;
|
||||
}
|
||||
|
||||
message ToCalculatedFieldNotificationMsg {
|
||||
ComponentLifecycleMsgProto componentLifecycle = 1;
|
||||
CalculatedFieldEntityUpdateMsgProto entityUpdateMsg = 2;
|
||||
}
|
||||
|
||||
/* Messages that are handled by ThingsBoard RuleEngine Service */
|
||||
message ToRuleEngineMsg {
|
||||
int64 tenantIdMSB = 1;
|
||||
@ -1639,9 +1621,6 @@ message ToRuleEngineMsg {
|
||||
bytes tbMsg = 3;
|
||||
repeated string relationTypes = 4;
|
||||
string failureMessage = 5;
|
||||
TelemetryUpdateMsgProto cfTelemetryUpdateMsg = 6;
|
||||
EntityProfileUpdateMsgProto entityProfileUpdateMsg = 7;
|
||||
ProfileEntityMsgProto profileEntityMsg = 8;
|
||||
}
|
||||
|
||||
message ToRuleEngineNotificationMsg {
|
||||
|
||||
@ -51,8 +51,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.thingsboard.server.common.data.DataConstants.EDGE_QUEUE_NAME;
|
||||
import static org.thingsboard.server.common.data.DataConstants.MAIN_QUEUE_NAME;
|
||||
import static org.thingsboard.server.common.data.DataConstants.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@ -62,6 +61,10 @@ public class HashPartitionService implements PartitionService {
|
||||
private String coreTopic;
|
||||
@Value("${queue.core.partitions:10}")
|
||||
private Integer corePartitions;
|
||||
@Value("${queue.calculated-fields.topic}")
|
||||
private String cfTopic;
|
||||
@Value("${queue.calculated-fields.partitions:10}")
|
||||
private Integer cfPartitions;
|
||||
@Value("${queue.vc.topic:tb_version_control}")
|
||||
private String vcTopic;
|
||||
@Value("${queue.vc.partitions:10}")
|
||||
@ -108,10 +111,15 @@ public class HashPartitionService implements PartitionService {
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.hashFunction = forName(hashFunctionName);
|
||||
|
||||
QueueKey coreKey = new QueueKey(ServiceType.TB_CORE);
|
||||
partitionSizesMap.put(coreKey, corePartitions);
|
||||
partitionTopicsMap.put(coreKey, coreTopic);
|
||||
|
||||
QueueKey cfKey = new QueueKey(ServiceType.TB_RULE_ENGINE).withQueueName(CF_QUEUE_NAME);
|
||||
partitionSizesMap.put(cfKey, cfPartitions);
|
||||
partitionTopicsMap.put(cfKey, cfTopic);
|
||||
|
||||
QueueKey vcKey = new QueueKey(ServiceType.TB_VC_EXECUTOR);
|
||||
partitionSizesMap.put(vcKey, vcPartitions);
|
||||
partitionTopicsMap.put(vcKey, vcTopic);
|
||||
|
||||
@ -52,6 +52,10 @@ public class PartitionChangeEvent extends TbApplicationEvent {
|
||||
return getPartitionsByServiceTypeAndQueueName(ServiceType.TB_CORE, DataConstants.EDGE_QUEUE_NAME);
|
||||
}
|
||||
|
||||
public Set<TopicPartitionInfo> getCalculatedFieldsPartitions() {
|
||||
return getPartitionsByServiceTypeAndQueueName(ServiceType.TB_RULE_ENGINE, DataConstants.CF_QUEUE_NAME);
|
||||
}
|
||||
|
||||
private Set<TopicPartitionInfo> getPartitionsByServiceTypeAndQueueName(ServiceType serviceType, String queueName) {
|
||||
return partitionsMap.entrySet()
|
||||
.stream()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user