|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 45 KiB |
@ -0,0 +1,20 @@ |
|||
{ |
|||
"widgetsBundle": { |
|||
"alias": "high_performance_scada_oil_gas", |
|||
"title": "High-performance SCADA oil & gas", |
|||
"image": "tb-image:aHBfc2NhZGFfb2lsX2dhc19zeXN0ZW1fYnVuZGxlX2ltYWdlLnBuZw==:IkhpZ2gtcGVyZm9ybWFuY2UgU0NBREEgb2lsICYgZ2FzIiBzeXN0ZW0gYnVuZGxlIGltYWdl:SU1BR0U=;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAAAflBMVEXe3t7b29vf398AAADf39/e3t7e3t7////Gxsapqam5ubnR0NDj4+Otra2hoaHS0tLi4uK4uLjx8fGYmJikpKSdnZ2VlZWWlpbU1NS1tbWnp6eKioqysrLLy8uampra2tqvr6/X19eRkZF+fn7Dw8N1dXW/vr6FhYViYmJwcHCzXr36AAAABnRSTlPvIK8Av79l/pT7AAAI0UlEQVR42uza23LaMBSF4Z5msbyFpOFMAXcg0HT6/i/YGqvdNhBiYXtipf0v7CRX+UaSbWQ+fP745QNS79PHzx8+ps8A8JvxCe+idzCtwpC8Fwj+Q4bWvw0R7oQiJIbTAxAvwOmAIsFgiodYXxxPODecMYmGeD4fAOQoGtCYxEIMgcMQJbEQD5wlCvEYRLEQoig/wCBkMIgiIYKyE+claTBzKxJClO0AegDI8x0GUTREz5NTbvJUR0RwzjjAn1GpQlgcDif4nfiDAZAqBAIc8nBjNyY3ef6MQRR/HzlI7ZI7lCfHaIg5oA5Bu5bZzZaIKh6Cha9BHFq2HN2sb4gjra84rHAreCDKcjUr+n4b8n1WtHKW0LqDSGGwyFFmaOBMLGRv57uM4+moSWNONvuF7RrC8vhsBTBSEJwBEdfXUXRfux+RADIiJM4OSIIQVs8sHUmOiKlBSgd8pGS/2M8zrhutkemY2XyZ7TuGeKlBXHAJ4qN1q9mP+4ofs5WTXq5agipkqePzYLP7kBkiioIQIRrAifouSggCOsN0IaIQxyorJiOrb4uy5StrZFG2WVnTF8QZkAh5NjW4ebbKxqPo1pPdk2paQ7xHaGsAWMTMreXW7ibTUYum3DxtXBcQHRA5H6PmVjbqpKxLCEE9FUliEP49Uc9FNjGIBIdCwHSnFm8cwKQg9PqPXxgEr3ZkB4zp+tgBxNSWif7cDAJx3542nLa4+NrtkugAItefR3TxN4x2tthN1uPQ6G7jP01W2dyxszu7BXELAkIQk7Gh433I0ZaJ6fZZi8RtCEiPagN/aHS4hNSN2rAhwpch1qLasCEEX4JYCuIy4lbfXn+M36ycGHQMEby02K0aG27QbSbjadM7Bzfzhe0YAtYg6oAASGU7iLi8IaoD9OlAJBAUog5AkoHI1cBQHVEQu3nabyacNlsi2W6ebdkhRBe6QtQBIjKxDV4rzB0NtE4goiSFSI131SBf9ChEP+qKwV3IIF+9GWgsIRUHPNFDPUC8oJItDq7iePvX7U0hgmokIALt7b9L9yAEFENo6YwIL34TIk2IQPu796ulOrXC3q/29pethhDvoYV3PBzU3GoIEVRypr73W/TmcysaUjiqe7+hVCBE6OwIkPrfLTqvzxEpHApRSSojEiDBcXv/2qPv2kPoURQcNYhKBH3XHmJQFhw1COSsTAMixUEddQhcKSH6rj3EAlDHBaSUpDEiBCqOS0iQ0KPbeppa6riGBAn6rD3kynENKSWCfmsP4YXjGlJIHoYcs4t+ekQUARF1XENUQjyUrEcXrYmIYiDquIao5Fd797rcJgxEAbjX1UogBBRfErupm16mff8XbO2RWYuDqyCBx+30/EiMmTb6ugtSgYwtJcW2Q0hbUSSJkJ04ECJZO0rJRkE2hJkF4l4EYUMp0Qh5IswMEEPGvQDClAZ5RoglzAwQJpFch3DqRLK/WWsZEslVCFMqRE+4H5ILCSWWDf+OYQu0hDhGCDNh8iEFhRIbvhCCS5HYEiG1IUguRIZn+Cok55crqwm3R/IgRlrq/J3ZXLZW1u2exwnPCmRDROJj4PGB5Io8T3i+LA/CNJQUXFBRyf4syGEM0hFkvoqIpCJyFhxzttaeILNBRGKJ2BEVFsbupktcMwZpHEFyIc7RQGL8Y4GOxZHUW7KIjy3k8yE4NsvGT/bE4kjuraoFBS7kF4GQXR/fNcaRYcqGbJSKH+05EBwbnoUr3EVToxUGF/JLVETmePcCdco0ggv5hSDM67Wxds1MEEcTs79VaxkcWsU+6yg7sbVwIZ8PKQhi5UU2hFmpCeffnIpMg0z9+bYch9SWJEtBmC3z6UtuRar1D30lP9YVQXIgfPXNEcfEK9mdL0ezC868jS+KSJaoiBDYMmX1Fu/9iJvgiNeN9z06yoLEHb4iZPN6a3UugWpacbSstN98pvkgPPqWh4gkBdKVZ4falgKpWbXavzzQghXBhzNRPqWxjo1UbwXCx+1GmmshCD4uC39gSmP5MdccQI46aa5lWotDDUqcm9pYYxClW2muBSoy/kh5Ukm+6VO++Hm8d/jjpf3p9ydD4g6BiGQ6pPPnWqmCHOyyQ3UzQRi3QghKOAHSBPPIEhBLkqIigIhkIoR3/ajbAeTpEvKFZ28tcQhEJNMghWbuIY0uw5m91rqHMAslB1KEDoSgxMV/sOmUuoAoHa61tuoColTH+RDH6BBIIBayiToeVAhRtRaHLlUIUQ8mG2LAARCQRHuLH9UAIlO5nwp1K5CjhLMh4AAISKIV2akAwuW5DnLyrTmAqEMuhMEBEJDEIPsygPgRw7cA0la5FQEHQFDCsStyoxBuL9cqTQhRXT5EHAhBSfy0ZcsBpJHp4wgYh9Q2C+IcOBCCEhO/iyCQmi8ndN2vHEOI+pAFMehACEpc/MqiQJp2DNI2A4jNg6ADISjh+JVFgWjlcxKx8tEDSJcFYXQgBCU2slgEiPzPkHvWrBCDDoSghJMgzWnzGuSQBbEVRSDTJXoA2fbNFKzn6wFklQMxa0qBUGGi04hAlEBgc67WKigNQuYFV60bfcpOha3V9mtgfUrjPZxVkVQIT3xkQ2b2VqvRVHRzSHRGtFuFkUVWG7k2nwLhFEj8SvbTHxyqHd27o2UrktZbrhtxlP0/fqMgmyILYigJEl/JM0iai3bbNuBgyoLwUhByq1JdpNXBZv3UBpvPUo+bV4QpkvWu7BkffsAh8bWntN2B6I4hRHa1b5ibx9WmYK/qx87UrR6ZWW+0JclNWivpSjaz75oPD+L4+sFPxzIJ3q4i+Xepv5yXJKuCIFkQHAtLrP9yTpEKkXBX6YfDLsJIgcBf+bG8mo9YstTMD4HD7JO6mk80iKGFkt9aUyD3VRForSkQlyiZHYJn0EmQxN5aAIIjmQi5n4oMIX9tRUaer66vZkunfCafe4LISKAU8cLcU2tV3Odj+cJ85z7mBpL/H+x41/kPubf8Mx+s++od/RN58+98iPbb13//x2i/ev/67S8YXTU9MiU8PgAAAABJRU5ErkJggg==", |
|||
"scada": true, |
|||
"description": "Bundle with high-performance SCADA symbols for oil and gas system", |
|||
"order": 9405, |
|||
"name": "High-performance SCADA oil & gas" |
|||
}, |
|||
"widgetTypeFqns": [ |
|||
"hp_drilling_rig", |
|||
"hp_hook", |
|||
"hp_rotor", |
|||
"hp_preventer", |
|||
"hp_drill", |
|||
"hp_drilling_line", |
|||
"hp_platform" |
|||
] |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
{ |
|||
"fqn": "gateway_widgets.gateway_status", |
|||
"name": "Gateway status", |
|||
"deprecated": false, |
|||
"image": "tb-image;/api/images/system/gateway_status_system_widget_image.png", |
|||
"description": "Indicator of Gateway connection status.", |
|||
"descriptor": { |
|||
"type": "latest", |
|||
"sizeX": 7.5, |
|||
"sizeY": 3, |
|||
"resources": [ |
|||
{ |
|||
"url": "tb-resource;/api/resource/js_module/system/gateway-management-extension.js", |
|||
"isModule": true |
|||
} |
|||
], |
|||
"templateHtml": "<tb-gateway-status [deviceId]=\"entityId\" *ngIf=\"entityId\" [ctx]=\"ctx\"></tb-gateway-status>", |
|||
"templateCss": "", |
|||
"controllerScript": "self.onInit = function() {\n if (self.ctx.datasources && self.ctx.datasources.length) {\n self.ctx.$scope.entityId = self.ctx.datasources[0].entity.id;\n }\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.gatewayStatus?.onDataUpdated();\n};", |
|||
"settingsSchema": "", |
|||
"dataKeySettingsSchema": "", |
|||
"settingsDirective": "tb-gateway-status", |
|||
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"cardHtml\":\"<div class='card'>HTML code here</div>\",\"cardCss\":\".card {\\n font-weight: bold;\\n font-size: 32px;\\n color: #999;\\n width: 100%;\\n height: 100%;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\"},\"title\":\"HTML Card\",\"dropShadow\":true}" |
|||
}, |
|||
"tags": [ |
|||
"router", |
|||
"bridge", |
|||
"hub", |
|||
"access point", |
|||
"relay", |
|||
"opc ua", |
|||
"opc-ua", |
|||
"modbus", |
|||
"bacnet", |
|||
"odbc", |
|||
"ftp", |
|||
"snmp", |
|||
"mqtt", |
|||
"xmpp", |
|||
"ocpp", |
|||
"ble", |
|||
"bluetooth" |
|||
] |
|||
} |
|||
@ -0,0 +1,291 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.transport.coap.security; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.junit.Assert; |
|||
import org.springframework.test.context.TestPropertySource; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.transport.coap.x509.CertPrivateKey; |
|||
import org.thingsboard.server.transport.coap.x509.CoapClientX509Test; |
|||
import org.thingsboard.server.transport.coap.CoapTestConfigProperties; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.InputStream; |
|||
import java.net.ServerSocket; |
|||
import java.security.GeneralSecurityException; |
|||
import java.security.KeyStore; |
|||
import java.security.PrivateKey; |
|||
import java.security.cert.X509Certificate; |
|||
import java.util.ArrayList; |
|||
import java.util.HashSet; |
|||
import java.util.Iterator; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import static org.awaitility.Awaitility.await; |
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
@TestPropertySource(properties = { |
|||
"coap.enabled=true", |
|||
"coap.dtls.enabled=true", |
|||
"coap.dtls.credentials.pem.cert_file=coap/credentials/server/cert.pem", |
|||
"device.connectivity.coaps.enabled=true", |
|||
"service.integrations.supported=ALL", |
|||
"transport.coap.enabled=true", |
|||
}) |
|||
public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIntegrationTest { |
|||
private static final String COAPS_BASE_URL = "coaps://localhost:5684/api/v1/"; |
|||
protected final String CREDENTIALS_PATH = "coap/credentials/"; |
|||
protected final String CREDENTIALS_PATH_CLIENT = CREDENTIALS_PATH + "client/"; |
|||
protected final String CREDENTIALS_PATH_CLIENT_CERT_PEM = CREDENTIALS_PATH_CLIENT + "cert.pem"; |
|||
protected final String CREDENTIALS_PATH_CLIENT_KEY_PEM = CREDENTIALS_PATH_CLIENT + "key.pem"; |
|||
protected final X509Certificate clientX509CertTrustNo; // client certificate signed by intermediate, rootCA with a good CN ("host name")
|
|||
protected final PrivateKey clientPrivateKeyFromCertTrustNo; |
|||
|
|||
protected static final String CLIENT_JKS_FOR_TEST = "coapclientTest"; |
|||
protected static final String CLIENT_STORE_PWD = "client_ks_password"; |
|||
protected static final String CLIENT_ALIAS_CERT_TRUST_NO = "client_alias_trust_no"; |
|||
|
|||
protected AbstractCoapSecurityIntegrationTest() { |
|||
|
|||
try { |
|||
// Get certificates from key store
|
|||
char[] clientKeyStorePwd = CLIENT_STORE_PWD.toCharArray(); |
|||
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
|||
try (InputStream clientKeyStoreFile = |
|||
this.getClass().getClassLoader(). |
|||
getResourceAsStream(CREDENTIALS_PATH + CLIENT_JKS_FOR_TEST + ".jks")) { |
|||
clientKeyStore.load(clientKeyStoreFile, clientKeyStorePwd); |
|||
} |
|||
// No trust
|
|||
clientPrivateKeyFromCertTrustNo = (PrivateKey) clientKeyStore.getKey(CLIENT_ALIAS_CERT_TRUST_NO, clientKeyStorePwd); |
|||
clientX509CertTrustNo = (X509Certificate) clientKeyStore.getCertificate(CLIENT_ALIAS_CERT_TRUST_NO); |
|||
} catch (GeneralSecurityException | IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
} |
|||
|
|||
protected Device createDeviceWithX509(String deviceName, DeviceProfileId deviceProfileId, X509Certificate clientX509Cert) throws Exception { |
|||
Device device = new Device(); |
|||
device.setName(deviceName); |
|||
device.setType(deviceName); |
|||
device.setDeviceProfileId(deviceProfileId); |
|||
|
|||
DeviceCredentials deviceCredentials = new DeviceCredentials(); |
|||
deviceCredentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE); |
|||
String pemFormatCert = CertPrivateKey.convertCertToPEM(clientX509Cert); |
|||
deviceCredentials.setCredentialsValue(pemFormatCert); |
|||
|
|||
SaveDeviceWithCredentialsRequest saveRequest = new SaveDeviceWithCredentialsRequest(device, deviceCredentials); |
|||
Device deviceX509 = readResponse(doPost("/api/device-with-credentials", saveRequest) |
|||
.andExpect(status().isOk()), Device.class); |
|||
DeviceCredentials savedDeviceCredentials = |
|||
doGet("/api/device/" + deviceX509.getId().getId() + "/credentials", DeviceCredentials.class); |
|||
Assert.assertNotNull(savedDeviceCredentials); |
|||
Assert.assertNotNull(savedDeviceCredentials.getId()); |
|||
Assert.assertEquals(deviceX509.getId(), savedDeviceCredentials.getDeviceId()); |
|||
Assert.assertEquals(DeviceCredentialsType.X509_CERTIFICATE, savedDeviceCredentials.getCredentialsType()); |
|||
accessToken = savedDeviceCredentials.getCredentialsId(); |
|||
assertNotNull(accessToken); |
|||
return deviceX509; |
|||
} |
|||
|
|||
protected void clientX509FromJksUpdateAttributesTest() throws Exception { |
|||
CertPrivateKey certPrivateKey = new CertPrivateKey(clientX509CertTrustNo, clientPrivateKeyFromCertTrustNo); |
|||
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder() |
|||
.coapDeviceType(CoapDeviceType.DEFAULT) |
|||
.transportPayloadType(TransportPayloadType.JSON) |
|||
.build(); |
|||
DeviceProfile deviceProfile = createCoapDeviceProfile(configProperties); |
|||
assertNotNull(deviceProfile); |
|||
CoapClientX509Test clientX509 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey, |
|||
"CoapX509TrustNo_" + FeatureType.ATTRIBUTES.name(), deviceProfile.getId(), null); |
|||
clientX509.disconnect(); |
|||
} |
|||
|
|||
protected void clientX509FromPathUpdateFeatureTypeTest(FeatureType featureType) throws Exception { |
|||
CertPrivateKey certPrivateKey = new CertPrivateKey(CREDENTIALS_PATH_CLIENT_CERT_PEM, CREDENTIALS_PATH_CLIENT_KEY_PEM); |
|||
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder() |
|||
.coapDeviceType(CoapDeviceType.DEFAULT) |
|||
.transportPayloadType(TransportPayloadType.JSON) |
|||
.build(); |
|||
DeviceProfile deviceProfile = createCoapDeviceProfile(configProperties); |
|||
assertNotNull(deviceProfile); |
|||
CoapClientX509Test clientX509 = clientX509UpdateTest(featureType, certPrivateKey, |
|||
"CoapX509TrustNo_" + featureType.name(), deviceProfile.getId(), null); |
|||
clientX509.disconnect(); |
|||
} |
|||
protected void twoClientWithSamePortX509FromPathConnectTest() throws Exception { |
|||
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder() |
|||
.coapDeviceType(CoapDeviceType.DEFAULT) |
|||
.transportPayloadType(TransportPayloadType.JSON) |
|||
.build(); |
|||
DeviceProfile deviceProfile = createCoapDeviceProfile(configProperties); |
|||
CertPrivateKey certPrivateKey = new CertPrivateKey(CREDENTIALS_PATH_CLIENT_CERT_PEM, CREDENTIALS_PATH_CLIENT_KEY_PEM); |
|||
CertPrivateKey certPrivateKey_01 = new CertPrivateKey(CREDENTIALS_PATH_CLIENT + "cert_01.pem", |
|||
CREDENTIALS_PATH_CLIENT + "key_01.pem"); |
|||
Integer fixedPort = getFreePort(); |
|||
CoapClientX509Test clientX509 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey, |
|||
"CoapX509TrustNo_" + FeatureType.TELEMETRY.name(), deviceProfile.getId(), fixedPort); |
|||
clientX509.disconnect(); |
|||
await("Need to make port " + fixedPort + " free") |
|||
.atMost(40, TimeUnit.SECONDS) |
|||
.until(() -> isPortAvailable(fixedPort)); |
|||
CoapClientX509Test clientX509_01 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey_01, |
|||
"CoapX509TrustNo_" + FeatureType.TELEMETRY.name() + "_01", deviceProfile.getId(), |
|||
fixedPort, PAYLOAD_VALUES_STR_01); |
|||
clientX509_01.disconnect(); |
|||
} |
|||
|
|||
private CoapClientX509Test clientX509UpdateTest(FeatureType featureType, CertPrivateKey certPrivateKey, |
|||
String deviceName, DeviceProfileId deviceProfileId, Integer fixedPort) throws Exception { |
|||
return clientX509UpdateTest(featureType, certPrivateKey, deviceName, deviceProfileId, fixedPort, null); |
|||
} |
|||
|
|||
private CoapClientX509Test clientX509UpdateTest(FeatureType featureType, CertPrivateKey certPrivateKey, |
|||
String deviceName, DeviceProfileId deviceProfileId, Integer fixedPort, String payload) throws Exception { |
|||
String payloadValuesStr = payload == null ? PAYLOAD_VALUES_STR : payload; |
|||
Device deviceX509 = createDeviceWithX509(deviceName, deviceProfileId, certPrivateKey.getCert()); |
|||
CoapClientX509Test clientX509 = new CoapClientX509Test(certPrivateKey, featureType, COAPS_BASE_URL, fixedPort); |
|||
CoapResponse coapResponseX509 = clientX509.postMethod(payloadValuesStr); |
|||
assertNotNull(coapResponseX509); |
|||
assertEquals(CoAP.ResponseCode.CREATED, coapResponseX509.getCode()); |
|||
|
|||
if (FeatureType.ATTRIBUTES.equals(featureType)) { |
|||
DeviceId deviceId = deviceX509.getId(); |
|||
JsonNode expectedNode = JacksonUtil.toJsonNode(payloadValuesStr); |
|||
List<String> expectedKeys = getKeysFromNode(expectedNode); |
|||
List<String> actualKeys = getActualKeysList(deviceId, expectedKeys, "attributes/CLIENT_SCOPE"); |
|||
assertNotNull(actualKeys); |
|||
|
|||
Set<String> actualKeySet = new HashSet<>(actualKeys); |
|||
Set<String> expectedKeySet = new HashSet<>(expectedKeys); |
|||
assertEquals(expectedKeySet, actualKeySet); |
|||
|
|||
String getAttributesValuesUrl = getAttributesValuesUrl(deviceId, actualKeySet, "attributes/CLIENT_SCOPE"); |
|||
List<Map<String, Object>> actualValues = doGetAsyncTyped(getAttributesValuesUrl, new TypeReference<>() { |
|||
}); |
|||
assertValuesList(actualValues, expectedNode); |
|||
} |
|||
return clientX509; |
|||
} |
|||
|
|||
private List<String> getActualKeysList(DeviceId deviceId, List<String> expectedKeys, String apiSuffix) throws Exception { |
|||
long start = System.currentTimeMillis(); |
|||
long end = System.currentTimeMillis() + 5000; |
|||
|
|||
List<String> actualKeys = null; |
|||
while (start <= end) { |
|||
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/" + apiSuffix, new TypeReference<>() { |
|||
}); |
|||
if (actualKeys.size() == expectedKeys.size()) { |
|||
break; |
|||
} |
|||
Thread.sleep(100); |
|||
start += 100; |
|||
} |
|||
return actualKeys; |
|||
} |
|||
|
|||
private String getAttributesValuesUrl(DeviceId deviceId, Set<String> actualKeySet, String apiSuffix) { |
|||
return "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/" + apiSuffix + "?keys=" + String.join(",", actualKeySet); |
|||
} |
|||
|
|||
private List getKeysFromNode(JsonNode jNode) { |
|||
List<String> jKeys = new ArrayList<>(); |
|||
Iterator<String> fieldNames = jNode.fieldNames(); |
|||
while (fieldNames.hasNext()) { |
|||
jKeys.add(fieldNames.next()); |
|||
} |
|||
return jKeys; |
|||
} |
|||
|
|||
protected void assertValuesList(List<Map<String, Object>> actualValues, JsonNode expectedValues) { |
|||
assertTrue(actualValues.size() > 0); |
|||
assertEquals(expectedValues.size(), actualValues.size()); |
|||
for (Map<String, Object> map : actualValues) { |
|||
String key = (String) map.get("key"); |
|||
Object actualValue = map.get("value"); |
|||
assertTrue(expectedValues.has(key)); |
|||
JsonNode expectedValue = expectedValues.get(key); |
|||
assertExpectedActualValue(expectedValue, actualValue); |
|||
} |
|||
} |
|||
|
|||
protected void assertExpectedActualValue(JsonNode expectedValue, Object actualValue) { |
|||
switch (expectedValue.getNodeType()) { |
|||
case STRING: |
|||
assertEquals(expectedValue.asText(), actualValue); |
|||
break; |
|||
case NUMBER: |
|||
if (expectedValue.isInt()) { |
|||
assertEquals(expectedValue.asInt(), actualValue); |
|||
} else if (expectedValue.isLong()) { |
|||
assertEquals(expectedValue.asLong(), actualValue); |
|||
} else if (expectedValue.isFloat() || expectedValue.isDouble()) { |
|||
assertEquals(expectedValue.asDouble(), actualValue); |
|||
} |
|||
break; |
|||
case BOOLEAN: |
|||
assertEquals(expectedValue.asBoolean(), actualValue); |
|||
break; |
|||
case ARRAY: |
|||
case OBJECT: |
|||
expectedValue.toString().equals(JacksonUtil.toString(actualValue)); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
private static int getFreePort() throws IOException { |
|||
try (ServerSocket socket = new ServerSocket(0)) { |
|||
return socket.getLocalPort(); |
|||
} |
|||
} |
|||
|
|||
private static boolean isPortAvailable(int port) { |
|||
try (ServerSocket serverSocket = new ServerSocket(port)) { |
|||
serverSocket.setReuseAddress(true); |
|||
return true; |
|||
} catch (IOException e) { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,44 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.transport.coap.security.sql; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.springframework.test.context.TestPropertySource; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
import org.thingsboard.server.transport.coap.security.AbstractCoapSecurityIntegrationTest; |
|||
|
|||
@Slf4j |
|||
@DaoSqlTest |
|||
@TestPropertySource(properties = { |
|||
"coap.dtls.credentials.type=KEYSTORE", |
|||
"coap.dtls.credentials.keystore.store_file=coap/credentials/coapserverTest.jks", |
|||
"coap.dtls.credentials.keystore.key_password=server_ks_password", |
|||
"coap.dtls.credentials.keystore.key_alias=server", |
|||
}) |
|||
public class CoapClientX509SecurityJksIntegrationTest extends AbstractCoapSecurityIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testX509NoTrustFromJksConnectCoapSuccessUpdateAttributesSuccess() throws Exception { |
|||
clientX509FromJksUpdateAttributesTest(); |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.transport.coap.security.sql; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
import org.thingsboard.server.transport.coap.security.AbstractCoapSecurityIntegrationTest; |
|||
|
|||
@Slf4j |
|||
@DaoSqlTest |
|||
public class CoapClientX509SecurityPemIntegrationTest extends AbstractCoapSecurityIntegrationTest { |
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testX509NoTrustFromPathConnectCoapSuccessUpdateAttributesSuccess() throws Exception { |
|||
clientX509FromPathUpdateFeatureTypeTest(FeatureType.ATTRIBUTES); |
|||
} |
|||
@Test |
|||
public void testX509NoTrustFromPathConnectCoapSuccessUpdateTelemetrySuccess() throws Exception { |
|||
clientX509FromPathUpdateFeatureTypeTest(FeatureType.TELEMETRY); |
|||
} @Test |
|||
public void testTwoDevicesWithSamePortX509NoTrustFromPathConnectCoapSuccess() throws Exception { |
|||
twoClientWithSamePortX509FromPathConnectTest(); |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.transport.coap.x509; |
|||
|
|||
import org.apache.commons.io.FileUtils; |
|||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; |
|||
import org.thingsboard.common.util.SslUtil; |
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.security.KeyFactory; |
|||
import java.security.PrivateKey; |
|||
import java.security.cert.X509Certificate; |
|||
import java.security.interfaces.ECPrivateKey; |
|||
import java.security.spec.PKCS8EncodedKeySpec; |
|||
import java.util.Base64; |
|||
import java.util.List; |
|||
|
|||
public class CertPrivateKey { |
|||
private final X509Certificate cert; |
|||
private PrivateKey privateKey; |
|||
|
|||
public CertPrivateKey(String certFilePathPem, String keyFilePathPem) throws Exception { |
|||
List<X509Certificate> certs = SslUtil.readCertFile(fileRead(certFilePathPem)); |
|||
this.cert = certs.get(0); |
|||
this.privateKey = SslUtil.readPrivateKey(fileRead(keyFilePathPem), null); |
|||
if (this.privateKey instanceof BCECPrivateKey) { |
|||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(this.privateKey.getEncoded()); |
|||
KeyFactory keyFactory = KeyFactory.getInstance("EC"); |
|||
this.privateKey = keyFactory.generatePrivate(keySpec); |
|||
} |
|||
if (!(this.privateKey instanceof ECPrivateKey)) { |
|||
throw new RuntimeException("Private key generation must be of type java.security.interfaces.ECPrivateKey, which is used in the standard Java API!"); |
|||
} |
|||
} |
|||
|
|||
public CertPrivateKey(X509Certificate cert, PrivateKey privateKey) { |
|||
this.cert = cert; |
|||
this.privateKey = privateKey; |
|||
} |
|||
|
|||
public X509Certificate getCert() { |
|||
return this.cert; |
|||
} |
|||
|
|||
public PrivateKey getPrivateKey() { |
|||
return this.privateKey; |
|||
} |
|||
|
|||
private String fileRead(String fileName) throws IOException { |
|||
ClassLoader classLoader = getClass().getClassLoader(); |
|||
File file = new File(classLoader.getResource(fileName).getFile()); |
|||
return FileUtils.readFileToString(file, "UTF-8"); |
|||
} |
|||
|
|||
public static String convertCertToPEM(X509Certificate certificate) throws Exception { |
|||
StringBuilder pemBuilder = new StringBuilder(); |
|||
pemBuilder.append("-----BEGIN CERTIFICATE-----\n"); |
|||
// Copy cert to Base64
|
|||
String base64EncodedCert = Base64.getEncoder().encodeToString(certificate.getEncoded()); |
|||
int index = 0; |
|||
while (index < base64EncodedCert.length()) { |
|||
pemBuilder.append(base64EncodedCert, index, Math.min(index + 64, base64EncodedCert.length())); |
|||
pemBuilder.append("\n"); |
|||
index += 64; |
|||
} |
|||
pemBuilder.append("-----END CERTIFICATE-----\n"); |
|||
return pemBuilder.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,239 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.transport.coap.x509; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapHandler; |
|||
import org.eclipse.californium.core.CoapObserveRelation; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.core.coap.Request; |
|||
import org.eclipse.californium.core.config.CoapConfig; |
|||
import org.eclipse.californium.core.network.CoapEndpoint; |
|||
import org.eclipse.californium.elements.config.Configuration; |
|||
import org.eclipse.californium.elements.config.ValueException; |
|||
import org.eclipse.californium.elements.exception.ConnectorException; |
|||
import org.eclipse.californium.scandium.DTLSConnector; |
|||
import org.eclipse.californium.scandium.config.DtlsConfig.SignatureAndHashAlgorithmsDefinition; |
|||
import org.eclipse.californium.scandium.config.DtlsConnectorConfig; |
|||
import org.eclipse.californium.scandium.dtls.CertificateType; |
|||
import org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm; |
|||
import org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.HashAlgorithm; |
|||
import org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SignatureAlgorithm; |
|||
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; |
|||
import org.eclipse.californium.scandium.dtls.x509.CertificateProvider; |
|||
import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.transport.coap.CoapTestCallback; |
|||
|
|||
import java.io.IOException; |
|||
import java.net.InetSocketAddress; |
|||
import java.security.cert.X509Certificate; |
|||
import java.util.Arrays; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
|||
import static org.eclipse.californium.core.config.CoapConfig.DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_AUTO_HANDSHAKE_TIMEOUT; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CIPHER_SUITES; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_FRAGMENTED_HANDSHAKE_MESSAGE_LENGTH; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_PENDING_HANDSHAKE_RESULT_JOBS; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_RETRANSMISSIONS; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_MAX_RETRANSMISSION_TIMEOUT; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECEIVE_BUFFER_SIZE; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_ROLE; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_SIGNATURE_AND_HASH_ALGORITHMS; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_USE_HELLO_VERIFY_REQUEST; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_USE_MULTI_HANDSHAKE_MESSAGE_RECORDS; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole.CLIENT_ONLY; |
|||
import static org.eclipse.californium.scandium.config.DtlsConfig.MODULE; |
|||
import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA256_WITH_ECDSA; |
|||
import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA256_WITH_RSA; |
|||
import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA384_WITH_ECDSA; |
|||
|
|||
@Slf4j |
|||
public class CoapClientX509Test { |
|||
|
|||
private static final long CLIENT_REQUEST_TIMEOUT = 60000L; |
|||
|
|||
private final CoapClient clientX509; |
|||
private final DTLSConnector dtlsConnector; |
|||
private final Configuration config; |
|||
private final CertPrivateKey certPrivateKey; |
|||
private final String coapsBaseUrl; |
|||
|
|||
@Getter |
|||
private CoAP.Type type = CoAP.Type.CON; |
|||
|
|||
public CoapClientX509Test(CertPrivateKey certPrivateKey, FeatureType featureType, String coapsBaseUrl, Integer fixedPort) { |
|||
this.certPrivateKey = certPrivateKey; |
|||
this.coapsBaseUrl = coapsBaseUrl; |
|||
this.config = createConfiguration(); |
|||
this.dtlsConnector = createDTLSConnector(fixedPort); |
|||
this.clientX509 = createClient(getFeatureTokenUrl(featureType)); |
|||
} |
|||
public void disconnect() { |
|||
if (clientX509 != null) { |
|||
clientX509.shutdown(); |
|||
} |
|||
} |
|||
|
|||
public CoapResponse postMethod(String requestBody) throws ConnectorException, IOException { |
|||
return this.postMethod(requestBody.getBytes()); |
|||
} |
|||
|
|||
public CoapResponse postMethod(byte[] requestBodyBytes) throws ConnectorException, IOException { |
|||
return clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(requestBodyBytes, MediaTypeRegistry.APPLICATION_JSON); |
|||
} |
|||
|
|||
public void postMethod(CoapHandler handler, String payload, int format) { |
|||
clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(handler, payload, format); |
|||
} |
|||
|
|||
public void postMethod(CoapHandler handler, byte[] payload) { |
|||
clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(handler, payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
} |
|||
public void postMethod(CoapHandler handler, byte[] payload, int format) { |
|||
clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).post(handler, payload, format); |
|||
} |
|||
|
|||
public CoapResponse getMethod() throws ConnectorException, IOException { |
|||
return clientX509.setTimeout(CLIENT_REQUEST_TIMEOUT).get(); |
|||
} |
|||
|
|||
public CoapObserveRelation getObserveRelation(CoapTestCallback callback) { |
|||
return getObserveRelation(callback, true); |
|||
} |
|||
|
|||
public CoapObserveRelation getObserveRelation(CoapTestCallback callback, boolean confirmable) { |
|||
Request request = Request.newGet().setObserve(); |
|||
request.setType(confirmable ? CoAP.Type.CON : CoAP.Type.NON); |
|||
return clientX509.observe(request, callback); |
|||
} |
|||
|
|||
public void setURI(String featureTokenUrl) { |
|||
if (clientX509 == null) { |
|||
throw new RuntimeException("Failed to connect! CoapClient is not initialized!"); |
|||
} |
|||
clientX509.setURI(featureTokenUrl); |
|||
} |
|||
|
|||
public void setURI(String accessToken, FeatureType featureType) { |
|||
if (featureType == null) { |
|||
featureType = FeatureType.ATTRIBUTES; |
|||
} |
|||
setURI(getFeatureTokenUrl(accessToken, featureType)); |
|||
} |
|||
|
|||
public void useCONs() { |
|||
if (clientX509 == null) { |
|||
throw new RuntimeException("Failed to connect! CoapClient is not initialized!"); |
|||
} |
|||
type = CoAP.Type.CON; |
|||
clientX509.useCONs(); |
|||
} |
|||
|
|||
public void useNONs() { |
|||
if (clientX509 == null) { |
|||
throw new RuntimeException("Failed to connect! CoapClient is not initialized!"); |
|||
} |
|||
type = CoAP.Type.NON; |
|||
clientX509.useNONs(); |
|||
} |
|||
|
|||
private Configuration createConfiguration() { |
|||
Configuration clientCoapConfig = new Configuration(); |
|||
clientCoapConfig.set(CoapConfig.BLOCKWISE_STRICT_BLOCK2_OPTION, true); |
|||
clientCoapConfig.set(CoapConfig.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); |
|||
clientCoapConfig.set(CoapConfig.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS, TimeUnit.SECONDS); |
|||
clientCoapConfig.set(CoapConfig.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024); |
|||
clientCoapConfig.set(CoapConfig.RESPONSE_MATCHING, CoapConfig.MatcherMode.RELAXED); |
|||
clientCoapConfig.set(CoapConfig.PREFERRED_BLOCK_SIZE, 1024); |
|||
clientCoapConfig.set(CoapConfig.MAX_MESSAGE_SIZE, 1024); |
|||
clientCoapConfig.set(DTLS_ROLE, CLIENT_ONLY); |
|||
clientCoapConfig.set(DTLS_MAX_RETRANSMISSIONS, 2); |
|||
clientCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, 5000, MILLISECONDS); |
|||
clientCoapConfig.set(DTLS_MAX_RETRANSMISSION_TIMEOUT, 60000, TimeUnit.MILLISECONDS); |
|||
clientCoapConfig.set(DTLS_USE_HELLO_VERIFY_REQUEST, false); |
|||
clientCoapConfig.set(DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT, false); |
|||
clientCoapConfig.set(DTLS_MAX_FRAGMENTED_HANDSHAKE_MESSAGE_LENGTH, 22490); |
|||
clientCoapConfig.set(DTLS_AUTO_HANDSHAKE_TIMEOUT, 100000, TimeUnit.MILLISECONDS); |
|||
clientCoapConfig.set(DTLS_MAX_PENDING_HANDSHAKE_RESULT_JOBS, 64); |
|||
clientCoapConfig.set(DTLS_USE_MULTI_HANDSHAKE_MESSAGE_RECORDS, false); |
|||
clientCoapConfig.set(DTLS_RECEIVE_BUFFER_SIZE, 8192); |
|||
clientCoapConfig.setTransient(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); |
|||
SignatureAndHashAlgorithmsDefinition algorithmsDefinition = new SignatureAndHashAlgorithmsDefinition(MODULE + "SIGNATURE_AND_HASH_ALGORITHMS", "List of DTLS signature- and hash-algorithms.\nValues e.g SHA256withECDSA or ED25519."); |
|||
SignatureAndHashAlgorithm SHA384_WITH_RSA = new SignatureAndHashAlgorithm(HashAlgorithm.SHA384, |
|||
SignatureAlgorithm.RSA); |
|||
List<SignatureAndHashAlgorithm> algorithms = null; |
|||
try { |
|||
algorithms = algorithmsDefinition.checkValue(Arrays.asList(SHA256_WITH_ECDSA, SHA256_WITH_RSA, SHA384_WITH_ECDSA, SHA384_WITH_RSA)); |
|||
} catch (ValueException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
clientCoapConfig.setTransient(DTLS_SIGNATURE_AND_HASH_ALGORITHMS); |
|||
clientCoapConfig.set(DTLS_SIGNATURE_AND_HASH_ALGORITHMS, algorithms); |
|||
clientCoapConfig.setTransient(DTLS_CIPHER_SUITES); |
|||
clientCoapConfig.set(DTLS_CIPHER_SUITES, Arrays.asList(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)); |
|||
clientCoapConfig.setTransient(DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT); |
|||
clientCoapConfig.set(DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT, false); |
|||
return clientCoapConfig; |
|||
} |
|||
|
|||
private DTLSConnector createDTLSConnector(Integer fixedPort) { |
|||
try { |
|||
// Create DTLS config client
|
|||
DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder(this.config); |
|||
configBuilder.setAdvancedCertificateVerifier(new TbAdvancedCertificateVerifier()); |
|||
X509Certificate[] certificateChainClient = new X509Certificate[]{this.certPrivateKey.getCert()}; |
|||
CertificateProvider certificateProvider = new SingleCertificateProvider(this.certPrivateKey.getPrivateKey(), certificateChainClient, Collections.singletonList(CertificateType.X_509)); |
|||
configBuilder.setCertificateIdentityProvider(certificateProvider); |
|||
if (fixedPort != null) { |
|||
InetSocketAddress localAddress = new InetSocketAddress("0.0.0.0", fixedPort); |
|||
configBuilder.setAddress(localAddress); |
|||
configBuilder.setReuseAddress(true); |
|||
} |
|||
return new DTLSConnector(configBuilder.build()); |
|||
} catch (Exception e) { |
|||
throw new RuntimeException("", e); |
|||
} |
|||
} |
|||
|
|||
private CoapClient createClient(String featureTokenUrl) { |
|||
CoapClient client = new CoapClient(featureTokenUrl); |
|||
CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); |
|||
builder.setConnector(dtlsConnector); |
|||
client.setEndpoint(builder.build()); |
|||
return client; |
|||
} |
|||
|
|||
public String getFeatureTokenUrl(FeatureType featureType) { |
|||
return this.coapsBaseUrl + featureType.name().toLowerCase(); |
|||
} |
|||
|
|||
public String getFeatureTokenUrl(String token, FeatureType featureType) { |
|||
return this.coapsBaseUrl + token + "/" + featureType.name().toLowerCase(); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,129 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.transport.coap.x509; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.scandium.dtls.AlertMessage; |
|||
import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription; |
|||
import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel; |
|||
import org.eclipse.californium.scandium.dtls.CertificateMessage; |
|||
import org.eclipse.californium.scandium.dtls.CertificateType; |
|||
import org.eclipse.californium.scandium.dtls.CertificateVerificationResult; |
|||
import org.eclipse.californium.scandium.dtls.ConnectionId; |
|||
import org.eclipse.californium.scandium.dtls.HandshakeException; |
|||
import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; |
|||
import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; |
|||
import org.eclipse.californium.scandium.util.ServerNames; |
|||
|
|||
import javax.security.auth.x500.X500Principal; |
|||
import java.net.InetSocketAddress; |
|||
import java.security.PublicKey; |
|||
import java.security.cert.CertPath; |
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
public class TbAdvancedCertificateVerifier implements NewAdvancedCertificateVerifier { |
|||
|
|||
private HandshakeResultHandler resultHandler; |
|||
/** |
|||
* Get the list of supported certificate types in order of preference. |
|||
* |
|||
* @return the list of supported certificate types. |
|||
* @since 3.0 (renamed from getSupportedCertificateType) |
|||
*/ |
|||
@Override |
|||
public List<CertificateType> getSupportedCertificateTypes() { |
|||
return Arrays.asList(CertificateType.X_509, CertificateType.RAW_PUBLIC_KEY); |
|||
} |
|||
|
|||
/** |
|||
* Validates the certificate provided by the the peer as part of the |
|||
* certificate message. |
|||
* <p> |
|||
* If a x509 certificate chain is provided in the certificate message, |
|||
* validate the chain and key usage. If a RawPublicKey certificate is |
|||
* provided, check, if this public key is trusted. |
|||
* |
|||
* @param cid connection ID |
|||
* @param serverName indicated server names. May be {@code null}, if not |
|||
* available or SNI is not enabled. |
|||
* @param remotePeer socket address of remote peer |
|||
* @param clientUsage indicator to check certificate usage. {@code true}, |
|||
* check key usage for client, {@code false} for server. |
|||
* @param verifySubject {@code true} to verify the certificate's subjects, |
|||
* {@code false}, if not. |
|||
* @param truncateCertificatePath {@code true} truncate certificate path at |
|||
* a trusted certificate before validation. |
|||
* @param message certificate message to be validated |
|||
* @return certificate verification result, or {@code null}, if result is |
|||
* provided asynchronous. |
|||
* @since 3.0 (removed DTLSSession session, added remotePeer and |
|||
* verifySubject) |
|||
*/ |
|||
@Override |
|||
public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, |
|||
boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, |
|||
CertificateMessage message) { |
|||
CertPath certChain = message.getCertificateChain(); |
|||
CertificateVerificationResult result; |
|||
|
|||
if (certChain == null) { |
|||
PublicKey publicKey = message.getPublicKey(); |
|||
result = new CertificateVerificationResult(cid, publicKey, null); |
|||
} else { |
|||
if (message.getCertificateChain().getCertificates().isEmpty()) { |
|||
result = new CertificateVerificationResult(cid, new HandshakeException("Empty certificate chain", |
|||
new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE)), null); |
|||
} else { |
|||
result = new CertificateVerificationResult(cid, certChain, null); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* Return an list of certificate authorities which are trusted |
|||
* for authenticating peers. |
|||
* |
|||
* @return a non-null (possibly empty) list of accepted CA issuers. |
|||
*/ |
|||
@Override |
|||
public List<X500Principal> getAcceptedIssuers() { |
|||
log.trace("getAcceptedIssuers: return null"); |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* Set the handler for asynchronous handshake results. |
|||
* <p> |
|||
* Called during initialization of the {link DTLSConnector}. Synchronous |
|||
* implementations may just ignore this using an empty implementation. |
|||
* |
|||
* @param resultHandler handler for asynchronous master secret results. This |
|||
* handler MUST NOT be called from the thread calling |
|||
* {@link #verifyCertificate(ConnectionId, ServerNames, InetSocketAddress, boolean, boolean, boolean, CertificateMessage)}, |
|||
* instead just return the result there. |
|||
*/ |
|||
@Override |
|||
public void setResultHandler(HandshakeResultHandler resultHandler) { |
|||
if (this.resultHandler != null && resultHandler != null && this.resultHandler != resultHandler) { |
|||
throw new IllegalStateException("handshake result handler already set!"); |
|||
} |
|||
this.resultHandler = resultHandler; |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIB/TCCAaOgAwIBAgIIVNrVgKT9OE8wCgYIKoZIzj0EAwIwWjEOMAwGA1UEAxMF |
|||
Y2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNlIElv |
|||
VDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMzEwMjYwODA4MjJa |
|||
Fw0yNTEwMjUwODA4MjJaMF4xEjAQBgNVBAMTCWNmLWNsaWVudDEUMBIGA1UECxML |
|||
Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh |
|||
d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQxYO5/M5 |
|||
ie6+3QPOaAy5MD6CkFILZwIb2rOBCX/EWPaocX1H+eynUnaEEbmqxeN6rnI/pH19 |
|||
j4PtsegfHLrzzaNPME0wHQYDVR0OBBYEFKwEDLTJ+5cQoZfbjWN1vJ2ssgK+MAsG |
|||
A1UdDwQEAwIHgDAfBgNVHSMEGDAWgBSxVzoI1TL87++hsUb9vQwqODzgUTAKBggq |
|||
hkjOPQQDAgNIADBFAiA2KCOw3n2AK9Vm8u2u1bQREIEs3tKAU7eFjpNFn929NwIh |
|||
AInhBGoEwS2Xlu5bdZSfWnujoRrEQiIiQpStmLxVcIsH |
|||
-----END CERTIFICATE----- |
|||
@ -0,0 +1,14 @@ |
|||
-----BEGIN CERTIFICATE----- |
|||
MIICIzCCAcmgAwIBAgIUZZCGYm65c9vU0Xfvd/pAnLVDouUwCgYIKoZIzj0EAwIw |
|||
ZzELMAkGA1UEBhMCVUExDTALBgNVBAgMBEtpeXYxDTALBgNVBAcMBEtpeXYxFDAS |
|||
BgNVBAoMC1RoaW5nc2JvYXJkMRIwEAYDVQQLDAlkZXZlbG9wZXIxEDAOBgNVBAMM |
|||
B2NlcnRfMDEwHhcNMjQxMjE4MTU1NjE1WhcNMjUxMjE4MTU1NjE1WjBnMQswCQYD |
|||
VQQGEwJVQTENMAsGA1UECAwES2l5djENMAsGA1UEBwwES2l5djEUMBIGA1UECgwL |
|||
VGhpbmdzYm9hcmQxEjAQBgNVBAsMCWRldmVsb3BlcjEQMA4GA1UEAwwHY2VydF8w |
|||
MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNU1tE6o/QpqJJqpy+m+UoPuQe5g |
|||
eTgS4M3x0iQS6pzNEJBhzbnOp/BysGMB4wKiAWTRuKdH/gcRXDBTjLd/d7ijUzBR |
|||
MB0GA1UdDgQWBBSiao1iNWYzlsrSbxYqbda116HG1jAfBgNVHSMEGDAWgBSiao1i |
|||
NWYzlsrSbxYqbda116HG1jAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gA |
|||
MEUCIB2aCM/nvDqic9NkoSX/71GwksLiAKiFNkt2BZQykrcHAiEAr2h5IMdkyurN |
|||
Jy/idx2y44CP0tMq/3QV0QLCQFJIi6s= |
|||
-----END CERTIFICATE----- |
|||
@ -0,0 +1,4 @@ |
|||
-----BEGIN PRIVATE KEY----- |
|||
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDn0+4CuLeX7xwBs0ts |
|||
UUEDB3+HRwRKdIPeJlIbKuvvEQ== |
|||
-----END PRIVATE KEY----- |
|||
@ -0,0 +1,8 @@ |
|||
-----BEGIN EC PARAMETERS----- |
|||
BggqhkjOPQMBBw== |
|||
-----END EC PARAMETERS----- |
|||
-----BEGIN EC PRIVATE KEY----- |
|||
MHcCAQEEIJldU1MBuJUJnNHa9Ob5NGlXc/Os6put9eh1TlIbuScnoAoGCCqGSM49 |
|||
AwEHoUQDQgAE1TW0Tqj9CmokmqnL6b5Sg+5B7mB5OBLgzfHSJBLqnM0QkGHNuc6n |
|||
8HKwYwHjAqIBZNG4p0f+BxFcMFOMt393uA== |
|||
-----END EC PRIVATE KEY----- |
|||
@ -0,0 +1,35 @@ |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIBaDCCAQ2gAwIBAgIUCY+goBAOhowBs7BHs/qXdAX8XFgwCgYIKoZIzj0EAwIw |
|||
ETEPMA0GA1UEAwwGUm9vdENBMB4XDTI0MTIxOTEzNTY1OFoXDTM0MTIxNzEzNTY1 |
|||
OFowETEPMA0GA1UEAwwGU2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE |
|||
/qief3Kjnz0FpkQVaKRqJq3kHmCqqs+y1EGYLEZZAqLFvxmv7xoL6muG4Mj8tzqk |
|||
Ll94JJuz97hG1FiEZsq7O6NDMEEwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsG |
|||
AQUFBwMBMB0GA1UdDgQWBBTK/UPsN0I2ErVPILWKMRV6TSeAmTAKBggqhkjOPQQD |
|||
AgNJADBGAiEA8EhlOwvTbwGlxo55UIOJp9LBbCp0BEIWojlu8PzOVSsCIQDlV24S |
|||
3BUJVCuMRujO5lTfJLxaSKkOEIgRANwIGi88WA== |
|||
-----END CERTIFICATE----- |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIBGzCBwgIUP/PGQOKa5EyvsIXNgvv9PNietyEwCgYIKoZIzj0EAwMwEDEOMAwG |
|||
A1UEAwwFVFJVU1QwHhcNMjQxMjE5MTM1NjU4WhcNMzQxMjE3MTM1NjU4WjARMQ8w |
|||
DQYDVQQDDAZSb290Q0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT+qJ5/cqOf |
|||
PQWmRBVopGomreQeYKqqz7LUQZgsRlkCosW/Ga/vGgvqa4bgyPy3OqQuX3gkm7P3 |
|||
uEbUWIRmyrs7MAoGCCqGSM49BAMDA0gAMEUCIQD2DY3UDXbzaIBKrsCtohKlEunH |
|||
ip9LkSeYfSKCnfm23gIgA8AEJdunpRmPkilxgy6wZSLLROqDpGDnhnyv8dsR8cc= |
|||
-----END CERTIFICATE----- |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIBLTCB1AIUcsuauXAqvIS2RQcNPYysETJUAvwwCgYIKoZIzj0EAwMwIzEhMB8G |
|||
A1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTI0MTIxOTEzNTY1OFoX |
|||
DTM0MTIxNzEzNTY1OFowEDEOMAwGA1UEAwwFVFJVU1QwWTATBgcqhkjOPQIBBggq |
|||
hkjOPQMBBwNCAAT+qJ5/cqOfPQWmRBVopGomreQeYKqqz7LUQZgsRlkCosW/Ga/v |
|||
Ggvqa4bgyPy3OqQuX3gkm7P3uEbUWIRmyrs7MAoGCCqGSM49BAMDA0gAMEUCIQCM |
|||
DV8sfoArfWiXAUF2LNS3kkHD7sgb91jr2+poEHgBBgIgXf9VeJp3K5jHX6lJwtE8 |
|||
nd+jW7T9nhTc/5njHg7xons= |
|||
-----END CERTIFICATE----- |
|||
-----BEGIN EC PARAMETERS----- |
|||
BggqhkjOPQMBBw== |
|||
-----END EC PARAMETERS----- |
|||
-----BEGIN EC PRIVATE KEY----- |
|||
MHcCAQEEIB+Z69so6HqCCWo5VOFxGsLXOlTWIYijOtzt+SeNGrgPoAoGCCqGSM49 |
|||
AwEHoUQDQgAE/qief3Kjnz0FpkQVaKRqJq3kHmCqqs+y1EGYLEZZAqLFvxmv7xoL |
|||
6muG4Mj8tzqkLl94JJuz97hG1FiEZsq7Ow== |
|||
-----END EC PRIVATE KEY----- |
|||
@ -1,137 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.azure.servicebus; |
|||
|
|||
import com.microsoft.azure.servicebus.management.ManagementClient; |
|||
import com.microsoft.azure.servicebus.management.QueueDescription; |
|||
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; |
|||
import com.microsoft.azure.servicebus.primitives.MessagingEntityAlreadyExistsException; |
|||
import com.microsoft.azure.servicebus.primitives.ServiceBusException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.util.PropertyUtils; |
|||
|
|||
import java.io.IOException; |
|||
import java.time.Duration; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
|
|||
@Slf4j |
|||
@Deprecated(forRemoval = true, since = "3.9") // for removal in 4.0
|
|||
public class TbServiceBusAdmin implements TbQueueAdmin { |
|||
private final String MAX_SIZE = "maxSizeInMb"; |
|||
private final String MESSAGE_TIME_TO_LIVE = "messageTimeToLiveInSec"; |
|||
private final String LOCK_DURATION = "lockDurationInSec"; |
|||
|
|||
private final Map<String, String> queueConfigs; |
|||
private final Set<String> queues = ConcurrentHashMap.newKeySet(); |
|||
|
|||
private final ManagementClient client; |
|||
|
|||
public TbServiceBusAdmin(TbServiceBusSettings serviceBusSettings, Map<String, String> queueConfigs) { |
|||
this.queueConfigs = queueConfigs; |
|||
|
|||
ConnectionStringBuilder builder = new ConnectionStringBuilder( |
|||
serviceBusSettings.getNamespaceName(), |
|||
"queues", |
|||
serviceBusSettings.getSasKeyName(), |
|||
serviceBusSettings.getSasKey()); |
|||
|
|||
client = new ManagementClient(builder); |
|||
|
|||
try { |
|||
client.getQueues().forEach(queueDescription -> queues.add(queueDescription.getPath())); |
|||
} catch (ServiceBusException | InterruptedException e) { |
|||
log.error("Failed to get queues.", e); |
|||
throw new RuntimeException("Failed to get queues.", e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void createTopicIfNotExists(String topic, String properties) { |
|||
if (queues.contains(topic)) { |
|||
return; |
|||
} |
|||
|
|||
try { |
|||
QueueDescription queueDescription = new QueueDescription(topic); |
|||
queueDescription.setRequiresDuplicateDetection(false); |
|||
setQueueConfigs(queueDescription, PropertyUtils.getProps(queueConfigs, properties)); |
|||
|
|||
client.createQueue(queueDescription); |
|||
queues.add(topic); |
|||
} catch (ServiceBusException | InterruptedException e) { |
|||
if (e instanceof MessagingEntityAlreadyExistsException) { |
|||
queues.add(topic); |
|||
log.info("[{}] queue already exists.", topic); |
|||
} else { |
|||
log.error("Failed to create queue: [{}]", topic, e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void deleteTopic(String topic) { |
|||
if (queues.contains(topic)) { |
|||
doDelete(topic); |
|||
} else { |
|||
try { |
|||
if (client.getQueue(topic) != null) { |
|||
doDelete(topic); |
|||
} else { |
|||
log.warn("Azure Service Bus Queue [{}] is not exist.", topic); |
|||
} |
|||
} catch (ServiceBusException | InterruptedException e) { |
|||
log.error("Failed to delete Azure Service Bus queue [{}]", topic, e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void doDelete(String topic) { |
|||
try { |
|||
client.deleteTopic(topic); |
|||
} catch (ServiceBusException | InterruptedException e) { |
|||
log.error("Failed to delete Azure Service Bus queue [{}]", topic, e); |
|||
} |
|||
} |
|||
|
|||
private void setQueueConfigs(QueueDescription queueDescription, Map<String, String> queueConfigs) { |
|||
queueConfigs.forEach((confKey, confValue) -> { |
|||
switch (confKey) { |
|||
case MAX_SIZE: |
|||
queueDescription.setMaxSizeInMB(Long.parseLong(confValue)); |
|||
break; |
|||
case MESSAGE_TIME_TO_LIVE: |
|||
queueDescription.setDefaultMessageTimeToLive(Duration.ofSeconds(Long.parseLong(confValue))); |
|||
break; |
|||
case LOCK_DURATION: |
|||
queueDescription.setLockDuration(Duration.ofSeconds(Long.parseLong(confValue))); |
|||
break; |
|||
default: |
|||
log.error("Unknown config: [{}]", confKey); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void destroy() { |
|||
try { |
|||
client.close(); |
|||
} catch (IOException e) { |
|||
log.error("Failed to close ManagementClient."); |
|||
} |
|||
} |
|||
} |
|||
@ -1,175 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.azure.servicebus; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import com.microsoft.azure.servicebus.TransactionContext; |
|||
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; |
|||
import com.microsoft.azure.servicebus.primitives.CoreMessageReceiver; |
|||
import com.microsoft.azure.servicebus.primitives.MessageWithDeliveryTag; |
|||
import com.microsoft.azure.servicebus.primitives.MessagingEntityType; |
|||
import com.microsoft.azure.servicebus.primitives.MessagingFactory; |
|||
import com.microsoft.azure.servicebus.primitives.SettleModePair; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.qpid.proton.amqp.messaging.Data; |
|||
import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; |
|||
import org.apache.qpid.proton.amqp.transport.SenderSettleMode; |
|||
import org.springframework.util.CollectionUtils; |
|||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueMsg; |
|||
import org.thingsboard.server.queue.TbQueueMsgDecoder; |
|||
import org.thingsboard.server.queue.common.AbstractTbQueueConsumerTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|||
|
|||
import java.time.Duration; |
|||
import java.util.Collection; |
|||
import java.util.Collections; |
|||
import java.util.HashSet; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
import java.util.concurrent.CompletableFuture; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ExecutionException; |
|||
import java.util.stream.Collectors; |
|||
import java.util.stream.Stream; |
|||
|
|||
@Slf4j |
|||
public class TbServiceBusConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQueueConsumerTemplate<MessageWithDeliveryTag, T> { |
|||
private final TbQueueAdmin admin; |
|||
private final TbQueueMsgDecoder<T> decoder; |
|||
private final TbServiceBusSettings serviceBusSettings; |
|||
|
|||
private final Gson gson = new Gson(); |
|||
|
|||
private Set<CoreMessageReceiver> receivers; |
|||
private final Map<CoreMessageReceiver, Collection<MessageWithDeliveryTag>> pendingMessages = new ConcurrentHashMap<>(); |
|||
private volatile int messagesPerQueue; |
|||
|
|||
public TbServiceBusConsumerTemplate(TbQueueAdmin admin, TbServiceBusSettings serviceBusSettings, String topic, TbQueueMsgDecoder<T> decoder) { |
|||
super(topic); |
|||
this.admin = admin; |
|||
this.decoder = decoder; |
|||
this.serviceBusSettings = serviceBusSettings; |
|||
} |
|||
|
|||
@Override |
|||
protected List<MessageWithDeliveryTag> doPoll(long durationInMillis) { |
|||
List<CompletableFuture<Collection<MessageWithDeliveryTag>>> messageFutures = |
|||
receivers.stream() |
|||
.map(receiver -> receiver |
|||
.receiveAsync(messagesPerQueue, Duration.ofMillis(durationInMillis)) |
|||
.whenComplete((messages, err) -> { |
|||
if (!CollectionUtils.isEmpty(messages)) { |
|||
pendingMessages.put(receiver, messages); |
|||
} else if (err != null) { |
|||
log.error("Failed to receive messages.", err); |
|||
} |
|||
})) |
|||
.collect(Collectors.toList()); |
|||
try { |
|||
return fromList(messageFutures) |
|||
.get() |
|||
.stream() |
|||
.flatMap(messages -> CollectionUtils.isEmpty(messages) ? Stream.empty() : messages.stream()) |
|||
.collect(Collectors.toList()); |
|||
} catch (InterruptedException | ExecutionException e) { |
|||
if (stopped) { |
|||
log.info("[{}] Service Bus consumer is stopped.", getTopic()); |
|||
} else { |
|||
log.error("Failed to receive messages", e); |
|||
} |
|||
return Collections.emptyList(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
protected void doSubscribe(List<String> topicNames) { |
|||
createReceivers(); |
|||
messagesPerQueue = receivers.size() / Math.max(partitions.size(), 1); |
|||
} |
|||
|
|||
@Override |
|||
protected void doCommit() { |
|||
pendingMessages.forEach((receiver, msgs) -> |
|||
msgs.forEach(msg -> receiver.completeMessageAsync(msg.getDeliveryTag(), TransactionContext.NULL_TXN))); |
|||
pendingMessages.clear(); |
|||
} |
|||
|
|||
@Override |
|||
protected void doUnsubscribe() { |
|||
receivers.forEach(CoreMessageReceiver::closeAsync); |
|||
} |
|||
|
|||
private void createReceivers() { |
|||
List<CompletableFuture<CoreMessageReceiver>> receiverFutures = partitions.stream() |
|||
.map(TopicPartitionInfo::getFullTopicName) |
|||
.map(queue -> { |
|||
MessagingFactory factory; |
|||
try { |
|||
factory = MessagingFactory.createFromConnectionStringBuilder(createConnection(queue)); |
|||
} catch (InterruptedException | ExecutionException e) { |
|||
log.error("Failed to create factory for the queue [{}]", queue); |
|||
throw new RuntimeException("Failed to create the factory", e); |
|||
} |
|||
|
|||
return CoreMessageReceiver.create(factory, queue, queue, 0, |
|||
new SettleModePair(SenderSettleMode.UNSETTLED, ReceiverSettleMode.SECOND), |
|||
MessagingEntityType.QUEUE); |
|||
}).collect(Collectors.toList()); |
|||
|
|||
try { |
|||
receivers = new HashSet<>(fromList(receiverFutures).get()); |
|||
} catch (InterruptedException | ExecutionException e) { |
|||
if (stopped) { |
|||
log.info("[{}] Service Bus consumer is stopped.", getTopic()); |
|||
} else { |
|||
log.error("Failed to create receivers", e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private ConnectionStringBuilder createConnection(String queue) { |
|||
admin.createTopicIfNotExists(queue); |
|||
return new ConnectionStringBuilder( |
|||
serviceBusSettings.getNamespaceName(), |
|||
queue, |
|||
serviceBusSettings.getSasKeyName(), |
|||
serviceBusSettings.getSasKey()); |
|||
} |
|||
|
|||
private <V> CompletableFuture<List<V>> fromList(List<CompletableFuture<V>> futures) { |
|||
@SuppressWarnings("unchecked") |
|||
CompletableFuture<Collection<V>>[] arrayFuture = new CompletableFuture[futures.size()]; |
|||
futures.toArray(arrayFuture); |
|||
|
|||
return CompletableFuture |
|||
.allOf(arrayFuture) |
|||
.thenApply(v -> futures |
|||
.stream() |
|||
.map(CompletableFuture::join) |
|||
.collect(Collectors.toList())); |
|||
} |
|||
|
|||
@Override |
|||
protected T decode(MessageWithDeliveryTag data) throws InvalidProtocolBufferException { |
|||
DefaultTbQueueMsg msg = gson.fromJson(new String(((Data) data.getMessage().getBody()).getValue().getArray()), DefaultTbQueueMsg.class); |
|||
return decoder.decode(msg); |
|||
} |
|||
|
|||
} |
|||
@ -1,110 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.azure.servicebus; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.microsoft.azure.servicebus.IMessage; |
|||
import com.microsoft.azure.servicebus.Message; |
|||
import com.microsoft.azure.servicebus.QueueClient; |
|||
import com.microsoft.azure.servicebus.ReceiveMode; |
|||
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; |
|||
import com.microsoft.azure.servicebus.primitives.ServiceBusException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueCallback; |
|||
import org.thingsboard.server.queue.TbQueueMsg; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|||
|
|||
import java.util.Map; |
|||
import java.util.concurrent.CompletableFuture; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.Executors; |
|||
|
|||
@Slf4j |
|||
public class TbServiceBusProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> { |
|||
private final String defaultTopic; |
|||
private final Gson gson = new Gson(); |
|||
private final TbQueueAdmin admin; |
|||
private final TbServiceBusSettings serviceBusSettings; |
|||
private final Map<String, QueueClient> clients = new ConcurrentHashMap<>(); |
|||
private final ExecutorService executorService; |
|||
|
|||
public TbServiceBusProducerTemplate(TbQueueAdmin admin, TbServiceBusSettings serviceBusSettings, String defaultTopic) { |
|||
this.admin = admin; |
|||
this.defaultTopic = defaultTopic; |
|||
this.serviceBusSettings = serviceBusSettings; |
|||
executorService = Executors.newCachedThreadPool(); |
|||
} |
|||
|
|||
@Override |
|||
public void init() { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public String getDefaultTopic() { |
|||
return defaultTopic; |
|||
} |
|||
|
|||
@Override |
|||
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { |
|||
IMessage message = new Message(gson.toJson(new DefaultTbQueueMsg(msg))); |
|||
CompletableFuture<Void> future = getClient(tpi.getFullTopicName()).sendAsync(message); |
|||
future.whenCompleteAsync((success, err) -> { |
|||
if (err != null) { |
|||
callback.onFailure(err); |
|||
} else { |
|||
callback.onSuccess(null); |
|||
} |
|||
}, executorService); |
|||
} |
|||
|
|||
@Override |
|||
public void stop() { |
|||
clients.forEach((t, client) -> { |
|||
try { |
|||
client.close(); |
|||
} catch (ServiceBusException e) { |
|||
log.error("Failed to close QueueClient.", e); |
|||
} |
|||
}); |
|||
|
|||
if (executorService != null) { |
|||
executorService.shutdownNow(); |
|||
} |
|||
} |
|||
|
|||
private QueueClient getClient(String topic) { |
|||
return clients.computeIfAbsent(topic, k -> { |
|||
admin.createTopicIfNotExists(topic); |
|||
ConnectionStringBuilder builder = |
|||
new ConnectionStringBuilder( |
|||
serviceBusSettings.getNamespaceName(), |
|||
topic, |
|||
serviceBusSettings.getSasKeyName(), |
|||
serviceBusSettings.getSasKey()); |
|||
try { |
|||
return new QueueClient(builder, ReceiveMode.PEEKLOCK); |
|||
} catch (InterruptedException | ServiceBusException e) { |
|||
log.error("Failed to create new client for the Queue: [{}]", topic, e); |
|||
throw new RuntimeException("Failed to create new client for the Queue", e); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
@ -1,72 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.azure.servicebus; |
|||
|
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.Getter; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.queue.util.PropertyUtils; |
|||
|
|||
import java.util.Map; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus'") |
|||
public class TbServiceBusQueueConfigs { |
|||
|
|||
@Value("${queue.service-bus.queue-properties.core:}") |
|||
private String coreProperties; |
|||
@Value("${queue.service-bus.queue-properties.rule-engine:}") |
|||
private String ruleEngineProperties; |
|||
@Value("${queue.service-bus.queue-properties.transport-api:}") |
|||
private String transportApiProperties; |
|||
@Value("${queue.service-bus.queue-properties.notifications:}") |
|||
private String notificationsProperties; |
|||
@Value("${queue.service-bus.queue-properties.js-executor:}") |
|||
private String jsExecutorProperties; |
|||
@Value("${queue.service-bus.queue-properties.version-control:}") |
|||
private String vcProperties; |
|||
@Value("${queue.service-bus.queue-properties.edge:}") |
|||
private String edgeProperties; |
|||
|
|||
@Getter |
|||
private Map<String, String> coreConfigs; |
|||
@Getter |
|||
private Map<String, String> ruleEngineConfigs; |
|||
@Getter |
|||
private Map<String, String> transportApiConfigs; |
|||
@Getter |
|||
private Map<String, String> notificationsConfigs; |
|||
@Getter |
|||
private Map<String, String> jsExecutorConfigs; |
|||
@Getter |
|||
private Map<String, String> vcConfigs; |
|||
@Getter |
|||
private Map<String, String> edgeConfigs; |
|||
|
|||
@PostConstruct |
|||
private void init() { |
|||
coreConfigs = PropertyUtils.getProps(coreProperties); |
|||
ruleEngineConfigs = PropertyUtils.getProps(ruleEngineProperties); |
|||
transportApiConfigs = PropertyUtils.getProps(transportApiProperties); |
|||
notificationsConfigs = PropertyUtils.getProps(notificationsProperties); |
|||
jsExecutorConfigs = PropertyUtils.getProps(jsExecutorProperties); |
|||
vcConfigs = PropertyUtils.getProps(vcProperties); |
|||
edgeConfigs = PropertyUtils.getProps(edgeProperties); |
|||
} |
|||
|
|||
} |
|||
@ -1,37 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.azure.servicebus; |
|||
|
|||
import lombok.Data; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Slf4j |
|||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus'") |
|||
@Component |
|||
@Data |
|||
public class TbServiceBusSettings { |
|||
@Value("${queue.service_bus.namespace_name}") |
|||
private String namespaceName; |
|||
@Value("${queue.service_bus.sas_key_name}") |
|||
private String sasKeyName; |
|||
@Value("${queue.service_bus.sas_key}") |
|||
private String sasKey; |
|||
@Value("${queue.service_bus.max_messages}") |
|||
private int maxMessages; |
|||
} |
|||
@ -1,317 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import com.google.protobuf.util.JsonFormat; |
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.queue.Queue; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='monolith'") |
|||
public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory, TbVersionControlQueueFactory { |
|||
|
|||
private final TopicService topicService; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TbQueueTransportApiSettings transportApiSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TbAwsSqsSettings sqsSettings; |
|||
private final TbQueueVersionControlSettings vcSettings; |
|||
private final TbQueueEdgeSettings edgeSettings; |
|||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
private final TbQueueAdmin jsExecutorAdmin; |
|||
private final TbQueueAdmin transportApiAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin otaAdmin; |
|||
private final TbQueueAdmin vcAdmin; |
|||
private final TbQueueAdmin edgeAdmin; |
|||
|
|||
public AwsSqsMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbQueueTransportApiSettings transportApiSettings, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|||
TbAwsSqsSettings sqsSettings, |
|||
TbQueueVersionControlSettings vcSettings, |
|||
TbQueueEdgeSettings edgeSettings, |
|||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|||
TbQueueRemoteJsInvokeSettings jsInvokeSettings) { |
|||
this.topicService = topicService; |
|||
this.coreSettings = coreSettings; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.transportApiSettings = transportApiSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.sqsSettings = sqsSettings; |
|||
this.vcSettings = vcSettings; |
|||
this.edgeSettings = edgeSettings; |
|||
this.jsInvokeSettings = jsInvokeSettings; |
|||
|
|||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|||
this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); |
|||
this.transportApiAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getTransportApiAttributes()); |
|||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|||
this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); |
|||
this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); |
|||
this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|||
); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|||
return new TbAwsSqsConsumerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(configuration.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|||
} |
|||
|
|||
@Override |
|||
@Bean |
|||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|||
TbQueueProducer<TbProtoJsQueueMsg<RemoteJsRequest>> producer = new TbAwsSqsProducerTemplate<>(jsExecutorAdmin, sqsSettings, jsInvokeSettings.getRequestTopic()); |
|||
TbQueueConsumer<TbProtoQueueMsg<RemoteJsResponse>> consumer = new TbAwsSqsConsumerTemplate<>(jsExecutorAdmin, sqsSettings, |
|||
jsInvokeSettings.getResponseTopic() + "_" + serviceInfoProvider.getServiceId(), |
|||
msg -> { |
|||
RemoteJsResponse.Builder builder = RemoteJsResponse.newBuilder(); |
|||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|||
}); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|||
builder.queueAdmin(jsExecutorAdmin); |
|||
builder.requestTemplate(producer); |
|||
builder.responseTemplate(consumer); |
|||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|||
return builder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|||
} |
|||
|
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|||
return null; |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
if (jsExecutorAdmin != null) { |
|||
jsExecutorAdmin.destroy(); |
|||
} |
|||
if (transportApiAdmin != null) { |
|||
transportApiAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (otaAdmin != null) { |
|||
otaAdmin.destroy(); |
|||
} |
|||
if (vcAdmin != null) { |
|||
vcAdmin.destroy(); |
|||
} |
|||
if (edgeAdmin != null) { |
|||
edgeAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,291 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import com.google.protobuf.util.JsonFormat; |
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-core'") |
|||
public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { |
|||
|
|||
private final TbAwsSqsSettings sqsSettings; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbQueueTransportApiSettings transportApiSettings; |
|||
private final TopicService topicService; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TbQueueVersionControlSettings vcSettings; |
|||
private final TbQueueEdgeSettings edgeSettings; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
private final TbQueueAdmin jsExecutorAdmin; |
|||
private final TbQueueAdmin transportApiAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin otaAdmin; |
|||
private final TbQueueAdmin vcAdmin; |
|||
private final TbQueueAdmin edgeAdmin; |
|||
|
|||
public AwsSqsTbCoreQueueFactory(TbAwsSqsSettings sqsSettings, |
|||
TbQueueCoreSettings coreSettings, |
|||
TbQueueTransportApiSettings transportApiSettings, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TopicService topicService, |
|||
TbQueueVersionControlSettings vcSettings, |
|||
TbQueueEdgeSettings edgeSettings, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings) { |
|||
this.sqsSettings = sqsSettings; |
|||
this.coreSettings = coreSettings; |
|||
this.transportApiSettings = transportApiSettings; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.edgeSettings = edgeSettings; |
|||
this.topicService = topicService; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.jsInvokeSettings = jsInvokeSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.vcSettings = vcSettings; |
|||
|
|||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|||
this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); |
|||
this.transportApiAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getTransportApiAttributes()); |
|||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|||
this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); |
|||
this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); |
|||
this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|||
} |
|||
|
|||
@Override |
|||
@Bean |
|||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbAwsSqsProducerTemplate<>(jsExecutorAdmin, sqsSettings, jsInvokeSettings.getRequestTopic()); |
|||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbAwsSqsConsumerTemplate<>(jsExecutorAdmin, sqsSettings, |
|||
jsInvokeSettings.getResponseTopic() + "_" + serviceInfoProvider.getServiceId(), |
|||
msg -> { |
|||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|||
}); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|||
builder.queueAdmin(jsExecutorAdmin); |
|||
builder.requestTemplate(producer); |
|||
builder.responseTemplate(consumer); |
|||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|||
return builder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
if (jsExecutorAdmin != null) { |
|||
jsExecutorAdmin.destroy(); |
|||
} |
|||
if (transportApiAdmin != null) { |
|||
transportApiAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (otaAdmin != null) { |
|||
otaAdmin.destroy(); |
|||
} |
|||
if (vcAdmin != null) { |
|||
vcAdmin.destroy(); |
|||
} |
|||
if (edgeAdmin != null) { |
|||
edgeAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,208 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import com.google.protobuf.util.JsonFormat; |
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.queue.Queue; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-rule-engine'") |
|||
public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { |
|||
|
|||
private final TopicService topicService; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TbAwsSqsSettings sqsSettings; |
|||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TbQueueEdgeSettings edgeSettings; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
private final TbQueueAdmin jsExecutorAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin otaAdmin; |
|||
private final TbQueueAdmin edgeAdmin; |
|||
|
|||
public AwsSqsTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbAwsSqsSettings sqsSettings, |
|||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|||
TbQueueEdgeSettings edgeSettings) { |
|||
this.topicService = topicService; |
|||
this.coreSettings = coreSettings; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.sqsSettings = sqsSettings; |
|||
this.jsInvokeSettings = jsInvokeSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.edgeSettings = edgeSettings; |
|||
|
|||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|||
this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); |
|||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|||
this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); |
|||
this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|||
return new TbAwsSqsConsumerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(configuration.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
@Bean |
|||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbAwsSqsProducerTemplate<>(jsExecutorAdmin, sqsSettings, jsInvokeSettings.getRequestTopic()); |
|||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbAwsSqsConsumerTemplate<>(jsExecutorAdmin, sqsSettings, |
|||
jsInvokeSettings.getResponseTopic() + "_" + serviceInfoProvider.getServiceId(), |
|||
msg -> { |
|||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|||
}); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|||
builder.queueAdmin(jsExecutorAdmin); |
|||
builder.requestTemplate(producer); |
|||
builder.responseTemplate(consumer); |
|||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|||
return builder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
if (jsExecutorAdmin != null) { |
|||
jsExecutorAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (otaAdmin != null) { |
|||
otaAdmin.destroy(); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -1,98 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-vc-executor'") |
|||
public class AwsSqsTbVersionControlQueueFactory implements TbVersionControlQueueFactory { |
|||
|
|||
private final TbAwsSqsSettings sqsSettings; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbQueueVersionControlSettings vcSettings; |
|||
private final TopicService topicService; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin vcAdmin; |
|||
|
|||
public AwsSqsTbVersionControlQueueFactory(TbAwsSqsSettings sqsSettings, |
|||
TbQueueCoreSettings coreSettings, |
|||
TbQueueVersionControlSettings vcSettings, |
|||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|||
TopicService topicService |
|||
) { |
|||
this.sqsSettings = sqsSettings; |
|||
this.coreSettings = coreSettings; |
|||
this.vcSettings = vcSettings; |
|||
this.topicService = topicService; |
|||
|
|||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|||
this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|||
); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (vcAdmin != null) { |
|||
vcAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,153 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import jakarta.annotation.PreDestroy; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") |
|||
@Slf4j |
|||
public class AwsSqsTransportQueueFactory implements TbTransportQueueFactory { |
|||
private final TbQueueTransportApiSettings transportApiSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TbAwsSqsSettings sqsSettings; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TopicService topicService; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin transportApiAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
|
|||
public AwsSqsTransportQueueFactory(TbQueueTransportApiSettings transportApiSettings, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|||
TbAwsSqsSettings sqsSettings, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbQueueCoreSettings coreSettings, |
|||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TopicService topicService) { |
|||
this.transportApiSettings = transportApiSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.sqsSettings = sqsSettings; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.coreSettings = coreSettings; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.topicService = topicService; |
|||
|
|||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|||
this.transportApiAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getTransportApiAttributes()); |
|||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiRequestTemplate() { |
|||
TbQueueProducer<TbProtoQueueMsg<TransportApiRequestMsg>> producerTemplate = |
|||
new TbAwsSqsProducerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic())); |
|||
|
|||
TbQueueConsumer<TbProtoQueueMsg<TransportApiResponseMsg>> consumerTemplate = |
|||
new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, |
|||
topicService.buildTopicName(transportApiSettings.getResponsesTopic() + "_" + serviceInfoProvider.getServiceId()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiResponseMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> templateBuilder = DefaultTbQueueRequestTemplate.builder(); |
|||
templateBuilder.queueAdmin(transportApiAdmin); |
|||
templateBuilder.requestTemplate(producerTemplate); |
|||
templateBuilder.responseTemplate(consumerTemplate); |
|||
templateBuilder.maxPendingRequests(transportApiSettings.getMaxPendingRequests()); |
|||
templateBuilder.maxRequestTimeout(transportApiSettings.getMaxRequestsTimeout()); |
|||
templateBuilder.pollInterval(transportApiSettings.getResponsePollInterval()); |
|||
return templateBuilder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsConsumer() { |
|||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic() + "_" + serviceInfoProvider.getServiceId()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToTransportMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (transportApiAdmin != null) { |
|||
transportApiAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,315 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import com.google.protobuf.util.JsonFormat; |
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.queue.Queue; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='monolith'") |
|||
public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory, TbVersionControlQueueFactory { |
|||
|
|||
private final TbPubSubSettings pubSubSettings; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TbQueueTransportApiSettings transportApiSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TopicService topicService; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|||
private final TbQueueVersionControlSettings vcSettings; |
|||
private final TbQueueEdgeSettings edgeSettings; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
private final TbQueueAdmin jsExecutorAdmin; |
|||
private final TbQueueAdmin transportApiAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin vcAdmin; |
|||
private final TbQueueAdmin edgeAdmin; |
|||
|
|||
public PubSubMonolithQueueFactory(TbPubSubSettings pubSubSettings, |
|||
TbQueueCoreSettings coreSettings, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TbQueueTransportApiSettings transportApiSettings, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|||
TopicService topicService, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings, |
|||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|||
TbQueueVersionControlSettings vcSettings, |
|||
TbQueueEdgeSettings edgeSettings) { |
|||
this.pubSubSettings = pubSubSettings; |
|||
this.coreSettings = coreSettings; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.transportApiSettings = transportApiSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.topicService = topicService; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.vcSettings = vcSettings; |
|||
this.edgeSettings = edgeSettings; |
|||
|
|||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|||
this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); |
|||
this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); |
|||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|||
this.vcAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getVcSettings()); |
|||
this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); |
|||
|
|||
this.jsInvokeSettings = jsInvokeSettings; |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|||
); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|||
return new TbPubSubConsumerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(configuration.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|||
return new TbPubSubProducerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|||
} |
|||
|
|||
@Override |
|||
@Bean |
|||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|||
TbQueueProducer<TbProtoJsQueueMsg<RemoteJsRequest>> producer = new TbPubSubProducerTemplate<>(jsExecutorAdmin, pubSubSettings, jsInvokeSettings.getRequestTopic()); |
|||
TbQueueConsumer<TbProtoQueueMsg<RemoteJsResponse>> consumer = new TbPubSubConsumerTemplate<>(jsExecutorAdmin, pubSubSettings, |
|||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|||
msg -> { |
|||
RemoteJsResponse.Builder builder = RemoteJsResponse.newBuilder(); |
|||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|||
}); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|||
builder.queueAdmin(jsExecutorAdmin); |
|||
builder.requestTemplate(producer); |
|||
builder.responseTemplate(consumer); |
|||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|||
return builder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|||
return null; |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
if (jsExecutorAdmin != null) { |
|||
jsExecutorAdmin.destroy(); |
|||
} |
|||
if (transportApiAdmin != null) { |
|||
transportApiAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (vcAdmin != null) { |
|||
vcAdmin.destroy(); |
|||
} |
|||
if (edgeAdmin != null) { |
|||
edgeAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,278 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import com.google.protobuf.util.JsonFormat; |
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='tb-core'") |
|||
public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { |
|||
|
|||
private final TbPubSubSettings pubSubSettings; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbQueueTransportApiSettings transportApiSettings; |
|||
private final TopicService topicService; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TbQueueEdgeSettings edgeSettings; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin jsExecutorAdmin; |
|||
private final TbQueueAdmin transportApiAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
private final TbQueueAdmin edgeAdmin; |
|||
|
|||
public PubSubTbCoreQueueFactory(TbPubSubSettings pubSubSettings, |
|||
TbQueueCoreSettings coreSettings, |
|||
TbQueueTransportApiSettings transportApiSettings, |
|||
TopicService topicService, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TbQueueEdgeSettings edgeSettings, |
|||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings) { |
|||
this.pubSubSettings = pubSubSettings; |
|||
this.coreSettings = coreSettings; |
|||
this.transportApiSettings = transportApiSettings; |
|||
this.topicService = topicService; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.jsInvokeSettings = jsInvokeSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.edgeSettings = edgeSettings; |
|||
|
|||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|||
this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); |
|||
this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); |
|||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|||
this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|||
return new TbPubSubProducerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|||
} |
|||
|
|||
@Override |
|||
@Bean |
|||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbPubSubProducerTemplate<>(jsExecutorAdmin, pubSubSettings, jsInvokeSettings.getRequestTopic()); |
|||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbPubSubConsumerTemplate<>(jsExecutorAdmin, pubSubSettings, |
|||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|||
msg -> { |
|||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|||
}); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|||
builder.queueAdmin(jsExecutorAdmin); |
|||
builder.requestTemplate(producer); |
|||
builder.responseTemplate(consumer); |
|||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|||
return builder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|||
//TODO: version-control
|
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (jsExecutorAdmin != null) { |
|||
jsExecutorAdmin.destroy(); |
|||
} |
|||
if (transportApiAdmin != null) { |
|||
transportApiAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
if (edgeAdmin != null) { |
|||
edgeAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,209 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.queue.provider; |
|||
|
|||
import com.google.protobuf.util.JsonFormat; |
|||
import jakarta.annotation.PreDestroy; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.queue.Queue; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|||
import org.thingsboard.server.queue.TbQueueAdmin; |
|||
import org.thingsboard.server.queue.TbQueueConsumer; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|||
import org.thingsboard.server.queue.discovery.TopicService; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Component |
|||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='tb-rule-engine'") |
|||
public class PubSubTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { |
|||
|
|||
private final TbPubSubSettings pubSubSettings; |
|||
private final TbQueueCoreSettings coreSettings; |
|||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|||
private final TopicService topicService; |
|||
private final TbServiceInfoProvider serviceInfoProvider; |
|||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|||
private final TbQueueEdgeSettings edgeSettings; |
|||
|
|||
private final TbQueueAdmin coreAdmin; |
|||
private final TbQueueAdmin ruleEngineAdmin; |
|||
private final TbQueueAdmin jsExecutorAdmin; |
|||
private final TbQueueAdmin notificationAdmin; |
|||
private final TbQueueAdmin edgeAdmin; |
|||
|
|||
public PubSubTbRuleEngineQueueFactory(TbPubSubSettings pubSubSettings, |
|||
TbQueueCoreSettings coreSettings, |
|||
TbQueueRuleEngineSettings ruleEngineSettings, |
|||
TopicService topicService, |
|||
TbServiceInfoProvider serviceInfoProvider, |
|||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings, |
|||
TbQueueEdgeSettings edgeSettings) { |
|||
this.pubSubSettings = pubSubSettings; |
|||
this.coreSettings = coreSettings; |
|||
this.ruleEngineSettings = ruleEngineSettings; |
|||
this.topicService = topicService; |
|||
this.serviceInfoProvider = serviceInfoProvider; |
|||
this.jsInvokeSettings = jsInvokeSettings; |
|||
this.transportNotificationSettings = transportNotificationSettings; |
|||
this.edgeSettings = edgeSettings; |
|||
|
|||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|||
this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); |
|||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|||
this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|||
return new TbPubSubConsumerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(configuration.getTopic()), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|||
} |
|||
|
|||
@Override |
|||
@Bean |
|||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbPubSubProducerTemplate<>(jsExecutorAdmin, pubSubSettings, jsInvokeSettings.getRequestTopic()); |
|||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbPubSubConsumerTemplate<>(jsExecutorAdmin, pubSubSettings, |
|||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|||
msg -> { |
|||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|||
}); |
|||
|
|||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|||
builder.queueAdmin(jsExecutorAdmin); |
|||
builder.requestTemplate(producer); |
|||
builder.responseTemplate(consumer); |
|||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|||
return builder.build(); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|||
} |
|||
|
|||
@Override |
|||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|||
} |
|||
|
|||
@PreDestroy |
|||
private void destroy() { |
|||
if (coreAdmin != null) { |
|||
coreAdmin.destroy(); |
|||
} |
|||
if (ruleEngineAdmin != null) { |
|||
ruleEngineAdmin.destroy(); |
|||
} |
|||
if (jsExecutorAdmin != null) { |
|||
jsExecutorAdmin.destroy(); |
|||
} |
|||
if (notificationAdmin != null) { |
|||
notificationAdmin.destroy(); |
|||
} |
|||
} |
|||
} |
|||