Commit ae91c85e1b802f242f3d5a13e944809131caaef5
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
54 changed files
with
1608 additions
and
1386 deletions
Too many changes to show.
To preserve performance only 54 of 659 files are displayed.
@@ -2,6 +2,7 @@ before_install: | @@ -2,6 +2,7 @@ before_install: | ||
2 | - sudo rm -f /etc/mavenrc | 2 | - sudo rm -f /etc/mavenrc |
3 | - export M2_HOME=/usr/local/maven | 3 | - export M2_HOME=/usr/local/maven |
4 | - export MAVEN_OPTS="-Dmaven.repo.local=$HOME/.m2/repository -Xms1024m -Xmx3072m" | 4 | - export MAVEN_OPTS="-Dmaven.repo.local=$HOME/.m2/repository -Xms1024m -Xmx3072m" |
5 | + - export HTTP_LOG_CONTROLLER_ERROR_STACK_TRACE=false | ||
5 | jdk: | 6 | jdk: |
6 | - oraclejdk8 | 7 | - oraclejdk8 |
7 | language: java | 8 | language: java |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.1.1-SNAPSHOT</version> | 23 | + <version>2.2.0-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>application</artifactId> | 26 | <artifactId>application</artifactId> |
@@ -57,26 +57,30 @@ | @@ -57,26 +57,30 @@ | ||
57 | <artifactId>rule-engine-components</artifactId> | 57 | <artifactId>rule-engine-components</artifactId> |
58 | </dependency> | 58 | </dependency> |
59 | <dependency> | 59 | <dependency> |
60 | - <groupId>org.thingsboard.common</groupId> | ||
61 | - <artifactId>transport</artifactId> | 60 | + <groupId>org.thingsboard.common.transport</groupId> |
61 | + <artifactId>transport-api</artifactId> | ||
62 | </dependency> | 62 | </dependency> |
63 | <dependency> | 63 | <dependency> |
64 | - <groupId>org.thingsboard.transport</groupId> | ||
65 | - <artifactId>http</artifactId> | 64 | + <groupId>org.thingsboard.common.transport</groupId> |
65 | + <artifactId>mqtt</artifactId> | ||
66 | </dependency> | 66 | </dependency> |
67 | <dependency> | 67 | <dependency> |
68 | - <groupId>org.thingsboard.transport</groupId> | ||
69 | - <artifactId>coap</artifactId> | 68 | + <groupId>org.thingsboard.common.transport</groupId> |
69 | + <artifactId>http</artifactId> | ||
70 | </dependency> | 70 | </dependency> |
71 | <dependency> | 71 | <dependency> |
72 | - <groupId>org.thingsboard.transport</groupId> | ||
73 | - <artifactId>mqtt</artifactId> | 72 | + <groupId>org.thingsboard.common.transport</groupId> |
73 | + <artifactId>coap</artifactId> | ||
74 | </dependency> | 74 | </dependency> |
75 | <dependency> | 75 | <dependency> |
76 | <groupId>org.thingsboard</groupId> | 76 | <groupId>org.thingsboard</groupId> |
77 | <artifactId>dao</artifactId> | 77 | <artifactId>dao</artifactId> |
78 | </dependency> | 78 | </dependency> |
79 | <dependency> | 79 | <dependency> |
80 | + <groupId>org.thingsboard.common</groupId> | ||
81 | + <artifactId>queue</artifactId> | ||
82 | + </dependency> | ||
83 | + <dependency> | ||
80 | <groupId>org.thingsboard</groupId> | 84 | <groupId>org.thingsboard</groupId> |
81 | <artifactId>dao</artifactId> | 85 | <artifactId>dao</artifactId> |
82 | <type>test-jar</type> | 86 | <type>test-jar</type> |
@@ -538,7 +542,8 @@ | @@ -538,7 +542,8 @@ | ||
538 | <args> | 542 | <args> |
539 | <arg>-PprojectBuildDir=${project.build.directory}</arg> | 543 | <arg>-PprojectBuildDir=${project.build.directory}</arg> |
540 | <arg>-PprojectVersion=${project.version}</arg> | 544 | <arg>-PprojectVersion=${project.version}</arg> |
541 | - <arg>-PmainJar=${project.build.directory}/${project.build.finalName}-boot.${project.packaging}</arg> | 545 | + <arg>-PmainJar=${project.build.directory}/${project.build.finalName}-boot.${project.packaging} |
546 | + </arg> | ||
542 | <arg>-PpkgName=${pkg.name}</arg> | 547 | <arg>-PpkgName=${pkg.name}</arg> |
543 | <arg>-PpkgInstallFolder=${pkg.installFolder}</arg> | 548 | <arg>-PpkgInstallFolder=${pkg.installFolder}</arg> |
544 | <arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg> | 549 | <arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg> |
@@ -573,6 +578,27 @@ | @@ -573,6 +578,27 @@ | ||
573 | </executions> | 578 | </executions> |
574 | </plugin> | 579 | </plugin> |
575 | <plugin> | 580 | <plugin> |
581 | + <groupId>org.apache.maven.plugins</groupId> | ||
582 | + <artifactId>maven-install-plugin</artifactId> | ||
583 | + <configuration> | ||
584 | + <file>${project.build.directory}/${pkg.name}.deb</file> | ||
585 | + <artifactId>${project.artifactId}</artifactId> | ||
586 | + <groupId>${project.groupId}</groupId> | ||
587 | + <version>${project.version}</version> | ||
588 | + <classifier>deb</classifier> | ||
589 | + <packaging>deb</packaging> | ||
590 | + </configuration> | ||
591 | + <executions> | ||
592 | + <execution> | ||
593 | + <id>install-deb</id> | ||
594 | + <phase>package</phase> | ||
595 | + <goals> | ||
596 | + <goal>install-file</goal> | ||
597 | + </goals> | ||
598 | + </execution> | ||
599 | + </executions> | ||
600 | + </plugin> | ||
601 | + <plugin> | ||
576 | <groupId>org.xolstice.maven.plugins</groupId> | 602 | <groupId>org.xolstice.maven.plugins</groupId> |
577 | <artifactId>protobuf-maven-plugin</artifactId> | 603 | <artifactId>protobuf-maven-plugin</artifactId> |
578 | </plugin> | 604 | </plugin> |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | "resources": [], | 15 | "resources": [], |
16 | "templateHtml": "", | 16 | "templateHtml": "", |
17 | "templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n margin: 5px;\n padding: 8px;\n}\n\n.tbDatasource-title {\n font-size: 1.200rem;\n font-weight: 500;\n padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n width: 100%;\n box-shadow: 0 0 10px #ccc;\n border-collapse: collapse;\n white-space: nowrap;\n font-size: 1.000rem;\n color: #757575;\n}\n\n.tbDatasource-table td {\n position: relative;\n border-top: 1px solid rgba(0, 0, 0, 0.12);\n border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n padding: 0px 18px;\n box-sizing: border-box;\n}", | 17 | "templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n margin: 5px;\n padding: 8px;\n}\n\n.tbDatasource-title {\n font-size: 1.200rem;\n font-weight: 500;\n padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n width: 100%;\n box-shadow: 0 0 10px #ccc;\n border-collapse: collapse;\n white-space: nowrap;\n font-size: 1.000rem;\n color: #757575;\n}\n\n.tbDatasource-table td {\n position: relative;\n border-top: 1px solid rgba(0, 0, 0, 0.12);\n border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n padding: 0px 18px;\n box-sizing: border-box;\n}", |
18 | - "controllerScript": "self.onInit = function() {\n \n self.ctx.datasourceTitleCells = [];\n self.ctx.valueCells = [];\n self.ctx.labelCells = [];\n \n for (var i=0; i < self.ctx.datasources.length; i++) {\n var tbDatasource = self.ctx.datasources[i];\n\n var datasourceId = 'tbDatasource' + i;\n self.ctx.$container.append(\n \"<div id='\" + datasourceId +\n \"' class='tbDatasource-container'></div>\"\n );\n\n var datasourceContainer = $('#' + datasourceId,\n self.ctx.$container);\n\n datasourceContainer.append(\n \"<div class='tbDatasource-title'>\" +\n tbDatasource.name + \"</div>\"\n );\n \n var datasourceTitleCell = $('.tbDatasource-title', datasourceContainer);\n self.ctx.datasourceTitleCells.push(datasourceTitleCell);\n \n var tableId = 'table' + i;\n datasourceContainer.append(\n \"<table id='\" + tableId +\n \"' class='tbDatasource-table'><col width='30%'><col width='70%'></table>\"\n );\n var table = $('#' + tableId, self.ctx.$container);\n\n for (var a = 0; a < tbDatasource.dataKeys.length; a++) {\n var dataKey = tbDatasource.dataKeys[a];\n var labelCellId = 'labelCell' + a;\n var cellId = 'cell' + a;\n table.append(\"<tr><td id='\" + labelCellId + \"'>\" + dataKey.label +\n \"</td><td id='\" + cellId +\n \"'></td></tr>\");\n var labelCell = $('#' + labelCellId, table);\n self.ctx.labelCells.push(labelCell);\n var valueCell = $('#' + cellId, table);\n self.ctx.valueCells.push(valueCell);\n }\n } \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.valueCells.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData && cellData.data && cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length -\n 1];\n var value = tvPair[1];\n self.ctx.valueCells[i].html(value);\n }\n } \n}\n\nself.onResize = function() {\n var datasoirceTitleFontSize = self.ctx.height/8;\n if (self.ctx.width/self.ctx.height <= 1.5) {\n datasoirceTitleFontSize = self.ctx.width/12;\n }\n datasoirceTitleFontSize = Math.min(datasoirceTitleFontSize, 20);\n for (var i = 0; i < self.ctx.datasourceTitleCells.length; i++) {\n self.ctx.datasourceTitleCells[i].css('font-size', datasoirceTitleFontSize+'px');\n }\n var valueFontSize = self.ctx.height/9;\n var labelFontSize = self.ctx.height/9;\n if (self.ctx.width/self.ctx.height <= 1.5) {\n valueFontSize = self.ctx.width/15;\n labelFontSize = self.ctx.width/15;\n }\n valueFontSize = Math.min(valueFontSize, 18);\n labelFontSize = Math.min(labelFontSize, 18);\n\n for (i = 0; i < self.ctx.valueCells; i++) {\n self.ctx.valueCells[i].css('font-size', valueFontSize+'px');\n self.ctx.valueCells[i].css('height', valueFontSize*2.5+'px');\n self.ctx.valueCells[i].css('padding', '0px ' + valueFontSize + 'px');\n self.ctx.labelCells[i].css('font-size', labelFontSize+'px');\n self.ctx.labelCells[i].css('height', labelFontSize*2.5+'px');\n self.ctx.labelCells[i].css('padding', '0px ' + labelFontSize + 'px');\n } \n}\n\nself.onDestroy = function() {\n}\n", | 18 | + "controllerScript": "self.onInit = function() {\n \n self.ctx.datasourceTitleCells = [];\n self.ctx.valueCells = [];\n self.ctx.labelCells = [];\n \n for (var i=0; i < self.ctx.datasources.length; i++) {\n var tbDatasource = self.ctx.datasources[i];\n\n var datasourceId = 'tbDatasource' + i;\n self.ctx.$container.append(\n \"<div id='\" + datasourceId +\n \"' class='tbDatasource-container'></div>\"\n );\n\n var datasourceContainer = $('#' + datasourceId,\n self.ctx.$container);\n\n datasourceContainer.append(\n \"<div class='tbDatasource-title'>\" +\n tbDatasource.name + \"</div>\"\n );\n \n var datasourceTitleCell = $('.tbDatasource-title', datasourceContainer);\n self.ctx.datasourceTitleCells.push(datasourceTitleCell);\n \n var tableId = 'table' + i;\n datasourceContainer.append(\n \"<table id='\" + tableId +\n \"' class='tbDatasource-table'><col width='30%'><col width='70%'></table>\"\n );\n var table = $('#' + tableId, self.ctx.$container);\n\n for (var a = 0; a < tbDatasource.dataKeys.length; a++) {\n var dataKey = tbDatasource.dataKeys[a];\n var labelCellId = 'labelCell' + a;\n var cellId = 'cell' + a;\n table.append(\"<tr><td id='\" + labelCellId + \"'>\" + dataKey.label +\n \"</td><td id='\" + cellId +\n \"'></td></tr>\");\n var labelCell = $('#' + labelCellId, table);\n self.ctx.labelCells.push(labelCell);\n var valueCell = $('#' + cellId, table);\n self.ctx.valueCells.push(valueCell);\n }\n } \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.valueCells.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData && cellData.data && cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length -\n 1];\n var value = tvPair[1];\n var textValue;\n //toDo -> + IsNumber\n \n if (isNumber(value)) {\n var decimals = self.ctx.decimals;\n var units = self.ctx.units;\n if (cellData.dataKey.decimals || cellData.dataKey.decimals === 0) {\n decimals = cellData.dataKey.decimals;\n }\n if (cellData.dataKey.units) {\n units = cellData.dataKey.units;\n }\n txtValue = self.ctx.utils.formatValue(value, decimals, units, true);\n } else {\n txtValue = value;\n }\n self.ctx.valueCells[i].html(txtValue);\n }\n }\n \n function isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n}\n\nself.onResize = function() {\n var datasoirceTitleFontSize = self.ctx.height/8;\n if (self.ctx.width/self.ctx.height <= 1.5) {\n datasoirceTitleFontSize = self.ctx.width/12;\n }\n datasoirceTitleFontSize = Math.min(datasoirceTitleFontSize, 20);\n for (var i = 0; i < self.ctx.datasourceTitleCells.length; i++) {\n self.ctx.datasourceTitleCells[i].css('font-size', datasoirceTitleFontSize+'px');\n }\n var valueFontSize = self.ctx.height/9;\n var labelFontSize = self.ctx.height/9;\n if (self.ctx.width/self.ctx.height <= 1.5) {\n valueFontSize = self.ctx.width/15;\n labelFontSize = self.ctx.width/15;\n }\n valueFontSize = Math.min(valueFontSize, 18);\n labelFontSize = Math.min(labelFontSize, 18);\n\n for (i = 0; i < self.ctx.valueCells; i++) {\n self.ctx.valueCells[i].css('font-size', valueFontSize+'px');\n self.ctx.valueCells[i].css('height', valueFontSize*2.5+'px');\n self.ctx.valueCells[i].css('padding', '0px ' + valueFontSize + 'px');\n self.ctx.labelCells[i].css('font-size', labelFontSize+'px');\n self.ctx.labelCells[i].css('height', labelFontSize*2.5+'px');\n self.ctx.labelCells[i].css('padding', '0px ' + labelFontSize + 'px');\n } \n}\n\nself.onDestroy = function() {\n}\n", |
19 | "settingsSchema": "{}", | 19 | "settingsSchema": "{}", |
20 | "dataKeySettingsSchema": "{}\n", | 20 | "dataKeySettingsSchema": "{}\n", |
21 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"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\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Attributes card\"}" | 21 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"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\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Attributes card\"}" |
@@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
27 | "descriptor": { | 27 | "descriptor": { |
28 | "type": "latest", | 28 | "type": "latest", |
29 | "sizeX": 7.5, | 29 | "sizeX": 7.5, |
30 | - "sizeY": 4.5, | 30 | + "sizeY": 6.5, |
31 | "resources": [], | 31 | "resources": [], |
32 | "templateHtml": "<tb-entities-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-entities-table-widget>", | 32 | "templateHtml": "<tb-entities-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-entities-table-widget>", |
33 | "templateCss": "", | 33 | "templateCss": "", |
@@ -95,7 +95,7 @@ | @@ -95,7 +95,7 @@ | ||
95 | "resources": [], | 95 | "resources": [], |
96 | "templateHtml": "", | 96 | "templateHtml": "", |
97 | "templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n.tbDatasource-table {\n width: 100%;\n height: 100%;\n border-collapse: collapse;\n white-space: nowrap;\n font-weight: 100;\n text-align: right;\n}\n\n.tbDatasource-table td {\n padding: 12px;\n position: relative;\n box-sizing: border-box;\n}\n\n.tbDatasource-data-key {\n opacity: 0.7;\n font-weight: 400;\n font-size: 3.500rem;\n}\n\n.tbDatasource-value {\n font-size: 5.000rem;\n}", | 97 | "templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n.tbDatasource-table {\n width: 100%;\n height: 100%;\n border-collapse: collapse;\n white-space: nowrap;\n font-weight: 100;\n text-align: right;\n}\n\n.tbDatasource-table td {\n padding: 12px;\n position: relative;\n box-sizing: border-box;\n}\n\n.tbDatasource-data-key {\n opacity: 0.7;\n font-weight: 400;\n font-size: 3.500rem;\n}\n\n.tbDatasource-value {\n font-size: 5.000rem;\n}", |
98 | - "controllerScript": "self.onInit = function() {\n\n self.ctx.labelPosition = self.ctx.settings.labelPosition || 'left';\n \n if (self.ctx.datasources.length > 0) {\n var tbDatasource = self.ctx.datasources[0];\n var datasourceId = 'tbDatasource' + 0;\n self.ctx.$container.append(\n \"<div id='\" + datasourceId +\n \"' class='tbDatasource-container'></div>\"\n );\n \n self.ctx.datasourceContainer = $('#' + datasourceId,\n self.ctx.$container);\n \n var tableId = 'table' + 0;\n self.ctx.datasourceContainer.append(\n \"<table id='\" + tableId +\n \"' class='tbDatasource-table'><col width='30%'><col width='70%'></table>\"\n );\n var table = $('#' + tableId, self.ctx.$container);\n if (self.ctx.labelPosition === 'top') {\n table.css('text-align', 'left');\n }\n \n if (tbDatasource.dataKeys.length > 0) {\n var dataKey = tbDatasource.dataKeys[0];\n var labelCellId = 'labelCell' + 0;\n var cellId = 'cell' + 0;\n if (self.ctx.labelPosition === 'left') {\n table.append(\n \"<tr><td class='tbDatasource-data-key' id='\" + labelCellId +\"'>\" +\n dataKey.label +\n \"</td><td class='tbDatasource-value' id='\" +\n cellId +\n \"'></td></tr>\");\n } else {\n table.append(\n \"<tr style='vertical-align: bottom;'><td class='tbDatasource-data-key' id='\" + labelCellId +\"'>\" +\n dataKey.label +\n \"</td></tr><tr><td class='tbDatasource-value' id='\" +\n cellId +\n \"'></td></tr>\");\n }\n self.ctx.labelCell = $('#' + labelCellId, table);\n self.ctx.valueCell = $('#' + cellId, table);\n self.ctx.valueCell.html(0 + ' ' + self.ctx.units);\n }\n }\n \n $.fn.textWidth = function(){\n var html_org = $(this).html();\n var html_calc = '<span>' + html_org + '</span>';\n $(this).html(html_calc);\n var width = $(this).find('span:first').width();\n $(this).html(html_org);\n return width;\n }; \n \n self.onResize();\n};\n\nself.onDataUpdated = function() {\n \n function isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n if (self.ctx.valueCell && self.ctx.data.length > 0) {\n var cellData = self.ctx.data[0];\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length -\n 1];\n var value = tvPair[1];\n var txtValue;\n if (isNumber(value)) {\n txtValue = self.ctx.utils.formatValue(value, self.ctx.decimals, self.ctx.units);\n } else {\n txtValue = value;\n }\n self.ctx.valueCell.html(txtValue);\n var targetWidth;\n var minDelta;\n if (self.ctx.labelPosition === 'left') {\n targetWidth = self.ctx.datasourceContainer.width() - self.ctx.labelCell.width();\n minDelta = self.ctx.width/16 + self.ctx.padding;\n } else {\n targetWidth = self.ctx.datasourceContainer.width();\n minDelta = self.ctx.padding;\n }\n var delta = targetWidth - self.ctx.valueCell.textWidth();\n var fontSize = self.ctx.valueFontSize;\n if (targetWidth > minDelta) {\n while (delta < minDelta && fontSize > 6) {\n fontSize--;\n self.ctx.valueCell.css('font-size', fontSize+'px');\n delta = targetWidth - self.ctx.valueCell.textWidth();\n }\n }\n }\n } \n \n};\n\nself.onResize = function() {\n var labelFontSize;\n if (self.ctx.labelPosition === 'top') {\n self.ctx.padding = self.ctx.height/20;\n labelFontSize = self.ctx.height/4;\n self.ctx.valueFontSize = self.ctx.height/2;\n } else {\n self.ctx.padding = self.ctx.width/50;\n labelFontSize = self.ctx.height/2.5;\n self.ctx.valueFontSize = self.ctx.height/2;\n if (self.ctx.width/self.ctx.height <= 2.7) {\n labelFontSize = self.ctx.width/7;\n self.ctx.valueFontSize = self.ctx.width/6;\n }\n }\n self.ctx.padding = Math.min(12, self.ctx.padding);\n \n if (self.ctx.labelCell) {\n self.ctx.labelCell.css('font-size', labelFontSize+'px');\n self.ctx.labelCell.css('padding', self.ctx.padding+'px');\n }\n if (self.ctx.valueCell) {\n self.ctx.valueCell.css('font-size', self.ctx.valueFontSize+'px');\n self.ctx.valueCell.css('padding', self.ctx.padding+'px');\n } \n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n };\n};\n\n\nself.onDestroy = function() {\n};\n", | 98 | + "controllerScript": "self.onInit = function() {\n\n self.ctx.labelPosition = self.ctx.settings.labelPosition || 'left';\n \n if (self.ctx.datasources.length > 0) {\n var tbDatasource = self.ctx.datasources[0];\n var datasourceId = 'tbDatasource' + 0;\n self.ctx.$container.append(\n \"<div id='\" + datasourceId +\n \"' class='tbDatasource-container'></div>\"\n );\n \n self.ctx.datasourceContainer = $('#' + datasourceId,\n self.ctx.$container);\n \n var tableId = 'table' + 0;\n self.ctx.datasourceContainer.append(\n \"<table id='\" + tableId +\n \"' class='tbDatasource-table'><col width='30%'><col width='70%'></table>\"\n );\n var table = $('#' + tableId, self.ctx.$container);\n if (self.ctx.labelPosition === 'top') {\n table.css('text-align', 'left');\n }\n \n if (tbDatasource.dataKeys.length > 0) {\n var dataKey = tbDatasource.dataKeys[0];\n var labelCellId = 'labelCell' + 0;\n var cellId = 'cell' + 0;\n if (self.ctx.labelPosition === 'left') {\n table.append(\n \"<tr><td class='tbDatasource-data-key' id='\" + labelCellId +\"'>\" +\n dataKey.label +\n \"</td><td class='tbDatasource-value' id='\" +\n cellId +\n \"'></td></tr>\");\n } else {\n table.append(\n \"<tr style='vertical-align: bottom;'><td class='tbDatasource-data-key' id='\" + labelCellId +\"'>\" +\n dataKey.label +\n \"</td></tr><tr><td class='tbDatasource-value' id='\" +\n cellId +\n \"'></td></tr>\");\n }\n self.ctx.labelCell = $('#' + labelCellId, table);\n self.ctx.valueCell = $('#' + cellId, table);\n self.ctx.valueCell.html(0 + ' ' + self.ctx.units);\n }\n }\n \n $.fn.textWidth = function(){\n var html_org = $(this).html();\n var html_calc = '<span>' + html_org + '</span>';\n $(this).html(html_calc);\n var width = $(this).find('span:first').width();\n $(this).html(html_org);\n return width;\n }; \n \n self.onResize();\n};\n\nself.onDataUpdated = function() {\n \n function isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n if (self.ctx.valueCell && self.ctx.data.length > 0) {\n var cellData = self.ctx.data[0];\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length -\n 1];\n var value = tvPair[1];\n var txtValue;\n if (isNumber(value)) {\n var decimals = self.ctx.decimals;\n var units = self.ctx.units;\n if (self.ctx.datasources.length > 0 && self.ctx.datasources[0].dataKeys.length > 0) {\n dataKey = self.ctx.datasources[0].dataKeys[0];\n if (dataKey.decimals || dataKey.decimals === 0) {\n decimals = dataKey.decimals;\n }\n if (dataKey.units) {\n units = dataKey.units;\n }\n }\n txtValue = self.ctx.utils.formatValue(value, decimals, units, true);\n } else {\n txtValue = value;\n }\n self.ctx.valueCell.html(txtValue);\n var targetWidth;\n var minDelta;\n if (self.ctx.labelPosition === 'left') {\n targetWidth = self.ctx.datasourceContainer.width() - self.ctx.labelCell.width();\n minDelta = self.ctx.width/16 + self.ctx.padding;\n } else {\n targetWidth = self.ctx.datasourceContainer.width();\n minDelta = self.ctx.padding;\n }\n var delta = targetWidth - self.ctx.valueCell.textWidth();\n var fontSize = self.ctx.valueFontSize;\n if (targetWidth > minDelta) {\n while (delta < minDelta && fontSize > 6) {\n fontSize--;\n self.ctx.valueCell.css('font-size', fontSize+'px');\n delta = targetWidth - self.ctx.valueCell.textWidth();\n }\n }\n }\n } \n \n};\n\nself.onResize = function() {\n var labelFontSize;\n if (self.ctx.labelPosition === 'top') {\n self.ctx.padding = self.ctx.height/20;\n labelFontSize = self.ctx.height/4;\n self.ctx.valueFontSize = self.ctx.height/2;\n } else {\n self.ctx.padding = self.ctx.width/50;\n labelFontSize = self.ctx.height/2.5;\n self.ctx.valueFontSize = self.ctx.height/2;\n if (self.ctx.width/self.ctx.height <= 2.7) {\n labelFontSize = self.ctx.width/7;\n self.ctx.valueFontSize = self.ctx.width/6;\n }\n }\n self.ctx.padding = Math.min(12, self.ctx.padding);\n \n if (self.ctx.labelCell) {\n self.ctx.labelCell.css('font-size', labelFontSize+'px');\n self.ctx.labelCell.css('padding', self.ctx.padding+'px');\n }\n if (self.ctx.valueCell) {\n self.ctx.valueCell.css('font-size', self.ctx.valueFontSize+'px');\n self.ctx.valueCell.css('padding', self.ctx.padding+'px');\n } \n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n };\n};\n\n\nself.onDestroy = function() {\n};\n", |
99 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"labelPosition\": {\n \"title\": \"Label position\",\n \"type\": \"string\",\n \"default\": \"left\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"labelPosition\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"left\",\n \"label\": \"Left\"\n },\n {\n \"value\": \"top\",\n \"label\": \"Top\"\n }\n ]\n }\n ]\n}", | 99 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"labelPosition\": {\n \"title\": \"Label position\",\n \"type\": \"string\",\n \"default\": \"left\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"labelPosition\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"left\",\n \"label\": \"Left\"\n },\n {\n \"value\": \"top\",\n \"label\": \"Top\"\n }\n ]\n }\n ]\n}", |
100 | "dataKeySettingsSchema": "{}\n", | 100 | "dataKeySettingsSchema": "{}\n", |
101 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.2392660816082064,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ff5722\",\"color\":\"rgba(255, 255, 255, 0.87)\",\"padding\":\"16px\",\"settings\":{\"labelPosition\":\"top\"},\"title\":\"Simple card\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"units\":\"°C\",\"decimals\":0,\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{}}" | 101 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.2392660816082064,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ff5722\",\"color\":\"rgba(255, 255, 255, 0.87)\",\"padding\":\"16px\",\"settings\":{\"labelPosition\":\"top\"},\"title\":\"Simple card\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"units\":\"°C\",\"decimals\":0,\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{}}" |
@@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
35 | "resources": [], | 35 | "resources": [], |
36 | "templateHtml": "", | 36 | "templateHtml": "", |
37 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", | 37 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", |
38 | - "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", | 38 | + "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", |
39 | "settingsSchema": "{}", | 39 | "settingsSchema": "{}", |
40 | "dataKeySettingsSchema": "{}", | 40 | "dataKeySettingsSchema": "{}", |
41 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"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;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"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\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":false,\"tooltipIndividual\":false},\"title\":\"Timeseries - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}" | 41 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"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;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"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\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":false,\"tooltipIndividual\":false},\"title\":\"Timeseries - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}" |
@@ -147,10 +147,10 @@ | @@ -147,10 +147,10 @@ | ||
147 | "resources": [], | 147 | "resources": [], |
148 | "templateHtml": "", | 148 | "templateHtml": "", |
149 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", | 149 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", |
150 | - "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'bar'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(false);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", | 150 | + "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'bar'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('bar');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(false);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", |
151 | "settingsSchema": "{}", | 151 | "settingsSchema": "{}", |
152 | "dataKeySettingsSchema": "{}", | 152 | "dataKeySettingsSchema": "{}", |
153 | - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":true,\"tooltipIndividual\":false},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}" | 153 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":true,\"tooltipIndividual\":false,\"defaultBarWidth\":600},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{}}" |
154 | } | 154 | } |
155 | }, | 155 | }, |
156 | { | 156 | { |
@@ -163,7 +163,7 @@ | @@ -163,7 +163,7 @@ | ||
163 | "resources": [], | 163 | "resources": [], |
164 | "templateHtml": "", | 164 | "templateHtml": "", |
165 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", | 165 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", |
166 | - "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", | 166 | + "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", |
167 | "settingsSchema": "{}", | 167 | "settingsSchema": "{}", |
168 | "dataKeySettingsSchema": "{}", | 168 | "dataKeySettingsSchema": "{}", |
169 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" | 169 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" |
1 | +-- | ||
2 | +-- Copyright © 2016-2018 The Thingsboard Authors | ||
3 | +-- | ||
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +-- you may not use this file except in compliance with the License. | ||
6 | +-- You may obtain a copy of the License at | ||
7 | +-- | ||
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +-- | ||
10 | +-- Unless required by applicable law or agreed to in writing, software | ||
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +-- See the License for the specific language governing permissions and | ||
14 | +-- limitations under the License. | ||
15 | +-- | ||
16 | + | ||
17 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_name; | ||
18 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_search_text; | ||
19 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_customer; | ||
20 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_entity_id; | ||
21 | + | ||
22 | +DROP TABLE IF EXISTS thingsboard.entity_views; | ||
23 | + | ||
24 | +CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( | ||
25 | + id timeuuid, | ||
26 | + entity_id timeuuid, | ||
27 | + entity_type text, | ||
28 | + tenant_id timeuuid, | ||
29 | + customer_id timeuuid, | ||
30 | + name text, | ||
31 | + keys text, | ||
32 | + start_ts bigint, | ||
33 | + end_ts bigint, | ||
34 | + search_text text, | ||
35 | + additional_info text, | ||
36 | + PRIMARY KEY (id, entity_id, tenant_id, customer_id) | ||
37 | +); | ||
38 | + | ||
39 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_name AS | ||
40 | + SELECT * | ||
41 | + from thingsboard.entity_views | ||
42 | + WHERE tenant_id IS NOT NULL | ||
43 | + AND entity_id IS NOT NULL | ||
44 | + AND customer_id IS NOT NULL | ||
45 | + AND name IS NOT NULL | ||
46 | + AND id IS NOT NULL | ||
47 | + PRIMARY KEY (tenant_id, name, id, customer_id, entity_id) | ||
48 | + WITH CLUSTERING ORDER BY (name ASC, id DESC, customer_id DESC); | ||
49 | + | ||
50 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_search_text AS | ||
51 | + SELECT * | ||
52 | + from thingsboard.entity_views | ||
53 | + WHERE tenant_id IS NOT NULL | ||
54 | + AND entity_id IS NOT NULL | ||
55 | + AND customer_id IS NOT NULL | ||
56 | + AND search_text IS NOT NULL | ||
57 | + AND id IS NOT NULL | ||
58 | + PRIMARY KEY (tenant_id, search_text, id, customer_id, entity_id) | ||
59 | + WITH CLUSTERING ORDER BY (search_text ASC, id DESC, customer_id DESC); | ||
60 | + | ||
61 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer AS | ||
62 | + SELECT * | ||
63 | + from thingsboard.entity_views | ||
64 | + WHERE tenant_id IS NOT NULL | ||
65 | + AND customer_id IS NOT NULL | ||
66 | + AND entity_id IS NOT NULL | ||
67 | + AND search_text IS NOT NULL | ||
68 | + AND id IS NOT NULL | ||
69 | + PRIMARY KEY (tenant_id, customer_id, search_text, id, entity_id) | ||
70 | + WITH CLUSTERING ORDER BY (customer_id DESC, search_text ASC, id DESC); | ||
71 | + | ||
72 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_entity_id AS | ||
73 | + SELECT * | ||
74 | + from thingsboard.entity_views | ||
75 | + WHERE tenant_id IS NOT NULL | ||
76 | + AND customer_id IS NOT NULL | ||
77 | + AND entity_id IS NOT NULL | ||
78 | + AND search_text IS NOT NULL | ||
79 | + AND id IS NOT NULL | ||
80 | + PRIMARY KEY (tenant_id, entity_id, customer_id, search_text, id) | ||
81 | + WITH CLUSTERING ORDER BY (entity_id DESC, customer_id DESC, search_text ASC, id DESC); |
1 | +-- | ||
2 | +-- Copyright © 2016-2018 The Thingsboard Authors | ||
3 | +-- | ||
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +-- you may not use this file except in compliance with the License. | ||
6 | +-- You may obtain a copy of the License at | ||
7 | +-- | ||
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +-- | ||
10 | +-- Unless required by applicable law or agreed to in writing, software | ||
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +-- See the License for the specific language governing permissions and | ||
14 | +-- limitations under the License. | ||
15 | +-- | ||
16 | + | ||
17 | +DROP TABLE IF EXISTS entity_views; | ||
18 | + | ||
19 | +CREATE TABLE IF NOT EXISTS entity_views ( | ||
20 | + id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, | ||
21 | + entity_id varchar(31), | ||
22 | + entity_type varchar(255), | ||
23 | + tenant_id varchar(31), | ||
24 | + customer_id varchar(31), | ||
25 | + name varchar(255), | ||
26 | + keys varchar(255), | ||
27 | + start_ts bigint, | ||
28 | + end_ts bigint, | ||
29 | + search_text varchar(255), | ||
30 | + additional_info varchar | ||
31 | +); |
1 | +-- | ||
2 | +-- Copyright © 2016-2018 The Thingsboard Authors | ||
3 | +-- | ||
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +-- you may not use this file except in compliance with the License. | ||
6 | +-- You may obtain a copy of the License at | ||
7 | +-- | ||
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +-- | ||
10 | +-- Unless required by applicable law or agreed to in writing, software | ||
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +-- See the License for the specific language governing permissions and | ||
14 | +-- limitations under the License. | ||
15 | +-- | ||
16 | + | ||
17 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_name; | ||
18 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_search_text; | ||
19 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_customer; | ||
20 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_entity_id; | ||
21 | + | ||
22 | +DROP TABLE IF EXISTS thingsboard.entity_views; | ||
23 | + | ||
24 | +CREATE TABLE IF NOT EXISTS thingsboard.entity_view ( | ||
25 | + id timeuuid, | ||
26 | + entity_id timeuuid, | ||
27 | + entity_type text, | ||
28 | + tenant_id timeuuid, | ||
29 | + customer_id timeuuid, | ||
30 | + name text, | ||
31 | + type text, | ||
32 | + keys text, | ||
33 | + start_ts bigint, | ||
34 | + end_ts bigint, | ||
35 | + search_text text, | ||
36 | + additional_info text, | ||
37 | + PRIMARY KEY (id, entity_id, tenant_id, customer_id, type) | ||
38 | +); | ||
39 | + | ||
40 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_name AS | ||
41 | + SELECT * | ||
42 | + from thingsboard.entity_view | ||
43 | + WHERE tenant_id IS NOT NULL | ||
44 | + AND entity_id IS NOT NULL | ||
45 | + AND customer_id IS NOT NULL | ||
46 | + AND type IS NOT NULL | ||
47 | + AND name IS NOT NULL | ||
48 | + AND id IS NOT NULL | ||
49 | + PRIMARY KEY (tenant_id, name, id, customer_id, entity_id, type) | ||
50 | + WITH CLUSTERING ORDER BY (name ASC, id DESC, customer_id DESC); | ||
51 | + | ||
52 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_search_text AS | ||
53 | + SELECT * | ||
54 | + from thingsboard.entity_view | ||
55 | + WHERE tenant_id IS NOT NULL | ||
56 | + AND entity_id IS NOT NULL | ||
57 | + AND customer_id IS NOT NULL | ||
58 | + AND type IS NOT NULL | ||
59 | + AND search_text IS NOT NULL | ||
60 | + AND id IS NOT NULL | ||
61 | + PRIMARY KEY (tenant_id, search_text, id, customer_id, entity_id, type) | ||
62 | + WITH CLUSTERING ORDER BY (search_text ASC, id DESC, customer_id DESC); | ||
63 | + | ||
64 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_by_type_and_search_text AS | ||
65 | + SELECT * | ||
66 | + from thingsboard.entity_view | ||
67 | + WHERE tenant_id IS NOT NULL | ||
68 | + AND entity_id IS NOT NULL | ||
69 | + AND customer_id IS NOT NULL | ||
70 | + AND type IS NOT NULL | ||
71 | + AND search_text IS NOT NULL | ||
72 | + AND id IS NOT NULL | ||
73 | + PRIMARY KEY (tenant_id, type, search_text, id, customer_id, entity_id) | ||
74 | + WITH CLUSTERING ORDER BY (type ASC, search_text ASC, id DESC, customer_id DESC); | ||
75 | + | ||
76 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer AS | ||
77 | + SELECT * | ||
78 | + from thingsboard.entity_view | ||
79 | + WHERE tenant_id IS NOT NULL | ||
80 | + AND customer_id IS NOT NULL | ||
81 | + AND entity_id IS NOT NULL | ||
82 | + AND type IS NOT NULL | ||
83 | + AND search_text IS NOT NULL | ||
84 | + AND id IS NOT NULL | ||
85 | + PRIMARY KEY (tenant_id, customer_id, search_text, id, entity_id, type) | ||
86 | + WITH CLUSTERING ORDER BY (customer_id DESC, search_text ASC, id DESC); | ||
87 | + | ||
88 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer_and_type AS | ||
89 | + SELECT * | ||
90 | + from thingsboard.entity_view | ||
91 | + WHERE tenant_id IS NOT NULL | ||
92 | + AND customer_id IS NOT NULL | ||
93 | + AND entity_id IS NOT NULL | ||
94 | + AND type IS NOT NULL | ||
95 | + AND search_text IS NOT NULL | ||
96 | + AND id IS NOT NULL | ||
97 | + PRIMARY KEY (tenant_id, type, customer_id, search_text, id, entity_id) | ||
98 | + WITH CLUSTERING ORDER BY (type ASC, customer_id DESC, search_text ASC, id DESC); | ||
99 | + | ||
100 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_entity_id AS | ||
101 | + SELECT * | ||
102 | + from thingsboard.entity_view | ||
103 | + WHERE tenant_id IS NOT NULL | ||
104 | + AND customer_id IS NOT NULL | ||
105 | + AND entity_id IS NOT NULL | ||
106 | + AND type IS NOT NULL | ||
107 | + AND search_text IS NOT NULL | ||
108 | + AND id IS NOT NULL | ||
109 | + PRIMARY KEY (tenant_id, entity_id, customer_id, search_text, id, type) | ||
110 | + WITH CLUSTERING ORDER BY (entity_id DESC, customer_id DESC, search_text ASC, id DESC); |
1 | +-- | ||
2 | +-- Copyright © 2016-2018 The Thingsboard Authors | ||
3 | +-- | ||
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +-- you may not use this file except in compliance with the License. | ||
6 | +-- You may obtain a copy of the License at | ||
7 | +-- | ||
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +-- | ||
10 | +-- Unless required by applicable law or agreed to in writing, software | ||
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +-- See the License for the specific language governing permissions and | ||
14 | +-- limitations under the License. | ||
15 | +-- | ||
16 | + | ||
17 | +DROP TABLE IF EXISTS entity_views; | ||
18 | + | ||
19 | +CREATE TABLE IF NOT EXISTS entity_view ( | ||
20 | + id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, | ||
21 | + entity_id varchar(31), | ||
22 | + entity_type varchar(255), | ||
23 | + tenant_id varchar(31), | ||
24 | + customer_id varchar(31), | ||
25 | + type varchar(255), | ||
26 | + name varchar(255), | ||
27 | + keys varchar(255), | ||
28 | + start_ts bigint, | ||
29 | + end_ts bigint, | ||
30 | + search_text varchar(255), | ||
31 | + additional_info varchar | ||
32 | +); |
1 | +-- | ||
2 | +-- Copyright © 2016-2018 The Thingsboard Authors | ||
3 | +-- | ||
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +-- you may not use this file except in compliance with the License. | ||
6 | +-- You may obtain a copy of the License at | ||
7 | +-- | ||
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +-- | ||
10 | +-- Unless required by applicable law or agreed to in writing, software | ||
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +-- See the License for the specific language governing permissions and | ||
14 | +-- limitations under the License. | ||
15 | +-- | ||
16 | + | ||
17 | +ALTER TABLE component_descriptor ADD UNIQUE (clazz); |
@@ -31,6 +31,7 @@ import lombok.Setter; | @@ -31,6 +31,7 @@ import lombok.Setter; | ||
31 | import lombok.extern.slf4j.Slf4j; | 31 | import lombok.extern.slf4j.Slf4j; |
32 | import org.springframework.beans.factory.annotation.Autowired; | 32 | import org.springframework.beans.factory.annotation.Autowired; |
33 | import org.springframework.beans.factory.annotation.Value; | 33 | import org.springframework.beans.factory.annotation.Value; |
34 | +import org.springframework.context.annotation.Lazy; | ||
34 | import org.springframework.stereotype.Component; | 35 | import org.springframework.stereotype.Component; |
35 | import org.thingsboard.rule.engine.api.MailService; | 36 | import org.thingsboard.rule.engine.api.MailService; |
36 | import org.thingsboard.server.actors.service.ActorService; | 37 | import org.thingsboard.server.actors.service.ActorService; |
@@ -48,6 +49,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; | @@ -48,6 +49,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; | ||
48 | import org.thingsboard.server.dao.audit.AuditLogService; | 49 | import org.thingsboard.server.dao.audit.AuditLogService; |
49 | import org.thingsboard.server.dao.customer.CustomerService; | 50 | import org.thingsboard.server.dao.customer.CustomerService; |
50 | import org.thingsboard.server.dao.device.DeviceService; | 51 | import org.thingsboard.server.dao.device.DeviceService; |
52 | +import org.thingsboard.server.dao.entityview.EntityViewService; | ||
51 | import org.thingsboard.server.dao.event.EventService; | 53 | import org.thingsboard.server.dao.event.EventService; |
52 | import org.thingsboard.server.dao.relation.RelationService; | 54 | import org.thingsboard.server.dao.relation.RelationService; |
53 | import org.thingsboard.server.dao.rule.RuleChainService; | 55 | import org.thingsboard.server.dao.rule.RuleChainService; |
@@ -62,12 +64,13 @@ import org.thingsboard.server.service.encoding.DataDecodingEncodingService; | @@ -62,12 +64,13 @@ import org.thingsboard.server.service.encoding.DataDecodingEncodingService; | ||
62 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; | 64 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
63 | import org.thingsboard.server.service.executors.ExternalCallExecutorService; | 65 | import org.thingsboard.server.service.executors.ExternalCallExecutorService; |
64 | import org.thingsboard.server.service.mail.MailExecutorService; | 66 | import org.thingsboard.server.service.mail.MailExecutorService; |
65 | -import org.thingsboard.server.service.queue.MsgQueueService; | ||
66 | import org.thingsboard.server.service.rpc.DeviceRpcService; | 67 | import org.thingsboard.server.service.rpc.DeviceRpcService; |
67 | import org.thingsboard.server.service.script.JsExecutorService; | 68 | import org.thingsboard.server.service.script.JsExecutorService; |
68 | -import org.thingsboard.server.service.script.JsSandboxService; | 69 | +import org.thingsboard.server.service.script.JsInvokeService; |
70 | +import org.thingsboard.server.service.session.DeviceSessionCacheService; | ||
69 | import org.thingsboard.server.service.state.DeviceStateService; | 71 | import org.thingsboard.server.service.state.DeviceStateService; |
70 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | 72 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; |
73 | +import org.thingsboard.server.service.transport.RuleEngineTransportService; | ||
71 | 74 | ||
72 | import javax.annotation.Nullable; | 75 | import javax.annotation.Nullable; |
73 | import java.io.IOException; | 76 | import java.io.IOException; |
@@ -161,6 +164,10 @@ public class ActorSystemContext { | @@ -161,6 +164,10 @@ public class ActorSystemContext { | ||
161 | 164 | ||
162 | @Autowired | 165 | @Autowired |
163 | @Getter | 166 | @Getter |
167 | + private EntityViewService entityViewService; | ||
168 | + | ||
169 | + @Autowired | ||
170 | + @Getter | ||
164 | private TelemetrySubscriptionService tsSubService; | 171 | private TelemetrySubscriptionService tsSubService; |
165 | 172 | ||
166 | @Autowired | 173 | @Autowired |
@@ -169,7 +176,7 @@ public class ActorSystemContext { | @@ -169,7 +176,7 @@ public class ActorSystemContext { | ||
169 | 176 | ||
170 | @Autowired | 177 | @Autowired |
171 | @Getter | 178 | @Getter |
172 | - private JsSandboxService jsSandbox; | 179 | + private JsInvokeService jsSandbox; |
173 | 180 | ||
174 | @Autowired | 181 | @Autowired |
175 | @Getter | 182 | @Getter |
@@ -193,11 +200,16 @@ public class ActorSystemContext { | @@ -193,11 +200,16 @@ public class ActorSystemContext { | ||
193 | 200 | ||
194 | @Autowired | 201 | @Autowired |
195 | @Getter | 202 | @Getter |
196 | - private MsgQueueService msgQueueService; | 203 | + private DeviceStateService deviceStateService; |
204 | + | ||
205 | + @Autowired | ||
206 | + @Getter | ||
207 | + private DeviceSessionCacheService deviceSessionCacheService; | ||
197 | 208 | ||
209 | + @Lazy | ||
198 | @Autowired | 210 | @Autowired |
199 | @Getter | 211 | @Getter |
200 | - private DeviceStateService deviceStateService; | 212 | + private RuleEngineTransportService ruleEngineTransportService; |
201 | 213 | ||
202 | @Value("${cluster.partition_id}") | 214 | @Value("${cluster.partition_id}") |
203 | @Getter | 215 | @Getter |
@@ -247,17 +259,21 @@ public class ActorSystemContext { | @@ -247,17 +259,21 @@ public class ActorSystemContext { | ||
247 | @Getter | 259 | @Getter |
248 | private boolean allowSystemMailService; | 260 | private boolean allowSystemMailService; |
249 | 261 | ||
262 | + @Value("${transport.sessions.inactivity_timeout}") | ||
250 | @Getter | 263 | @Getter |
251 | - @Setter | ||
252 | - private ActorSystem actorSystem; | 264 | + private long sessionInactivityTimeout; |
265 | + | ||
266 | + @Value("${transport.sessions.report_timeout}") | ||
267 | + @Getter | ||
268 | + private long sessionReportTimeout; | ||
253 | 269 | ||
254 | @Getter | 270 | @Getter |
255 | @Setter | 271 | @Setter |
256 | - private ActorRef appActor; | 272 | + private ActorSystem actorSystem; |
257 | 273 | ||
258 | @Getter | 274 | @Getter |
259 | @Setter | 275 | @Setter |
260 | - private ActorRef sessionManagerActor; | 276 | + private ActorRef appActor; |
261 | 277 | ||
262 | @Getter | 278 | @Getter |
263 | @Setter | 279 | @Setter |
@@ -25,21 +25,24 @@ import akka.actor.Terminated; | @@ -25,21 +25,24 @@ import akka.actor.Terminated; | ||
25 | import akka.event.Logging; | 25 | import akka.event.Logging; |
26 | import akka.event.LoggingAdapter; | 26 | import akka.event.LoggingAdapter; |
27 | import akka.japi.Function; | 27 | import akka.japi.Function; |
28 | +import com.google.common.collect.BiMap; | ||
29 | +import com.google.common.collect.HashBiMap; | ||
30 | +import lombok.extern.slf4j.Slf4j; | ||
28 | import org.thingsboard.server.actors.ActorSystemContext; | 31 | import org.thingsboard.server.actors.ActorSystemContext; |
29 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; | 32 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; |
30 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 33 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
31 | import org.thingsboard.server.actors.service.DefaultActorService; | 34 | import org.thingsboard.server.actors.service.DefaultActorService; |
32 | import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager; | 35 | import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager; |
33 | import org.thingsboard.server.actors.tenant.TenantActor; | 36 | import org.thingsboard.server.actors.tenant.TenantActor; |
37 | +import org.thingsboard.server.common.data.EntityType; | ||
34 | import org.thingsboard.server.common.data.Tenant; | 38 | import org.thingsboard.server.common.data.Tenant; |
35 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
36 | import org.thingsboard.server.common.data.page.PageDataIterable; | 40 | import org.thingsboard.server.common.data.page.PageDataIterable; |
41 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
37 | import org.thingsboard.server.common.msg.TbActorMsg; | 42 | import org.thingsboard.server.common.msg.TbActorMsg; |
38 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; | 43 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; |
39 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | 44 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; |
40 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 45 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
41 | -import org.thingsboard.server.common.msg.core.BasicActorSystemToDeviceSessionActorMsg; | ||
42 | -import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg; | ||
43 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 46 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
44 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | 47 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; |
45 | import org.thingsboard.server.dao.model.ModelConstants; | 48 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -52,16 +55,14 @@ import java.util.Optional; | @@ -52,16 +55,14 @@ import java.util.Optional; | ||
52 | 55 | ||
53 | public class AppActor extends RuleChainManagerActor { | 56 | public class AppActor extends RuleChainManagerActor { |
54 | 57 | ||
55 | - private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | ||
56 | - | ||
57 | - public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); | 58 | + private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); |
58 | private final TenantService tenantService; | 59 | private final TenantService tenantService; |
59 | - private final Map<TenantId, ActorRef> tenantActors; | 60 | + private final BiMap<TenantId, ActorRef> tenantActors; |
60 | 61 | ||
61 | private AppActor(ActorSystemContext systemContext) { | 62 | private AppActor(ActorSystemContext systemContext) { |
62 | super(systemContext, new SystemRuleChainManager(systemContext)); | 63 | super(systemContext, new SystemRuleChainManager(systemContext)); |
63 | this.tenantService = systemContext.getTenantService(); | 64 | this.tenantService = systemContext.getTenantService(); |
64 | - this.tenantActors = new HashMap<>(); | 65 | + this.tenantActors = HashBiMap.create(); |
65 | } | 66 | } |
66 | 67 | ||
67 | @Override | 68 | @Override |
@@ -71,22 +72,20 @@ public class AppActor extends RuleChainManagerActor { | @@ -71,22 +72,20 @@ public class AppActor extends RuleChainManagerActor { | ||
71 | 72 | ||
72 | @Override | 73 | @Override |
73 | public void preStart() { | 74 | public void preStart() { |
74 | - logger.info("Starting main system actor."); | 75 | + log.info("Starting main system actor."); |
75 | try { | 76 | try { |
76 | initRuleChains(); | 77 | initRuleChains(); |
77 | - | ||
78 | if (systemContext.isTenantComponentsInitEnabled()) { | 78 | if (systemContext.isTenantComponentsInitEnabled()) { |
79 | PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); | 79 | PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); |
80 | for (Tenant tenant : tenantIterator) { | 80 | for (Tenant tenant : tenantIterator) { |
81 | - logger.debug("[{}] Creating tenant actor", tenant.getId()); | 81 | + log.debug("[{}] Creating tenant actor", tenant.getId()); |
82 | getOrCreateTenantActor(tenant.getId()); | 82 | getOrCreateTenantActor(tenant.getId()); |
83 | - logger.debug("Tenant actor created."); | 83 | + log.debug("Tenant actor created."); |
84 | } | 84 | } |
85 | } | 85 | } |
86 | - | ||
87 | - logger.info("Main system actor started."); | 86 | + log.info("Main system actor started."); |
88 | } catch (Exception e) { | 87 | } catch (Exception e) { |
89 | - logger.error(e, "Unknown failure"); | 88 | + log.warn("Unknown failure", e); |
90 | } | 89 | } |
91 | } | 90 | } |
92 | 91 | ||
@@ -105,7 +104,7 @@ public class AppActor extends RuleChainManagerActor { | @@ -105,7 +104,7 @@ public class AppActor extends RuleChainManagerActor { | ||
105 | case SERVICE_TO_RULE_ENGINE_MSG: | 104 | case SERVICE_TO_RULE_ENGINE_MSG: |
106 | onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); | 105 | onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); |
107 | break; | 106 | break; |
108 | - case DEVICE_SESSION_TO_DEVICE_ACTOR_MSG: | 107 | + case TRANSPORT_TO_DEVICE_ACTOR_MSG: |
109 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: | 108 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: |
110 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: | 109 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
111 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: | 110 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
@@ -114,19 +113,12 @@ public class AppActor extends RuleChainManagerActor { | @@ -114,19 +113,12 @@ public class AppActor extends RuleChainManagerActor { | ||
114 | case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG: | 113 | case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG: |
115 | onToDeviceActorMsg((TenantAwareMsg) msg); | 114 | onToDeviceActorMsg((TenantAwareMsg) msg); |
116 | break; | 115 | break; |
117 | - case ACTOR_SYSTEM_TO_DEVICE_SESSION_ACTOR_MSG: | ||
118 | - onToDeviceSessionMsg((BasicActorSystemToDeviceSessionActorMsg) msg); | ||
119 | - break; | ||
120 | default: | 116 | default: |
121 | return false; | 117 | return false; |
122 | } | 118 | } |
123 | return true; | 119 | return true; |
124 | } | 120 | } |
125 | 121 | ||
126 | - private void onToDeviceSessionMsg(BasicActorSystemToDeviceSessionActorMsg msg) { | ||
127 | - systemContext.getSessionManagerActor().tell(msg, self()); | ||
128 | - } | ||
129 | - | ||
130 | private void onPossibleClusterMsg(SendToClusterMsg msg) { | 122 | private void onPossibleClusterMsg(SendToClusterMsg msg) { |
131 | Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(msg.getEntityId()); | 123 | Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(msg.getEntityId()); |
132 | if (address.isPresent()) { | 124 | if (address.isPresent()) { |
@@ -139,7 +131,8 @@ public class AppActor extends RuleChainManagerActor { | @@ -139,7 +131,8 @@ public class AppActor extends RuleChainManagerActor { | ||
139 | 131 | ||
140 | private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { | 132 | private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { |
141 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { | 133 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { |
142 | - //TODO: ashvayka handle this. | 134 | +// this may be a notification about system entities created. |
135 | +// log.warn("[{}] Invalid service to rule engine msg called. System messages are not supported yet: {}", SYSTEM_TENANT, msg); | ||
143 | } else { | 136 | } else { |
144 | getOrCreateTenantActor(msg.getTenantId()).tell(msg, self()); | 137 | getOrCreateTenantActor(msg.getTenantId()).tell(msg, self()); |
145 | } | 138 | } |
@@ -152,16 +145,26 @@ public class AppActor extends RuleChainManagerActor { | @@ -152,16 +145,26 @@ public class AppActor extends RuleChainManagerActor { | ||
152 | } | 145 | } |
153 | 146 | ||
154 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 147 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
155 | - ActorRef target; | 148 | + ActorRef target = null; |
156 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { | 149 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { |
157 | target = getEntityActorRef(msg.getEntityId()); | 150 | target = getEntityActorRef(msg.getEntityId()); |
158 | } else { | 151 | } else { |
159 | - target = getOrCreateTenantActor(msg.getTenantId()); | 152 | + if (msg.getEntityId().getEntityType() == EntityType.TENANT |
153 | + && msg.getEvent() == ComponentLifecycleEvent.DELETED) { | ||
154 | + log.debug("[{}] Handling tenant deleted notification: {}", msg.getTenantId(), msg); | ||
155 | + ActorRef tenantActor = tenantActors.remove(new TenantId(msg.getEntityId().getId())); | ||
156 | + if (tenantActor != null) { | ||
157 | + log.debug("[{}] Deleting tenant actor: {}", msg.getTenantId(), tenantActor); | ||
158 | + context().stop(tenantActor); | ||
159 | + } | ||
160 | + } else { | ||
161 | + target = getOrCreateTenantActor(msg.getTenantId()); | ||
162 | + } | ||
160 | } | 163 | } |
161 | if (target != null) { | 164 | if (target != null) { |
162 | target.tell(msg, ActorRef.noSender()); | 165 | target.tell(msg, ActorRef.noSender()); |
163 | } else { | 166 | } else { |
164 | - logger.debug("Invalid component lifecycle msg: {}", msg); | 167 | + log.debug("[{}] Invalid component lifecycle msg: {}", msg.getTenantId(), msg); |
165 | } | 168 | } |
166 | } | 169 | } |
167 | 170 | ||
@@ -169,25 +172,25 @@ public class AppActor extends RuleChainManagerActor { | @@ -169,25 +172,25 @@ public class AppActor extends RuleChainManagerActor { | ||
169 | getOrCreateTenantActor(msg.getTenantId()).tell(msg, ActorRef.noSender()); | 172 | getOrCreateTenantActor(msg.getTenantId()).tell(msg, ActorRef.noSender()); |
170 | } | 173 | } |
171 | 174 | ||
172 | - private void processDeviceMsg(DeviceToDeviceActorMsg deviceToDeviceActorMsg) { | ||
173 | - TenantId tenantId = deviceToDeviceActorMsg.getTenantId(); | ||
174 | - ActorRef tenantActor = getOrCreateTenantActor(tenantId); | ||
175 | - if (deviceToDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) { | ||
176 | -// tenantActor.tell(new RuleChainDeviceMsg(deviceToDeviceActorMsg, ruleManager.getRuleChain(this.context())), context().self()); | ||
177 | - } else { | ||
178 | - tenantActor.tell(deviceToDeviceActorMsg, context().self()); | ||
179 | - } | ||
180 | - } | ||
181 | - | ||
182 | private ActorRef getOrCreateTenantActor(TenantId tenantId) { | 175 | private ActorRef getOrCreateTenantActor(TenantId tenantId) { |
183 | - return tenantActors.computeIfAbsent(tenantId, k -> context().actorOf(Props.create(new TenantActor.ActorCreator(systemContext, tenantId)) | ||
184 | - .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), tenantId.toString())); | 176 | + return tenantActors.computeIfAbsent(tenantId, k -> { |
177 | + log.debug("[{}] Creating tenant actor.", tenantId); | ||
178 | + ActorRef tenantActor = context().actorOf(Props.create(new TenantActor.ActorCreator(systemContext, tenantId)) | ||
179 | + .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), tenantId.toString()); | ||
180 | + context().watch(tenantActor); | ||
181 | + log.debug("[{}] Created tenant actor: {}.", tenantId, tenantActor); | ||
182 | + return tenantActor; | ||
183 | + }); | ||
185 | } | 184 | } |
186 | 185 | ||
187 | - private void processTermination(Terminated message) { | 186 | + @Override |
187 | + protected void processTermination(Terminated message) { | ||
188 | ActorRef terminated = message.actor(); | 188 | ActorRef terminated = message.actor(); |
189 | if (terminated instanceof LocalActorRef) { | 189 | if (terminated instanceof LocalActorRef) { |
190 | - logger.debug("Removed actor: {}", terminated); | 190 | + boolean removed = tenantActors.inverse().remove(terminated) != null; |
191 | + if (removed) { | ||
192 | + log.debug("[{}] Removed actor:", terminated); | ||
193 | + } | ||
191 | } else { | 194 | } else { |
192 | throw new IllegalStateException("Remote actors are not supported!"); | 195 | throw new IllegalStateException("Remote actors are not supported!"); |
193 | } | 196 | } |
@@ -201,20 +204,17 @@ public class AppActor extends RuleChainManagerActor { | @@ -201,20 +204,17 @@ public class AppActor extends RuleChainManagerActor { | ||
201 | } | 204 | } |
202 | 205 | ||
203 | @Override | 206 | @Override |
204 | - public AppActor create() throws Exception { | 207 | + public AppActor create() { |
205 | return new AppActor(context); | 208 | return new AppActor(context); |
206 | } | 209 | } |
207 | } | 210 | } |
208 | 211 | ||
209 | - private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), new Function<Throwable, Directive>() { | ||
210 | - @Override | ||
211 | - public Directive apply(Throwable t) { | ||
212 | - logger.error(t, "Unknown failure"); | ||
213 | - if (t instanceof RuntimeException) { | ||
214 | - return SupervisorStrategy.restart(); | ||
215 | - } else { | ||
216 | - return SupervisorStrategy.stop(); | ||
217 | - } | 212 | + private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> { |
213 | + log.warn("Unknown failure", t); | ||
214 | + if (t instanceof RuntimeException) { | ||
215 | + return SupervisorStrategy.restart(); | ||
216 | + } else { | ||
217 | + return SupervisorStrategy.stop(); | ||
218 | } | 218 | } |
219 | }); | 219 | }); |
220 | } | 220 | } |
@@ -15,43 +15,44 @@ | @@ -15,43 +15,44 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | -import akka.event.Logging; | ||
19 | -import akka.event.LoggingAdapter; | ||
20 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 18 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
21 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | 19 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
22 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | import org.thingsboard.server.actors.service.ContextAwareActor; | 21 | import org.thingsboard.server.actors.service.ContextAwareActor; |
24 | -import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
25 | import org.thingsboard.server.common.data.id.DeviceId; | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
27 | import org.thingsboard.server.common.msg.TbActorMsg; | 24 | import org.thingsboard.server.common.msg.TbActorMsg; |
28 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
29 | -import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg; | ||
30 | import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg; | 25 | import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg; |
31 | -import org.thingsboard.server.common.msg.timeout.DeviceActorQueueTimeoutMsg; | ||
32 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; | 26 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; |
33 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; | 27 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
34 | import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; | 28 | import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; |
29 | +import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; | ||
35 | 30 | ||
36 | public class DeviceActor extends ContextAwareActor { | 31 | public class DeviceActor extends ContextAwareActor { |
37 | 32 | ||
38 | - private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | ||
39 | - | ||
40 | private final DeviceActorMessageProcessor processor; | 33 | private final DeviceActorMessageProcessor processor; |
41 | 34 | ||
42 | - private DeviceActor(ActorSystemContext systemContext, TenantId tenantId, DeviceId deviceId) { | 35 | + DeviceActor(ActorSystemContext systemContext, TenantId tenantId, DeviceId deviceId) { |
43 | super(systemContext); | 36 | super(systemContext); |
44 | - this.processor = new DeviceActorMessageProcessor(systemContext, logger, tenantId, deviceId); | 37 | + this.processor = new DeviceActorMessageProcessor(systemContext, tenantId, deviceId); |
38 | + } | ||
39 | + | ||
40 | + @Override | ||
41 | + public void preStart() { | ||
42 | + log.debug("[{}][{}] Starting device actor.", processor.tenantId, processor.deviceId); | ||
43 | + try { | ||
44 | + processor.initSessionTimeout(context()); | ||
45 | + log.debug("[{}][{}] Device actor started.", processor.tenantId, processor.deviceId); | ||
46 | + } catch (Exception e) { | ||
47 | + log.warn("[{}][{}] Unknown failure", processor.tenantId, processor.deviceId, e); | ||
48 | + } | ||
45 | } | 49 | } |
46 | 50 | ||
47 | @Override | 51 | @Override |
48 | protected boolean process(TbActorMsg msg) { | 52 | protected boolean process(TbActorMsg msg) { |
49 | switch (msg.getMsgType()) { | 53 | switch (msg.getMsgType()) { |
50 | - case CLUSTER_EVENT_MSG: | ||
51 | - processor.processClusterEventMsg((ClusterEventMsg) msg); | ||
52 | - break; | ||
53 | - case DEVICE_SESSION_TO_DEVICE_ACTOR_MSG: | ||
54 | - processor.process(context(), (DeviceToDeviceActorMsg) msg); | 54 | + case TRANSPORT_TO_DEVICE_ACTOR_MSG: |
55 | + processor.process(context(), (TransportToDeviceActorMsgWrapper) msg); | ||
55 | break; | 56 | break; |
56 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: | 57 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: |
57 | processor.processAttributesUpdate(context(), (DeviceAttributesEventNotificationMsg) msg); | 58 | processor.processAttributesUpdate(context(), (DeviceAttributesEventNotificationMsg) msg); |
@@ -74,11 +75,8 @@ public class DeviceActor extends ContextAwareActor { | @@ -74,11 +75,8 @@ public class DeviceActor extends ContextAwareActor { | ||
74 | case DEVICE_ACTOR_CLIENT_SIDE_RPC_TIMEOUT_MSG: | 75 | case DEVICE_ACTOR_CLIENT_SIDE_RPC_TIMEOUT_MSG: |
75 | processor.processClientSideRpcTimeout(context(), (DeviceActorClientSideRpcTimeoutMsg) msg); | 76 | processor.processClientSideRpcTimeout(context(), (DeviceActorClientSideRpcTimeoutMsg) msg); |
76 | break; | 77 | break; |
77 | - case DEVICE_ACTOR_QUEUE_TIMEOUT_MSG: | ||
78 | - processor.processQueueTimeout(context(), (DeviceActorQueueTimeoutMsg) msg); | ||
79 | - break; | ||
80 | - case RULE_ENGINE_QUEUE_PUT_ACK_MSG: | ||
81 | - processor.processQueueAck(context(), (RuleEngineQueuePutAckMsg) msg); | 78 | + case SESSION_TIMEOUT_MSG: |
79 | + processor.checkSessionsTimeout(); | ||
82 | break; | 80 | break; |
83 | default: | 81 | default: |
84 | return false; | 82 | return false; |
@@ -86,22 +84,4 @@ public class DeviceActor extends ContextAwareActor { | @@ -86,22 +84,4 @@ public class DeviceActor extends ContextAwareActor { | ||
86 | return true; | 84 | return true; |
87 | } | 85 | } |
88 | 86 | ||
89 | - public static class ActorCreator extends ContextBasedCreator<DeviceActor> { | ||
90 | - private static final long serialVersionUID = 1L; | ||
91 | - | ||
92 | - private final TenantId tenantId; | ||
93 | - private final DeviceId deviceId; | ||
94 | - | ||
95 | - public ActorCreator(ActorSystemContext context, TenantId tenantId, DeviceId deviceId) { | ||
96 | - super(context); | ||
97 | - this.tenantId = tenantId; | ||
98 | - this.deviceId = deviceId; | ||
99 | - } | ||
100 | - | ||
101 | - @Override | ||
102 | - public DeviceActor create() throws Exception { | ||
103 | - return new DeviceActor(context, tenantId, deviceId); | ||
104 | - } | ||
105 | - } | ||
106 | - | ||
107 | } | 87 | } |
application/src/main/java/org/thingsboard/server/actors/device/DeviceActorCreator.java
renamed from
common/message/src/main/java/org/thingsboard/server/common/msg/core/SessionCloseNotification.java
@@ -13,26 +13,27 @@ | @@ -13,26 +13,27 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.common.msg.core; | 16 | +package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | -import lombok.ToString; | ||
19 | -import org.thingsboard.server.common.msg.kv.AttributesKVMsg; | ||
20 | -import org.thingsboard.server.common.msg.session.SessionMsgType; | ||
21 | -import org.thingsboard.server.common.msg.session.SessionMsgType; | ||
22 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | ||
23 | - | ||
24 | -@ToString | ||
25 | -public class SessionCloseNotification implements ToDeviceMsg { | 18 | +import org.thingsboard.server.actors.ActorSystemContext; |
19 | +import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
20 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
21 | +import org.thingsboard.server.common.data.id.TenantId; | ||
26 | 22 | ||
23 | +public class DeviceActorCreator extends ContextBasedCreator<DeviceActor> { | ||
27 | private static final long serialVersionUID = 1L; | 24 | private static final long serialVersionUID = 1L; |
28 | 25 | ||
29 | - @Override | ||
30 | - public boolean isSuccess() { | ||
31 | - return true; | ||
32 | - } | 26 | + private final TenantId tenantId; |
27 | + private final DeviceId deviceId; | ||
33 | 28 | ||
34 | - public SessionMsgType getSessionMsgType() { | ||
35 | - return SessionMsgType.SESSION_CLOSE; | 29 | + public DeviceActorCreator(ActorSystemContext context, TenantId tenantId, DeviceId deviceId) { |
30 | + super(context); | ||
31 | + this.tenantId = tenantId; | ||
32 | + this.deviceId = deviceId; | ||
36 | } | 33 | } |
37 | 34 | ||
35 | + @Override | ||
36 | + public DeviceActor create() { | ||
37 | + return new DeviceActor(context, tenantId, deviceId); | ||
38 | + } | ||
38 | } | 39 | } |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | import akka.actor.ActorContext; | 18 | import akka.actor.ActorContext; |
19 | -import akka.actor.ActorRef; | ||
20 | import akka.event.LoggingAdapter; | 19 | import akka.event.LoggingAdapter; |
21 | import com.datastax.driver.core.utils.UUIDs; | 20 | import com.datastax.driver.core.utils.UUIDs; |
22 | import com.google.common.util.concurrent.FutureCallback; | 21 | import com.google.common.util.concurrent.FutureCallback; |
@@ -25,6 +24,7 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -25,6 +24,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
25 | import com.google.gson.Gson; | 24 | import com.google.gson.Gson; |
26 | import com.google.gson.JsonObject; | 25 | import com.google.gson.JsonObject; |
27 | import com.google.gson.JsonParser; | 26 | import com.google.gson.JsonParser; |
27 | +import lombok.extern.slf4j.Slf4j; | ||
28 | import org.thingsboard.rule.engine.api.RpcError; | 28 | import org.thingsboard.rule.engine.api.RpcError; |
29 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 29 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
30 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | 30 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
@@ -33,7 +33,6 @@ import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; | @@ -33,7 +33,6 @@ import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; | ||
33 | import org.thingsboard.server.common.data.DataConstants; | 33 | import org.thingsboard.server.common.data.DataConstants; |
34 | import org.thingsboard.server.common.data.Device; | 34 | import org.thingsboard.server.common.data.Device; |
35 | import org.thingsboard.server.common.data.id.DeviceId; | 35 | import org.thingsboard.server.common.data.id.DeviceId; |
36 | -import org.thingsboard.server.common.data.id.SessionId; | ||
37 | import org.thingsboard.server.common.data.id.TenantId; | 36 | import org.thingsboard.server.common.data.id.TenantId; |
38 | import org.thingsboard.server.common.data.kv.AttributeKey; | 37 | import org.thingsboard.server.common.data.kv.AttributeKey; |
39 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 38 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
@@ -43,37 +42,34 @@ import org.thingsboard.server.common.msg.TbMsg; | @@ -43,37 +42,34 @@ import org.thingsboard.server.common.msg.TbMsg; | ||
43 | import org.thingsboard.server.common.msg.TbMsgDataType; | 42 | import org.thingsboard.server.common.msg.TbMsgDataType; |
44 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 43 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
45 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 44 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
46 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
47 | -import org.thingsboard.server.common.msg.core.ActorSystemToDeviceSessionActorMsg; | ||
48 | -import org.thingsboard.server.common.msg.core.AttributesUpdateNotification; | ||
49 | -import org.thingsboard.server.common.msg.core.AttributesUpdateRequest; | ||
50 | -import org.thingsboard.server.common.msg.core.BasicActorSystemToDeviceSessionActorMsg; | ||
51 | -import org.thingsboard.server.common.msg.core.BasicCommandAckResponse; | ||
52 | -import org.thingsboard.server.common.msg.core.BasicGetAttributesResponse; | ||
53 | -import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse; | ||
54 | -import org.thingsboard.server.common.msg.core.GetAttributesRequest; | ||
55 | -import org.thingsboard.server.common.msg.core.RuleEngineError; | ||
56 | -import org.thingsboard.server.common.msg.core.RuleEngineErrorMsg; | ||
57 | -import org.thingsboard.server.common.msg.core.SessionCloseMsg; | ||
58 | -import org.thingsboard.server.common.msg.core.SessionCloseNotification; | ||
59 | -import org.thingsboard.server.common.msg.core.SessionOpenMsg; | ||
60 | -import org.thingsboard.server.common.msg.core.TelemetryUploadRequest; | ||
61 | -import org.thingsboard.server.common.msg.core.ToDeviceRpcRequestMsg; | ||
62 | -import org.thingsboard.server.common.msg.core.ToDeviceRpcResponseMsg; | ||
63 | -import org.thingsboard.server.common.msg.core.ToServerRpcRequestMsg; | ||
64 | -import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg; | ||
65 | -import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg; | ||
66 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 45 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
67 | -import org.thingsboard.server.common.msg.session.FromDeviceMsg; | ||
68 | import org.thingsboard.server.common.msg.session.SessionMsgType; | 46 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
69 | -import org.thingsboard.server.common.msg.session.SessionType; | ||
70 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | ||
71 | import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg; | 47 | import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg; |
72 | -import org.thingsboard.server.common.msg.timeout.DeviceActorQueueTimeoutMsg; | ||
73 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; | 48 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; |
49 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
50 | +import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | ||
51 | +import org.thingsboard.server.gen.transport.TransportProtos.DeviceActorToTransportMsg; | ||
52 | +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; | ||
53 | +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; | ||
54 | +import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; | ||
55 | +import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType; | ||
56 | +import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; | ||
57 | +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | ||
58 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; | ||
59 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; | ||
60 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg; | ||
61 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | ||
62 | +import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; | ||
63 | +import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; | ||
64 | +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; | ||
65 | +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; | ||
66 | +import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; | ||
67 | +import org.thingsboard.server.gen.transport.TransportProtos.TsKvListProto; | ||
68 | +import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; | ||
74 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | 69 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
75 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; | 70 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
76 | import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; | 71 | import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; |
72 | +import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; | ||
77 | 73 | ||
78 | import javax.annotation.Nullable; | 74 | import javax.annotation.Nullable; |
79 | import java.util.ArrayList; | 75 | import java.util.ArrayList; |
@@ -87,24 +83,22 @@ import java.util.Map; | @@ -87,24 +83,22 @@ import java.util.Map; | ||
87 | import java.util.Optional; | 83 | import java.util.Optional; |
88 | import java.util.Set; | 84 | import java.util.Set; |
89 | import java.util.UUID; | 85 | import java.util.UUID; |
90 | -import java.util.concurrent.TimeoutException; | ||
91 | import java.util.function.Consumer; | 86 | import java.util.function.Consumer; |
92 | -import java.util.function.Predicate; | ||
93 | import java.util.stream.Collectors; | 87 | import java.util.stream.Collectors; |
94 | 88 | ||
95 | /** | 89 | /** |
96 | * @author Andrew Shvayka | 90 | * @author Andrew Shvayka |
97 | */ | 91 | */ |
98 | -public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
99 | - | ||
100 | - private final TenantId tenantId; | ||
101 | - private final DeviceId deviceId; | ||
102 | - private final Map<SessionId, SessionInfo> sessions; | ||
103 | - private final Map<SessionId, SessionInfo> attributeSubscriptions; | ||
104 | - private final Map<SessionId, SessionInfo> rpcSubscriptions; | 92 | +@Slf4j |
93 | +class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
94 | + | ||
95 | + final TenantId tenantId; | ||
96 | + final DeviceId deviceId; | ||
97 | + private final Map<UUID, SessionInfoMetaData> sessions; | ||
98 | + private final Map<UUID, SessionInfo> attributeSubscriptions; | ||
99 | + private final Map<UUID, SessionInfo> rpcSubscriptions; | ||
105 | private final Map<Integer, ToDeviceRpcRequestMetadata> toDeviceRpcPendingMap; | 100 | private final Map<Integer, ToDeviceRpcRequestMetadata> toDeviceRpcPendingMap; |
106 | private final Map<Integer, ToServerRpcRequestMetadata> toServerRpcPendingMap; | 101 | private final Map<Integer, ToServerRpcRequestMetadata> toServerRpcPendingMap; |
107 | - private final Map<UUID, PendingSessionMsgData> pendingMsgs; | ||
108 | 102 | ||
109 | private final Gson gson = new Gson(); | 103 | private final Gson gson = new Gson(); |
110 | private final JsonParser jsonParser = new JsonParser(); | 104 | private final JsonParser jsonParser = new JsonParser(); |
@@ -114,8 +108,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -114,8 +108,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
114 | private String deviceType; | 108 | private String deviceType; |
115 | private TbMsgMetaData defaultMetaData; | 109 | private TbMsgMetaData defaultMetaData; |
116 | 110 | ||
117 | - DeviceActorMessageProcessor(ActorSystemContext systemContext, LoggingAdapter logger, TenantId tenantId, DeviceId deviceId) { | ||
118 | - super(systemContext, logger); | 111 | + DeviceActorMessageProcessor(ActorSystemContext systemContext, TenantId tenantId, DeviceId deviceId) { |
112 | + super(systemContext); | ||
119 | this.tenantId = tenantId; | 113 | this.tenantId = tenantId; |
120 | this.deviceId = deviceId; | 114 | this.deviceId = deviceId; |
121 | this.sessions = new LinkedHashMap<>(); | 115 | this.sessions = new LinkedHashMap<>(); |
@@ -123,8 +117,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -123,8 +117,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
123 | this.rpcSubscriptions = new HashMap<>(); | 117 | this.rpcSubscriptions = new HashMap<>(); |
124 | this.toDeviceRpcPendingMap = new HashMap<>(); | 118 | this.toDeviceRpcPendingMap = new HashMap<>(); |
125 | this.toServerRpcPendingMap = new HashMap<>(); | 119 | this.toServerRpcPendingMap = new HashMap<>(); |
126 | - this.pendingMsgs = new HashMap<>(); | ||
127 | initAttributes(); | 120 | initAttributes(); |
121 | + restoreSessions(); | ||
128 | } | 122 | } |
129 | 123 | ||
130 | private void initAttributes() { | 124 | private void initAttributes() { |
@@ -139,41 +133,36 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -139,41 +133,36 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
139 | void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) { | 133 | void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) { |
140 | ToDeviceRpcRequest request = msg.getMsg(); | 134 | ToDeviceRpcRequest request = msg.getMsg(); |
141 | ToDeviceRpcRequestBody body = request.getBody(); | 135 | ToDeviceRpcRequestBody body = request.getBody(); |
142 | - ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg( | ||
143 | - rpcSeq++, | ||
144 | - body.getMethod(), | ||
145 | - body.getParams() | ||
146 | - ); | 136 | + ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder().setRequestId( |
137 | + rpcSeq++).setMethodName(body.getMethod()).setParams(body.getParams()).build(); | ||
147 | 138 | ||
148 | long timeout = request.getExpirationTime() - System.currentTimeMillis(); | 139 | long timeout = request.getExpirationTime() - System.currentTimeMillis(); |
149 | if (timeout <= 0) { | 140 | if (timeout <= 0) { |
150 | - logger.debug("[{}][{}] Ignoring message due to exp time reached", deviceId, request.getId(), request.getExpirationTime()); | 141 | + log.debug("[{}][{}] Ignoring message due to exp time reached, {}", deviceId, request.getId(), request.getExpirationTime()); |
151 | return; | 142 | return; |
152 | } | 143 | } |
153 | 144 | ||
154 | boolean sent = rpcSubscriptions.size() > 0; | 145 | boolean sent = rpcSubscriptions.size() > 0; |
155 | - Set<SessionId> syncSessionSet = new HashSet<>(); | ||
156 | - rpcSubscriptions.entrySet().forEach(sub -> { | ||
157 | - ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(rpcRequest, sub.getKey()); | ||
158 | - sendMsgToSessionActor(response, sub.getValue().getServer()); | ||
159 | - if (SessionType.SYNC == sub.getValue().getType()) { | ||
160 | - syncSessionSet.add(sub.getKey()); | 146 | + Set<UUID> syncSessionSet = new HashSet<>(); |
147 | + rpcSubscriptions.forEach((key, value) -> { | ||
148 | + sendToTransport(rpcRequest, key, value.getNodeId()); | ||
149 | + if (TransportProtos.SessionType.SYNC == value.getType()) { | ||
150 | + syncSessionSet.add(key); | ||
161 | } | 151 | } |
162 | }); | 152 | }); |
163 | syncSessionSet.forEach(rpcSubscriptions::remove); | 153 | syncSessionSet.forEach(rpcSubscriptions::remove); |
164 | 154 | ||
165 | if (request.isOneway() && sent) { | 155 | if (request.isOneway() && sent) { |
166 | - logger.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId()); | ||
167 | - systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(msg.getMsg().getId(), msg.getServerAddress(), null, null)); | 156 | + log.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId()); |
157 | + systemContext.getDeviceRpcService().processResponseToServerSideRPCRequestFromDeviceActor(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null)); | ||
168 | } else { | 158 | } else { |
169 | registerPendingRpcRequest(context, msg, sent, rpcRequest, timeout); | 159 | registerPendingRpcRequest(context, msg, sent, rpcRequest, timeout); |
170 | } | 160 | } |
171 | if (sent) { | 161 | if (sent) { |
172 | - logger.debug("[{}] RPC request {} is sent!", deviceId, request.getId()); | 162 | + log.debug("[{}] RPC request {} is sent!", deviceId, request.getId()); |
173 | } else { | 163 | } else { |
174 | - logger.debug("[{}] RPC request {} is NOT sent!", deviceId, request.getId()); | 164 | + log.debug("[{}] RPC request {} is NOT sent!", deviceId, request.getId()); |
175 | } | 165 | } |
176 | - | ||
177 | } | 166 | } |
178 | 167 | ||
179 | private void registerPendingRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) { | 168 | private void registerPendingRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) { |
@@ -185,101 +174,82 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -185,101 +174,82 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
185 | void processServerSideRpcTimeout(ActorContext context, DeviceActorServerSideRpcTimeoutMsg msg) { | 174 | void processServerSideRpcTimeout(ActorContext context, DeviceActorServerSideRpcTimeoutMsg msg) { |
186 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); | 175 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); |
187 | if (requestMd != null) { | 176 | if (requestMd != null) { |
188 | - logger.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); | ||
189 | - systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | ||
190 | - requestMd.getMsg().getServerAddress(), null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION)); | ||
191 | - } | ||
192 | - } | ||
193 | - | ||
194 | - void processQueueTimeout(ActorContext context, DeviceActorQueueTimeoutMsg msg) { | ||
195 | - PendingSessionMsgData data = pendingMsgs.remove(msg.getId()); | ||
196 | - if (data != null) { | ||
197 | - logger.debug("[{}] Queue put [{}] timeout detected!", deviceId, msg.getId()); | ||
198 | - ToDeviceMsg toDeviceMsg = new RuleEngineErrorMsg(data.getSessionMsgType(), RuleEngineError.QUEUE_PUT_TIMEOUT); | ||
199 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(toDeviceMsg, data.getSessionId()), data.getServerAddress()); | ||
200 | - } | ||
201 | - } | ||
202 | - | ||
203 | - void processQueueAck(ActorContext context, RuleEngineQueuePutAckMsg msg) { | ||
204 | - PendingSessionMsgData data = pendingMsgs.remove(msg.getId()); | ||
205 | - if (data != null && data.isReplyOnQueueAck()) { | ||
206 | - int remainingAcks = data.getAckMsgCount() - 1; | ||
207 | - data.setAckMsgCount(remainingAcks); | ||
208 | - logger.debug("[{}] Queue put [{}] ack detected. Remaining acks: {}!", deviceId, msg.getId(), remainingAcks); | ||
209 | - if (remainingAcks == 0) { | ||
210 | - ToDeviceMsg toDeviceMsg = BasicStatusCodeResponse.onSuccess(data.getSessionMsgType(), data.getRequestId()); | ||
211 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(toDeviceMsg, data.getSessionId()), data.getServerAddress()); | ||
212 | - } | 177 | + log.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); |
178 | + systemContext.getDeviceRpcService().processResponseToServerSideRPCRequestFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | ||
179 | + null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION)); | ||
213 | } | 180 | } |
214 | } | 181 | } |
215 | 182 | ||
216 | - private void sendPendingRequests(ActorContext context, SessionId sessionId, SessionType type, Optional<ServerAddress> server) { | 183 | + private void sendPendingRequests(ActorContext context, UUID sessionId, SessionInfoProto sessionInfo) { |
184 | + TransportProtos.SessionType sessionType = getSessionType(sessionId); | ||
217 | if (!toDeviceRpcPendingMap.isEmpty()) { | 185 | if (!toDeviceRpcPendingMap.isEmpty()) { |
218 | - logger.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId); | ||
219 | - if (type == SessionType.SYNC) { | ||
220 | - logger.debug("[{}] Cleanup sync rpc session [{}]", deviceId, sessionId); | 186 | + log.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId); |
187 | + if (sessionType == TransportProtos.SessionType.SYNC) { | ||
188 | + log.debug("[{}] Cleanup sync rpc session [{}]", deviceId, sessionId); | ||
221 | rpcSubscriptions.remove(sessionId); | 189 | rpcSubscriptions.remove(sessionId); |
222 | } | 190 | } |
223 | } else { | 191 | } else { |
224 | - logger.debug("[{}] No pending RPC messages for new async session [{}]", deviceId, sessionId); | 192 | + log.debug("[{}] No pending RPC messages for new async session [{}]", deviceId, sessionId); |
225 | } | 193 | } |
226 | Set<Integer> sentOneWayIds = new HashSet<>(); | 194 | Set<Integer> sentOneWayIds = new HashSet<>(); |
227 | - if (type == SessionType.ASYNC) { | ||
228 | - toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, server, sentOneWayIds)); | 195 | + if (sessionType == TransportProtos.SessionType.ASYNC) { |
196 | + toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds)); | ||
229 | } else { | 197 | } else { |
230 | - toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, server, sentOneWayIds)); | 198 | + toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds)); |
231 | } | 199 | } |
232 | 200 | ||
233 | sentOneWayIds.forEach(toDeviceRpcPendingMap::remove); | 201 | sentOneWayIds.forEach(toDeviceRpcPendingMap::remove); |
234 | } | 202 | } |
235 | 203 | ||
236 | - private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(ActorContext context, SessionId sessionId, Optional<ServerAddress> server, Set<Integer> sentOneWayIds) { | 204 | + private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(ActorContext context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) { |
237 | return entry -> { | 205 | return entry -> { |
238 | - ToDeviceRpcRequestActorMsg requestActorMsg = entry.getValue().getMsg(); | ||
239 | ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg(); | 206 | ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg(); |
240 | ToDeviceRpcRequestBody body = request.getBody(); | 207 | ToDeviceRpcRequestBody body = request.getBody(); |
241 | if (request.isOneway()) { | 208 | if (request.isOneway()) { |
242 | sentOneWayIds.add(entry.getKey()); | 209 | sentOneWayIds.add(entry.getKey()); |
243 | - systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(request.getId(), requestActorMsg.getServerAddress(), null, null)); | 210 | + systemContext.getDeviceRpcService().processResponseToServerSideRPCRequestFromDeviceActor(new FromDeviceRpcResponse(request.getId(), null, null)); |
244 | } | 211 | } |
245 | - ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg( | ||
246 | - entry.getKey(), | ||
247 | - body.getMethod(), | ||
248 | - body.getParams() | ||
249 | - ); | ||
250 | - ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(rpcRequest, sessionId); | ||
251 | - sendMsgToSessionActor(response, server); | 212 | + ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder().setRequestId( |
213 | + entry.getKey()).setMethodName(body.getMethod()).setParams(body.getParams()).build(); | ||
214 | + sendToTransport(rpcRequest, sessionId, nodeId); | ||
252 | }; | 215 | }; |
253 | } | 216 | } |
254 | 217 | ||
255 | - void process(ActorContext context, DeviceToDeviceActorMsg msg) { | ||
256 | - processSubscriptionCommands(context, msg); | ||
257 | - processRpcResponses(context, msg); | ||
258 | - processSessionStateMsgs(msg); | ||
259 | - | ||
260 | - SessionMsgType sessionMsgType = msg.getPayload().getMsgType(); | ||
261 | - if (sessionMsgType.requiresRulesProcessing()) { | ||
262 | - switch (sessionMsgType) { | ||
263 | - case GET_ATTRIBUTES_REQUEST: | ||
264 | - handleGetAttributesRequest(msg); | ||
265 | - break; | ||
266 | - case POST_ATTRIBUTES_REQUEST: | ||
267 | - handlePostAttributesRequest(context, msg); | ||
268 | - reportActivity(); | ||
269 | - break; | ||
270 | - case POST_TELEMETRY_REQUEST: | ||
271 | - handlePostTelemetryRequest(context, msg); | ||
272 | - reportActivity(); | ||
273 | - break; | ||
274 | - case TO_SERVER_RPC_REQUEST: | ||
275 | - handleClientSideRPCRequest(context, msg); | ||
276 | - reportActivity(); | ||
277 | - break; | ||
278 | - } | 218 | + void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { |
219 | + TransportToDeviceActorMsg msg = wrapper.getMsg(); | ||
220 | + if (msg.hasSessionEvent()) { | ||
221 | + processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); | ||
222 | + } | ||
223 | + if (msg.hasSubscribeToAttributes()) { | ||
224 | + processSubscriptionCommands(context, msg.getSessionInfo(), msg.getSubscribeToAttributes()); | ||
225 | + } | ||
226 | + if (msg.hasSubscribeToRPC()) { | ||
227 | + processSubscriptionCommands(context, msg.getSessionInfo(), msg.getSubscribeToRPC()); | ||
228 | + } | ||
229 | + if (msg.hasPostAttributes()) { | ||
230 | + handlePostAttributesRequest(context, msg.getSessionInfo(), msg.getPostAttributes()); | ||
231 | + reportLogicalDeviceActivity(); | ||
232 | + } | ||
233 | + if (msg.hasPostTelemetry()) { | ||
234 | + handlePostTelemetryRequest(context, msg.getSessionInfo(), msg.getPostTelemetry()); | ||
235 | + reportLogicalDeviceActivity(); | ||
236 | + } | ||
237 | + if (msg.hasGetAttributes()) { | ||
238 | + handleGetAttributesRequest(context, msg.getSessionInfo(), msg.getGetAttributes()); | ||
239 | + } | ||
240 | + if (msg.hasToDeviceRPCCallResponse()) { | ||
241 | + processRpcResponses(context, msg.getSessionInfo(), msg.getToDeviceRPCCallResponse()); | ||
242 | + } | ||
243 | + if (msg.hasToServerRPCCallRequest()) { | ||
244 | + handleClientSideRPCRequest(context, msg.getSessionInfo(), msg.getToServerRPCCallRequest()); | ||
245 | + reportLogicalDeviceActivity(); | ||
246 | + } | ||
247 | + if (msg.hasSubscriptionInfo()) { | ||
248 | + handleSessionActivity(context, msg.getSessionInfo(), msg.getSubscriptionInfo()); | ||
279 | } | 249 | } |
280 | } | 250 | } |
281 | 251 | ||
282 | - private void reportActivity() { | 252 | + private void reportLogicalDeviceActivity() { |
283 | systemContext.getDeviceStateService().onDeviceActivity(deviceId); | 253 | systemContext.getDeviceStateService().onDeviceActivity(deviceId); |
284 | } | 254 | } |
285 | 255 | ||
@@ -291,27 +261,27 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -291,27 +261,27 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
291 | systemContext.getDeviceStateService().onDeviceDisconnect(deviceId); | 261 | systemContext.getDeviceStateService().onDeviceDisconnect(deviceId); |
292 | } | 262 | } |
293 | 263 | ||
294 | - private void handleGetAttributesRequest(DeviceToDeviceActorMsg src) { | ||
295 | - GetAttributesRequest request = (GetAttributesRequest) src.getPayload(); | ||
296 | - ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, request.getClientAttributeNames()); | ||
297 | - ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, request.getSharedAttributeNames()); | ||
298 | - | 264 | + private void handleGetAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { |
265 | + ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, toOptionalSet(request.getClientAttributeNamesList())); | ||
266 | + ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, toOptionalSet(request.getSharedAttributeNamesList())); | ||
267 | + int requestId = request.getRequestId(); | ||
299 | Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback<List<List<AttributeKvEntry>>>() { | 268 | Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback<List<List<AttributeKvEntry>>>() { |
300 | @Override | 269 | @Override |
301 | public void onSuccess(@Nullable List<List<AttributeKvEntry>> result) { | 270 | public void onSuccess(@Nullable List<List<AttributeKvEntry>> result) { |
302 | - BasicGetAttributesResponse response = BasicGetAttributesResponse.onSuccess(request.getMsgType(), | ||
303 | - request.getRequestId(), BasicAttributeKVMsg.from(result.get(0), result.get(1))); | ||
304 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(response, src.getSessionId()), src.getServerAddress()); | 271 | + GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() |
272 | + .setRequestId(requestId) | ||
273 | + .addAllClientAttributeList(toTsKvProtos(result.get(0))) | ||
274 | + .addAllSharedAttributeList(toTsKvProtos(result.get(1))) | ||
275 | + .build(); | ||
276 | + sendToTransport(responseMsg, sessionInfo); | ||
305 | } | 277 | } |
306 | 278 | ||
307 | @Override | 279 | @Override |
308 | public void onFailure(Throwable t) { | 280 | public void onFailure(Throwable t) { |
309 | - if (t instanceof Exception) { | ||
310 | - ToDeviceMsg toDeviceMsg = BasicStatusCodeResponse.onError(SessionMsgType.GET_ATTRIBUTES_REQUEST, request.getRequestId(), (Exception) t); | ||
311 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(toDeviceMsg, src.getSessionId()), src.getServerAddress()); | ||
312 | - } else { | ||
313 | - logger.error("[{}] Failed to process attributes request", deviceId, t); | ||
314 | - } | 281 | + GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() |
282 | + .setError(t.getMessage()) | ||
283 | + .build(); | ||
284 | + sendToTransport(responseMsg, sessionInfo); | ||
315 | } | 285 | } |
316 | }); | 286 | }); |
317 | } | 287 | } |
@@ -328,220 +298,221 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -328,220 +298,221 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
328 | } | 298 | } |
329 | } | 299 | } |
330 | 300 | ||
331 | - private void handlePostAttributesRequest(ActorContext context, DeviceToDeviceActorMsg src) { | ||
332 | - AttributesUpdateRequest request = (AttributesUpdateRequest) src.getPayload(); | ||
333 | - | ||
334 | - JsonObject json = new JsonObject(); | ||
335 | - for (AttributeKvEntry kv : request.getAttributes()) { | ||
336 | - kv.getBooleanValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
337 | - kv.getLongValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
338 | - kv.getDoubleValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
339 | - kv.getStrValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
340 | - } | ||
341 | - | ||
342 | - TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), deviceId, defaultMetaData.copy(), TbMsgDataType.JSON, gson.toJson(json), null, null, 0L); | ||
343 | - PendingSessionMsgData msgData = new PendingSessionMsgData(src.getSessionId(), src.getServerAddress(), | ||
344 | - SessionMsgType.POST_ATTRIBUTES_REQUEST, request.getRequestId(), true, 1); | ||
345 | - pushToRuleEngineWithTimeout(context, tbMsg, msgData); | 301 | + private void handlePostAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, PostAttributeMsg postAttributes) { |
302 | + JsonObject json = getJsonObject(postAttributes.getKvList()); | ||
303 | + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), deviceId, defaultMetaData.copy(), | ||
304 | + TbMsgDataType.JSON, gson.toJson(json), null, null, 0L); | ||
305 | + pushToRuleEngine(context, tbMsg); | ||
346 | } | 306 | } |
347 | 307 | ||
348 | - private void handlePostTelemetryRequest(ActorContext context, DeviceToDeviceActorMsg src) { | ||
349 | - TelemetryUploadRequest request = (TelemetryUploadRequest) src.getPayload(); | ||
350 | - | ||
351 | - Map<Long, List<KvEntry>> tsData = request.getData(); | ||
352 | - | ||
353 | - PendingSessionMsgData msgData = new PendingSessionMsgData(src.getSessionId(), src.getServerAddress(), | ||
354 | - SessionMsgType.POST_TELEMETRY_REQUEST, request.getRequestId(), true, tsData.size()); | ||
355 | - | ||
356 | - for (Map.Entry<Long, List<KvEntry>> entry : tsData.entrySet()) { | ||
357 | - JsonObject json = new JsonObject(); | ||
358 | - for (KvEntry kv : entry.getValue()) { | ||
359 | - kv.getBooleanValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
360 | - kv.getLongValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
361 | - kv.getDoubleValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
362 | - kv.getStrValue().ifPresent(v -> json.addProperty(kv.getKey(), v)); | ||
363 | - } | 308 | + private void handlePostTelemetryRequest(ActorContext context, SessionInfoProto sessionInfo, PostTelemetryMsg postTelemetry) { |
309 | + for (TsKvListProto tsKv : postTelemetry.getTsKvListList()) { | ||
310 | + JsonObject json = getJsonObject(tsKv.getKvList()); | ||
364 | TbMsgMetaData metaData = defaultMetaData.copy(); | 311 | TbMsgMetaData metaData = defaultMetaData.copy(); |
365 | - metaData.putValue("ts", entry.getKey() + ""); | 312 | + metaData.putValue("ts", tsKv.getTs() + ""); |
366 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_TELEMETRY_REQUEST.name(), deviceId, metaData, TbMsgDataType.JSON, gson.toJson(json), null, null, 0L); | 313 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_TELEMETRY_REQUEST.name(), deviceId, metaData, TbMsgDataType.JSON, gson.toJson(json), null, null, 0L); |
367 | - pushToRuleEngineWithTimeout(context, tbMsg, msgData); | 314 | + pushToRuleEngine(context, tbMsg); |
368 | } | 315 | } |
369 | } | 316 | } |
370 | 317 | ||
371 | - private void handleClientSideRPCRequest(ActorContext context, DeviceToDeviceActorMsg src) { | ||
372 | - ToServerRpcRequestMsg request = (ToServerRpcRequestMsg) src.getPayload(); | ||
373 | - | 318 | + private void handleClientSideRPCRequest(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.ToServerRpcRequestMsg request) { |
319 | + UUID sessionId = getSessionId(sessionInfo); | ||
374 | JsonObject json = new JsonObject(); | 320 | JsonObject json = new JsonObject(); |
375 | - json.addProperty("method", request.getMethod()); | 321 | + json.addProperty("method", request.getMethodName()); |
376 | json.add("params", jsonParser.parse(request.getParams())); | 322 | json.add("params", jsonParser.parse(request.getParams())); |
377 | 323 | ||
378 | TbMsgMetaData requestMetaData = defaultMetaData.copy(); | 324 | TbMsgMetaData requestMetaData = defaultMetaData.copy(); |
379 | requestMetaData.putValue("requestId", Integer.toString(request.getRequestId())); | 325 | requestMetaData.putValue("requestId", Integer.toString(request.getRequestId())); |
380 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.TO_SERVER_RPC_REQUEST.name(), deviceId, requestMetaData, TbMsgDataType.JSON, gson.toJson(json), null, null, 0L); | 326 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.TO_SERVER_RPC_REQUEST.name(), deviceId, requestMetaData, TbMsgDataType.JSON, gson.toJson(json), null, null, 0L); |
381 | - PendingSessionMsgData msgData = new PendingSessionMsgData(src.getSessionId(), src.getServerAddress(), SessionMsgType.TO_SERVER_RPC_REQUEST, request.getRequestId(), false, 1); | ||
382 | - pushToRuleEngineWithTimeout(context, tbMsg, msgData); | 327 | + context.parent().tell(new DeviceActorToRuleEngineMsg(context.self(), tbMsg), context.self()); |
383 | 328 | ||
384 | scheduleMsgWithDelay(context, new DeviceActorClientSideRpcTimeoutMsg(request.getRequestId(), systemContext.getClientSideRpcTimeout()), systemContext.getClientSideRpcTimeout()); | 329 | scheduleMsgWithDelay(context, new DeviceActorClientSideRpcTimeoutMsg(request.getRequestId(), systemContext.getClientSideRpcTimeout()), systemContext.getClientSideRpcTimeout()); |
385 | - toServerRpcPendingMap.put(request.getRequestId(), new ToServerRpcRequestMetadata(src.getSessionId(), src.getSessionType(), src.getServerAddress())); | 330 | + toServerRpcPendingMap.put(request.getRequestId(), new ToServerRpcRequestMetadata(sessionId, getSessionType(sessionId), sessionInfo.getNodeId())); |
331 | + } | ||
332 | + | ||
333 | + private TransportProtos.SessionType getSessionType(UUID sessionId) { | ||
334 | + return sessions.containsKey(sessionId) ? TransportProtos.SessionType.ASYNC : TransportProtos.SessionType.SYNC; | ||
386 | } | 335 | } |
387 | 336 | ||
388 | - public void processClientSideRpcTimeout(ActorContext context, DeviceActorClientSideRpcTimeoutMsg msg) { | 337 | + void processClientSideRpcTimeout(ActorContext context, DeviceActorClientSideRpcTimeoutMsg msg) { |
389 | ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(msg.getId()); | 338 | ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(msg.getId()); |
390 | if (data != null) { | 339 | if (data != null) { |
391 | - logger.debug("[{}] Client side RPC request [{}] timeout detected!", deviceId, msg.getId()); | ||
392 | - ToDeviceMsg toDeviceMsg = new RuleEngineErrorMsg(SessionMsgType.TO_SERVER_RPC_REQUEST, RuleEngineError.TIMEOUT); | ||
393 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(toDeviceMsg, data.getSessionId()), data.getServer()); | 340 | + log.debug("[{}] Client side RPC request [{}] timeout detected!", deviceId, msg.getId()); |
341 | + sendToTransport(TransportProtos.ToServerRpcResponseMsg.newBuilder() | ||
342 | + .setRequestId(msg.getId()).setError("timeout").build() | ||
343 | + , data.getSessionId(), data.getNodeId()); | ||
394 | } | 344 | } |
395 | } | 345 | } |
396 | 346 | ||
397 | void processToServerRPCResponse(ActorContext context, ToServerRpcResponseActorMsg msg) { | 347 | void processToServerRPCResponse(ActorContext context, ToServerRpcResponseActorMsg msg) { |
398 | - ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(msg.getMsg().getRequestId()); | 348 | + int requestId = msg.getMsg().getRequestId(); |
349 | + ToServerRpcRequestMetadata data = toServerRpcPendingMap.remove(requestId); | ||
399 | if (data != null) { | 350 | if (data != null) { |
400 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(msg.getMsg(), data.getSessionId()), data.getServer()); | 351 | + log.debug("[{}] Pushing reply to [{}][{}]!", deviceId, data.getNodeId(), data.getSessionId()); |
352 | + sendToTransport(TransportProtos.ToServerRpcResponseMsg.newBuilder() | ||
353 | + .setRequestId(requestId).setPayload(msg.getMsg().getData()).build() | ||
354 | + , data.getSessionId(), data.getNodeId()); | ||
355 | + } else { | ||
356 | + log.debug("[{}][{}] Pending RPC request to server not found!", deviceId, requestId); | ||
401 | } | 357 | } |
402 | } | 358 | } |
403 | 359 | ||
404 | - private void pushToRuleEngineWithTimeout(ActorContext context, TbMsg tbMsg, PendingSessionMsgData pendingMsgData) { | ||
405 | - SessionMsgType sessionMsgType = pendingMsgData.getSessionMsgType(); | ||
406 | - int requestId = pendingMsgData.getRequestId(); | ||
407 | - if (systemContext.isQueuePersistenceEnabled()) { | ||
408 | - pendingMsgs.put(tbMsg.getId(), pendingMsgData); | ||
409 | - scheduleMsgWithDelay(context, new DeviceActorQueueTimeoutMsg(tbMsg.getId(), systemContext.getQueuePersistenceTimeout()), systemContext.getQueuePersistenceTimeout()); | ||
410 | - } else { | ||
411 | - ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(BasicStatusCodeResponse.onSuccess(sessionMsgType, requestId), pendingMsgData.getSessionId()); | ||
412 | - sendMsgToSessionActor(response, pendingMsgData.getServerAddress()); | ||
413 | - } | 360 | + private void pushToRuleEngine(ActorContext context, TbMsg tbMsg) { |
414 | context.parent().tell(new DeviceActorToRuleEngineMsg(context.self(), tbMsg), context.self()); | 361 | context.parent().tell(new DeviceActorToRuleEngineMsg(context.self(), tbMsg), context.self()); |
415 | } | 362 | } |
416 | 363 | ||
417 | void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) { | 364 | void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) { |
418 | if (attributeSubscriptions.size() > 0) { | 365 | if (attributeSubscriptions.size() > 0) { |
419 | - ToDeviceMsg notification = null; | 366 | + boolean hasNotificationData = false; |
367 | + AttributeUpdateNotificationMsg.Builder notification = AttributeUpdateNotificationMsg.newBuilder(); | ||
420 | if (msg.isDeleted()) { | 368 | if (msg.isDeleted()) { |
421 | - List<AttributeKey> sharedKeys = msg.getDeletedKeys().stream() | 369 | + List<String> sharedKeys = msg.getDeletedKeys().stream() |
422 | .filter(key -> DataConstants.SHARED_SCOPE.equals(key.getScope())) | 370 | .filter(key -> DataConstants.SHARED_SCOPE.equals(key.getScope())) |
371 | + .map(AttributeKey::getAttributeKey) | ||
423 | .collect(Collectors.toList()); | 372 | .collect(Collectors.toList()); |
424 | - notification = new AttributesUpdateNotification(BasicAttributeKVMsg.fromDeleted(sharedKeys)); | 373 | + if (!sharedKeys.isEmpty()) { |
374 | + notification.addAllSharedDeleted(sharedKeys); | ||
375 | + hasNotificationData = true; | ||
376 | + } | ||
425 | } else { | 377 | } else { |
426 | if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) { | 378 | if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) { |
427 | List<AttributeKvEntry> attributes = new ArrayList<>(msg.getValues()); | 379 | List<AttributeKvEntry> attributes = new ArrayList<>(msg.getValues()); |
428 | if (attributes.size() > 0) { | 380 | if (attributes.size() > 0) { |
429 | - notification = new AttributesUpdateNotification(BasicAttributeKVMsg.fromShared(attributes)); | 381 | + List<TsKvProto> sharedUpdated = msg.getValues().stream().map(this::toTsKvProto) |
382 | + .collect(Collectors.toList()); | ||
383 | + if (!sharedUpdated.isEmpty()) { | ||
384 | + notification.addAllSharedUpdated(sharedUpdated); | ||
385 | + hasNotificationData = true; | ||
386 | + } | ||
430 | } else { | 387 | } else { |
431 | - logger.debug("[{}] No public server side attributes changed!", deviceId); | 388 | + log.debug("[{}] No public server side attributes changed!", deviceId); |
432 | } | 389 | } |
433 | } | 390 | } |
434 | } | 391 | } |
435 | - if (notification != null) { | ||
436 | - ToDeviceMsg finalNotification = notification; | 392 | + if (hasNotificationData) { |
393 | + AttributeUpdateNotificationMsg finalNotification = notification.build(); | ||
437 | attributeSubscriptions.entrySet().forEach(sub -> { | 394 | attributeSubscriptions.entrySet().forEach(sub -> { |
438 | - ActorSystemToDeviceSessionActorMsg response = new BasicActorSystemToDeviceSessionActorMsg(finalNotification, sub.getKey()); | ||
439 | - sendMsgToSessionActor(response, sub.getValue().getServer()); | 395 | + sendToTransport(finalNotification, sub.getKey(), sub.getValue().getNodeId()); |
440 | }); | 396 | }); |
441 | } | 397 | } |
442 | } else { | 398 | } else { |
443 | - logger.debug("[{}] No registered attributes subscriptions to process!", deviceId); | 399 | + log.debug("[{}] No registered attributes subscriptions to process!", deviceId); |
444 | } | 400 | } |
445 | } | 401 | } |
446 | 402 | ||
447 | - private void processRpcResponses(ActorContext context, DeviceToDeviceActorMsg msg) { | ||
448 | - SessionId sessionId = msg.getSessionId(); | ||
449 | - FromDeviceMsg inMsg = msg.getPayload(); | ||
450 | - if (inMsg.getMsgType() == SessionMsgType.TO_DEVICE_RPC_RESPONSE) { | ||
451 | - logger.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId); | ||
452 | - ToDeviceRpcResponseMsg responseMsg = (ToDeviceRpcResponseMsg) inMsg; | ||
453 | - ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); | ||
454 | - boolean success = requestMd != null; | ||
455 | - if (success) { | ||
456 | - systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | ||
457 | - requestMd.getMsg().getServerAddress(), responseMsg.getData(), null)); | ||
458 | - } else { | ||
459 | - logger.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId()); | ||
460 | - } | ||
461 | - if (msg.getSessionType() == SessionType.SYNC) { | ||
462 | - BasicCommandAckResponse response = success | ||
463 | - ? BasicCommandAckResponse.onSuccess(SessionMsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId()) | ||
464 | - : BasicCommandAckResponse.onError(SessionMsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId(), new TimeoutException()); | ||
465 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(response, msg.getSessionId()), msg.getServerAddress()); | ||
466 | - } | 403 | + private void processRpcResponses(ActorContext context, SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg responseMsg) { |
404 | + UUID sessionId = getSessionId(sessionInfo); | ||
405 | + log.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId); | ||
406 | + ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); | ||
407 | + boolean success = requestMd != null; | ||
408 | + if (success) { | ||
409 | + systemContext.getDeviceRpcService().processResponseToServerSideRPCRequestFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | ||
410 | + responseMsg.getPayload(), null)); | ||
411 | + } else { | ||
412 | + log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId()); | ||
467 | } | 413 | } |
468 | } | 414 | } |
469 | 415 | ||
470 | - void processClusterEventMsg(ClusterEventMsg msg) { | ||
471 | - if (!msg.isAdded()) { | ||
472 | - logger.debug("[{}] Clearing attributes/rpc subscription for server [{}]", deviceId, msg.getServerAddress()); | ||
473 | - Predicate<Map.Entry<SessionId, SessionInfo>> filter = e -> e.getValue().getServer() | ||
474 | - .map(serverAddress -> serverAddress.equals(msg.getServerAddress())).orElse(false); | ||
475 | - attributeSubscriptions.entrySet().removeIf(filter); | ||
476 | - rpcSubscriptions.entrySet().removeIf(filter); | 416 | + private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { |
417 | + UUID sessionId = getSessionId(sessionInfo); | ||
418 | + if (subscribeCmd.getUnsubscribe()) { | ||
419 | + log.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); | ||
420 | + attributeSubscriptions.remove(sessionId); | ||
421 | + } else { | ||
422 | + SessionInfoMetaData sessionMD = sessions.get(sessionId); | ||
423 | + if (sessionMD == null) { | ||
424 | + sessionMD = new SessionInfoMetaData(new SessionInfo(TransportProtos.SessionType.SYNC, sessionInfo.getNodeId())); | ||
425 | + } | ||
426 | + sessionMD.setSubscribedToAttributes(true); | ||
427 | + log.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId); | ||
428 | + attributeSubscriptions.put(sessionId, sessionMD.getSessionInfo()); | ||
429 | + dumpSessions(); | ||
477 | } | 430 | } |
478 | } | 431 | } |
479 | 432 | ||
480 | - private void processSubscriptionCommands(ActorContext context, DeviceToDeviceActorMsg msg) { | ||
481 | - SessionId sessionId = msg.getSessionId(); | ||
482 | - SessionType sessionType = msg.getSessionType(); | ||
483 | - FromDeviceMsg inMsg = msg.getPayload(); | ||
484 | - if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_ATTRIBUTES_REQUEST) { | ||
485 | - logger.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId); | ||
486 | - attributeSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress())); | ||
487 | - } else if (inMsg.getMsgType() == SessionMsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST) { | ||
488 | - logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); | ||
489 | - attributeSubscriptions.remove(sessionId); | ||
490 | - } else if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST) { | ||
491 | - logger.debug("[{}] Registering rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType); | ||
492 | - rpcSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress())); | ||
493 | - sendPendingRequests(context, sessionId, sessionType, msg.getServerAddress()); | ||
494 | - } else if (inMsg.getMsgType() == SessionMsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST) { | ||
495 | - logger.debug("[{}] Canceling rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType); | 433 | + private UUID getSessionId(SessionInfoProto sessionInfo) { |
434 | + return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | ||
435 | + } | ||
436 | + | ||
437 | + private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToRPCMsg subscribeCmd) { | ||
438 | + UUID sessionId = getSessionId(sessionInfo); | ||
439 | + if (subscribeCmd.getUnsubscribe()) { | ||
440 | + log.debug("[{}] Canceling rpc subscription for session [{}]", deviceId, sessionId); | ||
496 | rpcSubscriptions.remove(sessionId); | 441 | rpcSubscriptions.remove(sessionId); |
442 | + } else { | ||
443 | + SessionInfoMetaData sessionMD = sessions.get(sessionId); | ||
444 | + if (sessionMD == null) { | ||
445 | + sessionMD = new SessionInfoMetaData(new SessionInfo(TransportProtos.SessionType.SYNC, sessionInfo.getNodeId())); | ||
446 | + } | ||
447 | + sessionMD.setSubscribedToRPC(true); | ||
448 | + log.debug("[{}] Registering rpc subscription for session [{}]", deviceId, sessionId); | ||
449 | + rpcSubscriptions.put(sessionId, sessionMD.getSessionInfo()); | ||
450 | + sendPendingRequests(context, sessionId, sessionInfo); | ||
451 | + dumpSessions(); | ||
497 | } | 452 | } |
498 | } | 453 | } |
499 | 454 | ||
500 | - private void processSessionStateMsgs(DeviceToDeviceActorMsg msg) { | ||
501 | - SessionId sessionId = msg.getSessionId(); | ||
502 | - FromDeviceMsg inMsg = msg.getPayload(); | ||
503 | - if (inMsg instanceof SessionOpenMsg) { | ||
504 | - logger.debug("[{}] Processing new session [{}]", deviceId, sessionId); | 455 | + private void processSessionStateMsgs(SessionInfoProto sessionInfo, SessionEventMsg msg) { |
456 | + UUID sessionId = getSessionId(sessionInfo); | ||
457 | + if (msg.getEvent() == SessionEvent.OPEN) { | ||
458 | + if (sessions.containsKey(sessionId)) { | ||
459 | + log.debug("[{}] Received duplicate session open event [{}]", deviceId, sessionId); | ||
460 | + return; | ||
461 | + } | ||
462 | + log.debug("[{}] Processing new session [{}]", deviceId, sessionId); | ||
505 | if (sessions.size() >= systemContext.getMaxConcurrentSessionsPerDevice()) { | 463 | if (sessions.size() >= systemContext.getMaxConcurrentSessionsPerDevice()) { |
506 | - SessionId sessionIdToRemove = sessions.keySet().stream().findFirst().orElse(null); | 464 | + UUID sessionIdToRemove = sessions.keySet().stream().findFirst().orElse(null); |
507 | if (sessionIdToRemove != null) { | 465 | if (sessionIdToRemove != null) { |
508 | - closeSession(sessionIdToRemove, sessions.remove(sessionIdToRemove)); | 466 | + notifyTransportAboutClosedSession(sessionIdToRemove, sessions.remove(sessionIdToRemove)); |
509 | } | 467 | } |
510 | } | 468 | } |
511 | - sessions.put(sessionId, new SessionInfo(SessionType.ASYNC, msg.getServerAddress())); | 469 | + sessions.put(sessionId, new SessionInfoMetaData(new SessionInfo(TransportProtos.SessionType.ASYNC, sessionInfo.getNodeId()))); |
512 | if (sessions.size() == 1) { | 470 | if (sessions.size() == 1) { |
513 | reportSessionOpen(); | 471 | reportSessionOpen(); |
514 | } | 472 | } |
515 | - } else if (inMsg instanceof SessionCloseMsg) { | ||
516 | - logger.debug("[{}] Canceling subscriptions for closed session [{}]", deviceId, sessionId); | 473 | + dumpSessions(); |
474 | + } else if (msg.getEvent() == SessionEvent.CLOSED) { | ||
475 | + log.debug("[{}] Canceling subscriptions for closed session [{}]", deviceId, sessionId); | ||
517 | sessions.remove(sessionId); | 476 | sessions.remove(sessionId); |
518 | attributeSubscriptions.remove(sessionId); | 477 | attributeSubscriptions.remove(sessionId); |
519 | rpcSubscriptions.remove(sessionId); | 478 | rpcSubscriptions.remove(sessionId); |
520 | if (sessions.isEmpty()) { | 479 | if (sessions.isEmpty()) { |
521 | reportSessionClose(); | 480 | reportSessionClose(); |
522 | } | 481 | } |
482 | + dumpSessions(); | ||
523 | } | 483 | } |
524 | } | 484 | } |
525 | 485 | ||
526 | - private void sendMsgToSessionActor(ActorSystemToDeviceSessionActorMsg response, Optional<ServerAddress> sessionAddress) { | ||
527 | - if (sessionAddress.isPresent()) { | ||
528 | - ServerAddress address = sessionAddress.get(); | ||
529 | - logger.debug("{} Forwarding msg: {}", address, response); | ||
530 | - systemContext.getRpcService().tell(systemContext.getEncodingService() | ||
531 | - .convertToProtoDataMessage(sessionAddress.get(), response)); | ||
532 | - } else { | ||
533 | - systemContext.getSessionManagerActor().tell(response, ActorRef.noSender()); | 486 | + private void handleSessionActivity(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.SubscriptionInfoProto subscriptionInfo) { |
487 | + UUID sessionId = getSessionId(sessionInfo); | ||
488 | + SessionInfoMetaData sessionMD = sessions.get(sessionId); | ||
489 | + if (sessionMD != null) { | ||
490 | + sessionMD.setLastActivityTime(subscriptionInfo.getLastActivityTime()); | ||
491 | + sessionMD.setSubscribedToAttributes(subscriptionInfo.getAttributeSubscription()); | ||
492 | + sessionMD.setSubscribedToRPC(subscriptionInfo.getRpcSubscription()); | ||
493 | + if (subscriptionInfo.getAttributeSubscription()) { | ||
494 | + attributeSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); | ||
495 | + } | ||
496 | + if (subscriptionInfo.getRpcSubscription()) { | ||
497 | + rpcSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); | ||
498 | + } | ||
534 | } | 499 | } |
500 | + dumpSessions(); | ||
535 | } | 501 | } |
536 | 502 | ||
537 | void processCredentialsUpdate() { | 503 | void processCredentialsUpdate() { |
538 | - sessions.forEach(this::closeSession); | 504 | + sessions.forEach(this::notifyTransportAboutClosedSession); |
539 | attributeSubscriptions.clear(); | 505 | attributeSubscriptions.clear(); |
540 | rpcSubscriptions.clear(); | 506 | rpcSubscriptions.clear(); |
507 | + dumpSessions(); | ||
541 | } | 508 | } |
542 | 509 | ||
543 | - private void closeSession(SessionId sessionId, SessionInfo sessionInfo) { | ||
544 | - sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(new SessionCloseNotification(), sessionId), sessionInfo.getServer()); | 510 | + private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) { |
511 | + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | ||
512 | + .setSessionIdMSB(sessionId.getMostSignificantBits()) | ||
513 | + .setSessionIdLSB(sessionId.getLeastSignificantBits()) | ||
514 | + .setSessionCloseNotification(SessionCloseNotificationProto.getDefaultInstance()).build(); | ||
515 | + systemContext.getRuleEngineTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg); | ||
545 | } | 516 | } |
546 | 517 | ||
547 | void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { | 518 | void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { |
@@ -552,4 +523,178 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -552,4 +523,178 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | ||
552 | this.defaultMetaData.putValue("deviceType", deviceType); | 523 | this.defaultMetaData.putValue("deviceType", deviceType); |
553 | } | 524 | } |
554 | 525 | ||
526 | + private JsonObject getJsonObject(List<KeyValueProto> tsKv) { | ||
527 | + JsonObject json = new JsonObject(); | ||
528 | + for (KeyValueProto kv : tsKv) { | ||
529 | + switch (kv.getType()) { | ||
530 | + case BOOLEAN_V: | ||
531 | + json.addProperty(kv.getKey(), kv.getBoolV()); | ||
532 | + break; | ||
533 | + case LONG_V: | ||
534 | + json.addProperty(kv.getKey(), kv.getLongV()); | ||
535 | + break; | ||
536 | + case DOUBLE_V: | ||
537 | + json.addProperty(kv.getKey(), kv.getDoubleV()); | ||
538 | + break; | ||
539 | + case STRING_V: | ||
540 | + json.addProperty(kv.getKey(), kv.getStringV()); | ||
541 | + break; | ||
542 | + } | ||
543 | + } | ||
544 | + return json; | ||
545 | + } | ||
546 | + | ||
547 | + private Optional<Set<String>> toOptionalSet(List<String> strings) { | ||
548 | + if (strings == null || strings.isEmpty()) { | ||
549 | + return Optional.empty(); | ||
550 | + } else { | ||
551 | + return Optional.of(new HashSet<>(strings)); | ||
552 | + } | ||
553 | + } | ||
554 | + | ||
555 | + private void sendToTransport(GetAttributeResponseMsg responseMsg, SessionInfoProto sessionInfo) { | ||
556 | + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | ||
557 | + .setSessionIdMSB(sessionInfo.getSessionIdMSB()) | ||
558 | + .setSessionIdLSB(sessionInfo.getSessionIdLSB()) | ||
559 | + .setGetAttributesResponse(responseMsg).build(); | ||
560 | + systemContext.getRuleEngineTransportService().process(sessionInfo.getNodeId(), msg); | ||
561 | + } | ||
562 | + | ||
563 | + private void sendToTransport(AttributeUpdateNotificationMsg notificationMsg, UUID sessionId, String nodeId) { | ||
564 | + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | ||
565 | + .setSessionIdMSB(sessionId.getMostSignificantBits()) | ||
566 | + .setSessionIdLSB(sessionId.getLeastSignificantBits()) | ||
567 | + .setAttributeUpdateNotification(notificationMsg).build(); | ||
568 | + systemContext.getRuleEngineTransportService().process(nodeId, msg); | ||
569 | + } | ||
570 | + | ||
571 | + private void sendToTransport(ToDeviceRpcRequestMsg rpcMsg, UUID sessionId, String nodeId) { | ||
572 | + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | ||
573 | + .setSessionIdMSB(sessionId.getMostSignificantBits()) | ||
574 | + .setSessionIdLSB(sessionId.getLeastSignificantBits()) | ||
575 | + .setToDeviceRequest(rpcMsg).build(); | ||
576 | + systemContext.getRuleEngineTransportService().process(nodeId, msg); | ||
577 | + } | ||
578 | + | ||
579 | + private void sendToTransport(TransportProtos.ToServerRpcResponseMsg rpcMsg, UUID sessionId, String nodeId) { | ||
580 | + DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() | ||
581 | + .setSessionIdMSB(sessionId.getMostSignificantBits()) | ||
582 | + .setSessionIdLSB(sessionId.getLeastSignificantBits()) | ||
583 | + .setToServerResponse(rpcMsg).build(); | ||
584 | + systemContext.getRuleEngineTransportService().process(nodeId, msg); | ||
585 | + } | ||
586 | + | ||
587 | + | ||
588 | + private List<TsKvProto> toTsKvProtos(@Nullable List<AttributeKvEntry> result) { | ||
589 | + List<TsKvProto> clientAttributes; | ||
590 | + if (result == null || result.isEmpty()) { | ||
591 | + clientAttributes = Collections.emptyList(); | ||
592 | + } else { | ||
593 | + clientAttributes = new ArrayList<>(result.size()); | ||
594 | + for (AttributeKvEntry attrEntry : result) { | ||
595 | + clientAttributes.add(toTsKvProto(attrEntry)); | ||
596 | + } | ||
597 | + } | ||
598 | + return clientAttributes; | ||
599 | + } | ||
600 | + | ||
601 | + private TsKvProto toTsKvProto(AttributeKvEntry attrEntry) { | ||
602 | + return TsKvProto.newBuilder().setTs(attrEntry.getLastUpdateTs()) | ||
603 | + .setKv(toKeyValueProto(attrEntry)).build(); | ||
604 | + } | ||
605 | + | ||
606 | + private KeyValueProto toKeyValueProto(KvEntry kvEntry) { | ||
607 | + KeyValueProto.Builder builder = KeyValueProto.newBuilder(); | ||
608 | + builder.setKey(kvEntry.getKey()); | ||
609 | + switch (kvEntry.getDataType()) { | ||
610 | + case BOOLEAN: | ||
611 | + builder.setType(KeyValueType.BOOLEAN_V); | ||
612 | + builder.setBoolV(kvEntry.getBooleanValue().get()); | ||
613 | + break; | ||
614 | + case DOUBLE: | ||
615 | + builder.setType(KeyValueType.DOUBLE_V); | ||
616 | + builder.setDoubleV(kvEntry.getDoubleValue().get()); | ||
617 | + break; | ||
618 | + case LONG: | ||
619 | + builder.setType(KeyValueType.LONG_V); | ||
620 | + builder.setLongV(kvEntry.getLongValue().get()); | ||
621 | + break; | ||
622 | + case STRING: | ||
623 | + builder.setType(KeyValueType.STRING_V); | ||
624 | + builder.setStringV(kvEntry.getStrValue().get()); | ||
625 | + break; | ||
626 | + } | ||
627 | + return builder.build(); | ||
628 | + } | ||
629 | + | ||
630 | + private void restoreSessions() { | ||
631 | + log.debug("[{}] Restoring sessions from cache", deviceId); | ||
632 | + TransportProtos.DeviceSessionsCacheEntry sessionsDump = systemContext.getDeviceSessionCacheService().get(deviceId); | ||
633 | + if (sessionsDump.getSerializedSize() == 0) { | ||
634 | + log.debug("[{}] No session information found", deviceId); | ||
635 | + return; | ||
636 | + } | ||
637 | + for (TransportProtos.SessionSubscriptionInfoProto sessionSubscriptionInfoProto : sessionsDump.getSessionsList()) { | ||
638 | + SessionInfoProto sessionInfoProto = sessionSubscriptionInfoProto.getSessionInfo(); | ||
639 | + UUID sessionId = getSessionId(sessionInfoProto); | ||
640 | + SessionInfo sessionInfo = new SessionInfo(TransportProtos.SessionType.ASYNC, sessionInfoProto.getNodeId()); | ||
641 | + TransportProtos.SubscriptionInfoProto subInfo = sessionSubscriptionInfoProto.getSubscriptionInfo(); | ||
642 | + SessionInfoMetaData sessionMD = new SessionInfoMetaData(sessionInfo, subInfo.getLastActivityTime()); | ||
643 | + sessions.put(sessionId, sessionMD); | ||
644 | + if (subInfo.getAttributeSubscription()) { | ||
645 | + attributeSubscriptions.put(sessionId, sessionInfo); | ||
646 | + sessionMD.setSubscribedToAttributes(true); | ||
647 | + } | ||
648 | + if (subInfo.getRpcSubscription()) { | ||
649 | + rpcSubscriptions.put(sessionId, sessionInfo); | ||
650 | + sessionMD.setSubscribedToRPC(true); | ||
651 | + } | ||
652 | + log.debug("[{}] Restored session: {}", deviceId, sessionMD); | ||
653 | + } | ||
654 | + log.debug("[{}] Restored sessions: {}, rpc subscriptions: {}, attribute subscriptions: {}", deviceId, sessions.size(), rpcSubscriptions.size(), attributeSubscriptions.size()); | ||
655 | + } | ||
656 | + | ||
657 | + private void dumpSessions() { | ||
658 | + log.debug("[{}] Dumping sessions: {}, rpc subscriptions: {}, attribute subscriptions: {} to cache", deviceId, sessions.size(), rpcSubscriptions.size(), attributeSubscriptions.size()); | ||
659 | + List<TransportProtos.SessionSubscriptionInfoProto> sessionsList = new ArrayList<>(sessions.size()); | ||
660 | + sessions.forEach((uuid, sessionMD) -> { | ||
661 | + if (sessionMD.getSessionInfo().getType() == TransportProtos.SessionType.SYNC) { | ||
662 | + return; | ||
663 | + } | ||
664 | + SessionInfo sessionInfo = sessionMD.getSessionInfo(); | ||
665 | + TransportProtos.SubscriptionInfoProto subscriptionInfoProto = TransportProtos.SubscriptionInfoProto.newBuilder() | ||
666 | + .setLastActivityTime(sessionMD.getLastActivityTime()) | ||
667 | + .setAttributeSubscription(sessionMD.isSubscribedToAttributes()) | ||
668 | + .setRpcSubscription(sessionMD.isSubscribedToRPC()).build(); | ||
669 | + TransportProtos.SessionInfoProto sessionInfoProto = TransportProtos.SessionInfoProto.newBuilder() | ||
670 | + .setSessionIdMSB(uuid.getMostSignificantBits()) | ||
671 | + .setSessionIdLSB(uuid.getLeastSignificantBits()) | ||
672 | + .setNodeId(sessionInfo.getNodeId()).build(); | ||
673 | + sessionsList.add(TransportProtos.SessionSubscriptionInfoProto.newBuilder() | ||
674 | + .setSessionInfo(sessionInfoProto) | ||
675 | + .setSubscriptionInfo(subscriptionInfoProto).build()); | ||
676 | + log.debug("[{}] Dumping session: {}", deviceId, sessionMD); | ||
677 | + }); | ||
678 | + systemContext.getDeviceSessionCacheService() | ||
679 | + .put(deviceId, TransportProtos.DeviceSessionsCacheEntry.newBuilder() | ||
680 | + .addAllSessions(sessionsList).build()); | ||
681 | + } | ||
682 | + | ||
683 | + void initSessionTimeout(ActorContext context) { | ||
684 | + schedulePeriodicMsgWithDelay(context, SessionTimeoutCheckMsg.instance(), systemContext.getSessionInactivityTimeout(), systemContext.getSessionInactivityTimeout()); | ||
685 | + } | ||
686 | + | ||
687 | + void checkSessionsTimeout() { | ||
688 | + long expTime = System.currentTimeMillis() - systemContext.getSessionInactivityTimeout(); | ||
689 | + Map<UUID, SessionInfoMetaData> sessionsToRemove = sessions.entrySet().stream().filter(kv -> kv.getValue().getLastActivityTime() < expTime).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | ||
690 | + sessionsToRemove.forEach((sessionId, sessionMD) -> { | ||
691 | + sessions.remove(sessionId); | ||
692 | + rpcSubscriptions.remove(sessionId); | ||
693 | + attributeSubscriptions.remove(sessionId); | ||
694 | + notifyTransportAboutClosedSession(sessionId, sessionMD); | ||
695 | + }); | ||
696 | + if (!sessionsToRemove.isEmpty()) { | ||
697 | + dumpSessions(); | ||
698 | + } | ||
699 | + } | ||
555 | } | 700 | } |
@@ -16,10 +16,7 @@ | @@ -16,10 +16,7 @@ | ||
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
20 | -import org.thingsboard.server.common.msg.session.SessionType; | ||
21 | - | ||
22 | -import java.util.Optional; | 19 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionType; |
23 | 20 | ||
24 | /** | 21 | /** |
25 | * @author Andrew Shvayka | 22 | * @author Andrew Shvayka |
@@ -27,5 +24,6 @@ import java.util.Optional; | @@ -27,5 +24,6 @@ import java.util.Optional; | ||
27 | @Data | 24 | @Data |
28 | public class SessionInfo { | 25 | public class SessionInfo { |
29 | private final SessionType type; | 26 | private final SessionType type; |
30 | - private final Optional<ServerAddress> server; | 27 | + private final String nodeId; |
28 | + private long lastActivityTime; | ||
31 | } | 29 | } |
application/src/main/java/org/thingsboard/server/actors/device/SessionInfoMetaData.java
renamed from
common/message/src/main/java/org/thingsboard/server/common/msg/core/ToDeviceRpcResponseMsg.java
@@ -13,24 +13,27 @@ | @@ -13,24 +13,27 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.common.msg.core; | 16 | +package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | -import org.thingsboard.server.common.msg.session.FromDeviceMsg; | ||
20 | -import org.thingsboard.server.common.msg.session.SessionMsgType; | ||
21 | -import org.thingsboard.server.common.msg.session.SessionMsgType; | 19 | +import org.thingsboard.server.gen.transport.TransportProtos.SessionType; |
22 | 20 | ||
23 | /** | 21 | /** |
24 | * @author Andrew Shvayka | 22 | * @author Andrew Shvayka |
25 | */ | 23 | */ |
26 | @Data | 24 | @Data |
27 | -public class ToDeviceRpcResponseMsg implements FromDeviceMsg { | 25 | +class SessionInfoMetaData { |
26 | + private final SessionInfo sessionInfo; | ||
27 | + private long lastActivityTime; | ||
28 | + private boolean subscribedToAttributes; | ||
29 | + private boolean subscribedToRPC; | ||
28 | 30 | ||
29 | - private final int requestId; | ||
30 | - private final String data; | 31 | + SessionInfoMetaData(SessionInfo sessionInfo) { |
32 | + this(sessionInfo, System.currentTimeMillis()); | ||
33 | + } | ||
31 | 34 | ||
32 | - @Override | ||
33 | - public SessionMsgType getMsgType() { | ||
34 | - return SessionMsgType.TO_DEVICE_RPC_RESPONSE; | 35 | + SessionInfoMetaData(SessionInfo sessionInfo, long lastActivityTime) { |
36 | + this.sessionInfo = sessionInfo; | ||
37 | + this.lastActivityTime = lastActivityTime; | ||
35 | } | 38 | } |
36 | } | 39 | } |
application/src/main/java/org/thingsboard/server/actors/device/SessionTimeoutCheckMsg.java
renamed from
application/src/main/java/org/thingsboard/server/actors/device/RuleEngineQueuePutAckMsg.java
@@ -15,22 +15,25 @@ | @@ -15,22 +15,25 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | -import lombok.Data; | ||
19 | import org.thingsboard.server.common.msg.MsgType; | 18 | import org.thingsboard.server.common.msg.MsgType; |
20 | import org.thingsboard.server.common.msg.TbActorMsg; | 19 | import org.thingsboard.server.common.msg.TbActorMsg; |
21 | 20 | ||
22 | -import java.util.UUID; | ||
23 | - | ||
24 | /** | 21 | /** |
25 | - * Created by ashvayka on 15.03.18. | 22 | + * Created by ashvayka on 29.10.18. |
26 | */ | 23 | */ |
27 | -@Data | ||
28 | -public final class RuleEngineQueuePutAckMsg implements TbActorMsg { | 24 | +public class SessionTimeoutCheckMsg implements TbActorMsg { |
25 | + | ||
26 | + private static final SessionTimeoutCheckMsg INSTANCE = new SessionTimeoutCheckMsg(); | ||
29 | 27 | ||
30 | - private final UUID id; | 28 | + private SessionTimeoutCheckMsg() { |
29 | + } | ||
30 | + | ||
31 | + public static SessionTimeoutCheckMsg instance() { | ||
32 | + return INSTANCE; | ||
33 | + } | ||
31 | 34 | ||
32 | @Override | 35 | @Override |
33 | public MsgType getMsgType() { | 36 | public MsgType getMsgType() { |
34 | - return MsgType.RULE_ENGINE_QUEUE_PUT_ACK_MSG; | 37 | + return MsgType.SESSION_TIMEOUT_MSG; |
35 | } | 38 | } |
36 | } | 39 | } |
@@ -16,18 +16,16 @@ | @@ -16,18 +16,16 @@ | ||
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | -import org.thingsboard.server.common.data.id.SessionId; | ||
20 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
21 | -import org.thingsboard.server.common.msg.session.SessionType; | 19 | +import org.thingsboard.server.gen.transport.TransportProtos; |
22 | 20 | ||
23 | -import java.util.Optional; | 21 | +import java.util.UUID; |
24 | 22 | ||
25 | /** | 23 | /** |
26 | * @author Andrew Shvayka | 24 | * @author Andrew Shvayka |
27 | */ | 25 | */ |
28 | @Data | 26 | @Data |
29 | public class ToServerRpcRequestMetadata { | 27 | public class ToServerRpcRequestMetadata { |
30 | - private final SessionId sessionId; | ||
31 | - private final SessionType type; | ||
32 | - private final Optional<ServerAddress> server; | 28 | + private final UUID sessionId; |
29 | + private final TransportProtos.SessionType type; | ||
30 | + private final String nodeId; | ||
33 | } | 31 | } |
@@ -32,7 +32,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener { | @@ -32,7 +32,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener { | ||
32 | private final ActorRef manager; | 32 | private final ActorRef manager; |
33 | private final ActorRef self; | 33 | private final ActorRef self; |
34 | 34 | ||
35 | - public BasicRpcSessionListener(ActorService service, ActorRef manager, ActorRef self) { | 35 | + BasicRpcSessionListener(ActorService service, ActorRef manager, ActorRef self) { |
36 | this.service = service; | 36 | this.service = service; |
37 | this.manager = manager; | 37 | this.manager = manager; |
38 | this.self = self; | 38 | this.self = self; |
@@ -40,7 +40,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener { | @@ -40,7 +40,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener { | ||
40 | 40 | ||
41 | @Override | 41 | @Override |
42 | public void onConnected(GrpcSession session) { | 42 | public void onConnected(GrpcSession session) { |
43 | - log.info("{} session started -> {}", getType(session), session.getRemoteServer()); | 43 | + log.info("[{}][{}] session started", session.getRemoteServer(), getType(session)); |
44 | if (!session.isClient()) { | 44 | if (!session.isClient()) { |
45 | manager.tell(new RpcSessionConnectedMsg(session.getRemoteServer(), session.getSessionId()), self); | 45 | manager.tell(new RpcSessionConnectedMsg(session.getRemoteServer(), session.getSessionId()), self); |
46 | } | 46 | } |
@@ -48,21 +48,19 @@ public class BasicRpcSessionListener implements GrpcSessionListener { | @@ -48,21 +48,19 @@ public class BasicRpcSessionListener implements GrpcSessionListener { | ||
48 | 48 | ||
49 | @Override | 49 | @Override |
50 | public void onDisconnected(GrpcSession session) { | 50 | public void onDisconnected(GrpcSession session) { |
51 | - log.info("{} session closed -> {}", getType(session), session.getRemoteServer()); | 51 | + log.info("[{}][{}] session closed", session.getRemoteServer(), getType(session)); |
52 | manager.tell(new RpcSessionDisconnectedMsg(session.isClient(), session.getRemoteServer()), self); | 52 | manager.tell(new RpcSessionDisconnectedMsg(session.isClient(), session.getRemoteServer()), self); |
53 | } | 53 | } |
54 | 54 | ||
55 | @Override | 55 | @Override |
56 | public void onReceiveClusterGrpcMsg(GrpcSession session, ClusterAPIProtos.ClusterMessage clusterMessage) { | 56 | public void onReceiveClusterGrpcMsg(GrpcSession session, ClusterAPIProtos.ClusterMessage clusterMessage) { |
57 | - log.trace("{} Service [{}] received session actor msg {}", getType(session), | ||
58 | - session.getRemoteServer(), | ||
59 | - clusterMessage); | 57 | + log.trace("Received session actor msg from [{}][{}]: {}", session.getRemoteServer(), getType(session), clusterMessage); |
60 | service.onReceivedMsg(session.getRemoteServer(), clusterMessage); | 58 | service.onReceivedMsg(session.getRemoteServer(), clusterMessage); |
61 | } | 59 | } |
62 | 60 | ||
63 | @Override | 61 | @Override |
64 | public void onError(GrpcSession session, Throwable t) { | 62 | public void onError(GrpcSession session, Throwable t) { |
65 | - log.warn("{} session got error -> {}", getType(session), session.getRemoteServer(), t); | 63 | + log.warn("[{}][{}] session got error -> {}", session.getRemoteServer(), getType(session), t); |
66 | manager.tell(new RpcSessionClosedMsg(session.isClient(), session.getRemoteServer()), self); | 64 | manager.tell(new RpcSessionClosedMsg(session.isClient(), session.getRemoteServer()), self); |
67 | session.close(); | 65 | session.close(); |
68 | } | 66 | } |
@@ -19,6 +19,7 @@ import akka.actor.ActorRef; | @@ -19,6 +19,7 @@ import akka.actor.ActorRef; | ||
19 | import akka.actor.Props; | 19 | import akka.actor.Props; |
20 | import akka.event.Logging; | 20 | import akka.event.Logging; |
21 | import akka.event.LoggingAdapter; | 21 | import akka.event.LoggingAdapter; |
22 | +import lombok.extern.slf4j.Slf4j; | ||
22 | import org.thingsboard.server.actors.ActorSystemContext; | 23 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | import org.thingsboard.server.actors.service.ContextAwareActor; | 24 | import org.thingsboard.server.actors.service.ContextAwareActor; |
24 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 25 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
@@ -26,6 +27,7 @@ import org.thingsboard.server.actors.service.DefaultActorService; | @@ -26,6 +27,7 @@ import org.thingsboard.server.actors.service.DefaultActorService; | ||
26 | import org.thingsboard.server.common.msg.TbActorMsg; | 27 | import org.thingsboard.server.common.msg.TbActorMsg; |
27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 28 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 29 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
30 | +import org.thingsboard.server.common.msg.cluster.ServerType; | ||
29 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; | 31 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
30 | import org.thingsboard.server.service.cluster.discovery.ServerInstance; | 32 | import org.thingsboard.server.service.cluster.discovery.ServerInstance; |
31 | 33 | ||
@@ -36,15 +38,13 @@ import java.util.*; | @@ -36,15 +38,13 @@ import java.util.*; | ||
36 | */ | 38 | */ |
37 | public class RpcManagerActor extends ContextAwareActor { | 39 | public class RpcManagerActor extends ContextAwareActor { |
38 | 40 | ||
39 | - private final LoggingAdapter log = Logging.getLogger(getContext().system(), this); | ||
40 | - | ||
41 | private final Map<ServerAddress, SessionActorInfo> sessionActors; | 41 | private final Map<ServerAddress, SessionActorInfo> sessionActors; |
42 | 42 | ||
43 | private final Map<ServerAddress, Queue<ClusterAPIProtos.ClusterMessage>> pendingMsgs; | 43 | private final Map<ServerAddress, Queue<ClusterAPIProtos.ClusterMessage>> pendingMsgs; |
44 | 44 | ||
45 | private final ServerAddress instance; | 45 | private final ServerAddress instance; |
46 | 46 | ||
47 | - public RpcManagerActor(ActorSystemContext systemContext) { | 47 | + private RpcManagerActor(ActorSystemContext systemContext) { |
48 | super(systemContext); | 48 | super(systemContext); |
49 | this.sessionActors = new HashMap<>(); | 49 | this.sessionActors = new HashMap<>(); |
50 | this.pendingMsgs = new HashMap<>(); | 50 | this.pendingMsgs = new HashMap<>(); |
@@ -54,7 +54,6 @@ public class RpcManagerActor extends ContextAwareActor { | @@ -54,7 +54,6 @@ public class RpcManagerActor extends ContextAwareActor { | ||
54 | .filter(otherServer -> otherServer.getServerAddress().compareTo(instance) > 0) | 54 | .filter(otherServer -> otherServer.getServerAddress().compareTo(instance) > 0) |
55 | .forEach(otherServer -> onCreateSessionRequest( | 55 | .forEach(otherServer -> onCreateSessionRequest( |
56 | new RpcSessionCreateRequestMsg(UUID.randomUUID(), otherServer.getServerAddress(), null))); | 56 | new RpcSessionCreateRequestMsg(UUID.randomUUID(), otherServer.getServerAddress(), null))); |
57 | - | ||
58 | } | 57 | } |
59 | 58 | ||
60 | @Override | 59 | @Override |
@@ -100,24 +99,23 @@ public class RpcManagerActor extends ContextAwareActor { | @@ -100,24 +99,23 @@ public class RpcManagerActor extends ContextAwareActor { | ||
100 | 99 | ||
101 | private void onMsg(ClusterAPIProtos.ClusterMessage msg) { | 100 | private void onMsg(ClusterAPIProtos.ClusterMessage msg) { |
102 | if (msg.hasServerAddress()) { | 101 | if (msg.hasServerAddress()) { |
103 | - ServerAddress address = new ServerAddress(msg.getServerAddress().getHost(), | ||
104 | - msg.getServerAddress().getPort()); | 102 | + ServerAddress address = new ServerAddress(msg.getServerAddress().getHost(), msg.getServerAddress().getPort(), ServerType.CORE); |
105 | SessionActorInfo session = sessionActors.get(address); | 103 | SessionActorInfo session = sessionActors.get(address); |
106 | if (session != null) { | 104 | if (session != null) { |
107 | - log.debug("{} Forwarding msg to session actor", address); | 105 | + log.debug("{} Forwarding msg to session actor: {}", address, msg); |
108 | session.getActor().tell(msg, ActorRef.noSender()); | 106 | session.getActor().tell(msg, ActorRef.noSender()); |
109 | } else { | 107 | } else { |
110 | - log.debug("{} Storing msg to pending queue", address); | 108 | + log.debug("{} Storing msg to pending queue: {}", address, msg); |
111 | Queue<ClusterAPIProtos.ClusterMessage> queue = pendingMsgs.get(address); | 109 | Queue<ClusterAPIProtos.ClusterMessage> queue = pendingMsgs.get(address); |
112 | if (queue == null) { | 110 | if (queue == null) { |
113 | queue = new LinkedList<>(); | 111 | queue = new LinkedList<>(); |
114 | pendingMsgs.put(new ServerAddress( | 112 | pendingMsgs.put(new ServerAddress( |
115 | - msg.getServerAddress().getHost(), msg.getServerAddress().getPort()), queue); | 113 | + msg.getServerAddress().getHost(), msg.getServerAddress().getPort(), ServerType.CORE), queue); |
116 | } | 114 | } |
117 | queue.add(msg); | 115 | queue.add(msg); |
118 | } | 116 | } |
119 | } else { | 117 | } else { |
120 | - logger.warning("Cluster msg doesn't have set Server Address [{}]", msg); | 118 | + log.warn("Cluster msg doesn't have server address [{}]", msg); |
121 | } | 119 | } |
122 | } | 120 | } |
123 | 121 | ||
@@ -162,9 +160,9 @@ public class RpcManagerActor extends ContextAwareActor { | @@ -162,9 +160,9 @@ public class RpcManagerActor extends ContextAwareActor { | ||
162 | } | 160 | } |
163 | 161 | ||
164 | private void onSessionClose(boolean reconnect, ServerAddress remoteAddress) { | 162 | private void onSessionClose(boolean reconnect, ServerAddress remoteAddress) { |
165 | - log.debug("[{}] session closed. Should reconnect: {}", remoteAddress, reconnect); | 163 | + log.info("[{}] session closed. Should reconnect: {}", remoteAddress, reconnect); |
166 | SessionActorInfo sessionRef = sessionActors.get(remoteAddress); | 164 | SessionActorInfo sessionRef = sessionActors.get(remoteAddress); |
167 | - if (context().sender() != null && context().sender().equals(sessionRef.actor)) { | 165 | + if (sessionRef != null && context().sender() != null && context().sender().equals(sessionRef.actor)) { |
168 | sessionActors.remove(remoteAddress); | 166 | sessionActors.remove(remoteAddress); |
169 | pendingMsgs.remove(remoteAddress); | 167 | pendingMsgs.remove(remoteAddress); |
170 | if (reconnect) { | 168 | if (reconnect) { |
@@ -182,18 +180,18 @@ public class RpcManagerActor extends ContextAwareActor { | @@ -182,18 +180,18 @@ public class RpcManagerActor extends ContextAwareActor { | ||
182 | 180 | ||
183 | private void register(ServerAddress remoteAddress, UUID uuid, ActorRef sender) { | 181 | private void register(ServerAddress remoteAddress, UUID uuid, ActorRef sender) { |
184 | sessionActors.put(remoteAddress, new SessionActorInfo(uuid, sender)); | 182 | sessionActors.put(remoteAddress, new SessionActorInfo(uuid, sender)); |
185 | - log.debug("[{}][{}] Registering session actor.", remoteAddress, uuid); | 183 | + log.info("[{}][{}] Registering session actor.", remoteAddress, uuid); |
186 | Queue<ClusterAPIProtos.ClusterMessage> data = pendingMsgs.remove(remoteAddress); | 184 | Queue<ClusterAPIProtos.ClusterMessage> data = pendingMsgs.remove(remoteAddress); |
187 | if (data != null) { | 185 | if (data != null) { |
188 | - log.debug("[{}][{}] Forwarding {} pending messages.", remoteAddress, uuid, data.size()); | 186 | + log.info("[{}][{}] Forwarding {} pending messages.", remoteAddress, uuid, data.size()); |
189 | data.forEach(msg -> sender.tell(new RpcSessionTellMsg(msg), ActorRef.noSender())); | 187 | data.forEach(msg -> sender.tell(new RpcSessionTellMsg(msg), ActorRef.noSender())); |
190 | } else { | 188 | } else { |
191 | - log.debug("[{}][{}] No pending messages to forward.", remoteAddress, uuid); | 189 | + log.info("[{}][{}] No pending messages to forward.", remoteAddress, uuid); |
192 | } | 190 | } |
193 | } | 191 | } |
194 | 192 | ||
195 | private ActorRef createSessionActor(RpcSessionCreateRequestMsg msg) { | 193 | private ActorRef createSessionActor(RpcSessionCreateRequestMsg msg) { |
196 | - log.debug("[{}] Creating session actor.", msg.getMsgUid()); | 194 | + log.info("[{}] Creating session actor.", msg.getMsgUid()); |
197 | ActorRef actor = context().actorOf( | 195 | ActorRef actor = context().actorOf( |
198 | Props.create(new RpcSessionActor.ActorCreator(systemContext, msg.getMsgUid())).withDispatcher(DefaultActorService.RPC_DISPATCHER_NAME)); | 196 | Props.create(new RpcSessionActor.ActorCreator(systemContext, msg.getMsgUid())).withDispatcher(DefaultActorService.RPC_DISPATCHER_NAME)); |
199 | actor.tell(msg, context().self()); | 197 | actor.tell(msg, context().self()); |
@@ -208,7 +206,7 @@ public class RpcManagerActor extends ContextAwareActor { | @@ -208,7 +206,7 @@ public class RpcManagerActor extends ContextAwareActor { | ||
208 | } | 206 | } |
209 | 207 | ||
210 | @Override | 208 | @Override |
211 | - public RpcManagerActor create() throws Exception { | 209 | + public RpcManagerActor create() { |
212 | return new RpcManagerActor(context); | 210 | return new RpcManagerActor(context); |
213 | } | 211 | } |
214 | } | 212 | } |
@@ -18,6 +18,7 @@ package org.thingsboard.server.actors.rpc; | @@ -18,6 +18,7 @@ package org.thingsboard.server.actors.rpc; | ||
18 | import akka.event.Logging; | 18 | import akka.event.Logging; |
19 | import akka.event.LoggingAdapter; | 19 | import akka.event.LoggingAdapter; |
20 | import io.grpc.Channel; | 20 | import io.grpc.Channel; |
21 | +import io.grpc.ManagedChannel; | ||
21 | import io.grpc.ManagedChannelBuilder; | 22 | import io.grpc.ManagedChannelBuilder; |
22 | import io.grpc.stub.StreamObserver; | 23 | import io.grpc.stub.StreamObserver; |
23 | import org.thingsboard.server.actors.ActorSystemContext; | 24 | import org.thingsboard.server.actors.ActorSystemContext; |
@@ -88,8 +89,8 @@ public class RpcSessionActor extends ContextAwareActor { | @@ -88,8 +89,8 @@ public class RpcSessionActor extends ContextAwareActor { | ||
88 | systemContext.getRpcService().onSessionCreated(msg.getMsgUid(), session.getInputStream()); | 89 | systemContext.getRpcService().onSessionCreated(msg.getMsgUid(), session.getInputStream()); |
89 | } else { | 90 | } else { |
90 | // Client session | 91 | // Client session |
91 | - Channel channel = ManagedChannelBuilder.forAddress(remoteServer.getHost(), remoteServer.getPort()).usePlaintext(true).build(); | ||
92 | - session = new GrpcSession(remoteServer, listener); | 92 | + ManagedChannel channel = ManagedChannelBuilder.forAddress(remoteServer.getHost(), remoteServer.getPort()).usePlaintext().build(); |
93 | + session = new GrpcSession(remoteServer, listener, channel); | ||
93 | session.initInputStream(); | 94 | session.initInputStream(); |
94 | 95 | ||
95 | ClusterRpcServiceGrpc.ClusterRpcServiceStub stub = ClusterRpcServiceGrpc.newStub(channel); | 96 | ClusterRpcServiceGrpc.ClusterRpcServiceStub stub = ClusterRpcServiceGrpc.newStub(channel); |
@@ -17,6 +17,7 @@ package org.thingsboard.server.actors.ruleChain; | @@ -17,6 +17,7 @@ package org.thingsboard.server.actors.ruleChain; | ||
17 | 17 | ||
18 | import akka.actor.ActorRef; | 18 | import akka.actor.ActorRef; |
19 | import com.datastax.driver.core.utils.UUIDs; | 19 | import com.datastax.driver.core.utils.UUIDs; |
20 | +import org.springframework.util.StringUtils; | ||
20 | import org.thingsboard.rule.engine.api.ListeningExecutor; | 21 | import org.thingsboard.rule.engine.api.ListeningExecutor; |
21 | import org.thingsboard.rule.engine.api.MailService; | 22 | import org.thingsboard.rule.engine.api.MailService; |
22 | import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; | 23 | import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; |
@@ -35,12 +36,15 @@ import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | @@ -35,12 +36,15 @@ import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | ||
35 | import org.thingsboard.server.common.data.rule.RuleNode; | 36 | import org.thingsboard.server.common.data.rule.RuleNode; |
36 | import org.thingsboard.server.common.msg.TbMsg; | 37 | import org.thingsboard.server.common.msg.TbMsg; |
37 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 38 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
39 | +import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
40 | +import org.thingsboard.server.common.msg.cluster.ServerType; | ||
38 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 41 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
39 | import org.thingsboard.server.dao.alarm.AlarmService; | 42 | import org.thingsboard.server.dao.alarm.AlarmService; |
40 | import org.thingsboard.server.dao.asset.AssetService; | 43 | import org.thingsboard.server.dao.asset.AssetService; |
41 | import org.thingsboard.server.dao.attributes.AttributesService; | 44 | import org.thingsboard.server.dao.attributes.AttributesService; |
42 | import org.thingsboard.server.dao.customer.CustomerService; | 45 | import org.thingsboard.server.dao.customer.CustomerService; |
43 | import org.thingsboard.server.dao.device.DeviceService; | 46 | import org.thingsboard.server.dao.device.DeviceService; |
47 | +import org.thingsboard.server.dao.entityview.EntityViewService; | ||
44 | import org.thingsboard.server.dao.relation.RelationService; | 48 | import org.thingsboard.server.dao.relation.RelationService; |
45 | import org.thingsboard.server.dao.rule.RuleChainService; | 49 | import org.thingsboard.server.dao.rule.RuleChainService; |
46 | import org.thingsboard.server.dao.tenant.TenantService; | 50 | import org.thingsboard.server.dao.tenant.TenantService; |
@@ -154,7 +158,7 @@ class DefaultTbContext implements TbContext { | @@ -154,7 +158,7 @@ class DefaultTbContext implements TbContext { | ||
154 | 158 | ||
155 | @Override | 159 | @Override |
156 | public ScriptEngine createJsScriptEngine(String script, String... argNames) { | 160 | public ScriptEngine createJsScriptEngine(String script, String... argNames) { |
157 | - return new RuleNodeJsScriptEngine(mainCtx.getJsSandbox(), script, argNames); | 161 | + return new RuleNodeJsScriptEngine(mainCtx.getJsSandbox(), nodeCtx.getSelf().getId(), script, argNames); |
158 | } | 162 | } |
159 | 163 | ||
160 | @Override | 164 | @Override |
@@ -213,6 +217,11 @@ class DefaultTbContext implements TbContext { | @@ -213,6 +217,11 @@ class DefaultTbContext implements TbContext { | ||
213 | } | 217 | } |
214 | 218 | ||
215 | @Override | 219 | @Override |
220 | + public EntityViewService getEntityViewService() { | ||
221 | + return mainCtx.getEntityViewService(); | ||
222 | + } | ||
223 | + | ||
224 | + @Override | ||
216 | public MailService getMailService() { | 225 | public MailService getMailService() { |
217 | if (mainCtx.isAllowSystemMailService()) { | 226 | if (mainCtx.isAllowSystemMailService()) { |
218 | return mainCtx.getMailService(); | 227 | return mainCtx.getMailService(); |
@@ -226,16 +235,22 @@ class DefaultTbContext implements TbContext { | @@ -226,16 +235,22 @@ class DefaultTbContext implements TbContext { | ||
226 | return new RuleEngineRpcService() { | 235 | return new RuleEngineRpcService() { |
227 | @Override | 236 | @Override |
228 | public void sendRpcReply(DeviceId deviceId, int requestId, String body) { | 237 | public void sendRpcReply(DeviceId deviceId, int requestId, String body) { |
229 | - mainCtx.getDeviceRpcService().sendRpcReplyToDevice(nodeCtx.getTenantId(), deviceId, requestId, body); | 238 | + mainCtx.getDeviceRpcService().sendReplyToRpcCallFromDevice(nodeCtx.getTenantId(), deviceId, requestId, body); |
230 | } | 239 | } |
231 | 240 | ||
232 | @Override | 241 | @Override |
233 | public void sendRpcRequest(RuleEngineDeviceRpcRequest src, Consumer<RuleEngineDeviceRpcResponse> consumer) { | 242 | public void sendRpcRequest(RuleEngineDeviceRpcRequest src, Consumer<RuleEngineDeviceRpcResponse> consumer) { |
234 | ToDeviceRpcRequest request = new ToDeviceRpcRequest(src.getRequestUUID(), nodeCtx.getTenantId(), src.getDeviceId(), | 243 | ToDeviceRpcRequest request = new ToDeviceRpcRequest(src.getRequestUUID(), nodeCtx.getTenantId(), src.getDeviceId(), |
235 | src.isOneway(), src.getExpirationTime(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody())); | 244 | src.isOneway(), src.getExpirationTime(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody())); |
236 | - mainCtx.getDeviceRpcService().processRpcRequestToDevice(request, response -> { | 245 | + mainCtx.getDeviceRpcService().forwardServerSideRPCRequestToDeviceActor(request, response -> { |
237 | if (src.isRestApiCall()) { | 246 | if (src.isRestApiCall()) { |
238 | - mainCtx.getDeviceRpcService().processRestAPIRpcResponseFromRuleEngine(response); | 247 | + ServerAddress requestOriginAddress; |
248 | + if (!StringUtils.isEmpty(src.getOriginHost())) { | ||
249 | + requestOriginAddress = new ServerAddress(src.getOriginHost(), src.getOriginPort(), ServerType.CORE); | ||
250 | + } else { | ||
251 | + requestOriginAddress = mainCtx.getRoutingService().getCurrentServer(); | ||
252 | + } | ||
253 | + mainCtx.getDeviceRpcService().processResponseToServerSideRPCRequestFromRuleEngine(requestOriginAddress, response); | ||
239 | } | 254 | } |
240 | consumer.accept(RuleEngineDeviceRpcResponse.builder() | 255 | consumer.accept(RuleEngineDeviceRpcResponse.builder() |
241 | .deviceId(src.getDeviceId()) | 256 | .deviceId(src.getDeviceId()) |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | +import akka.actor.ActorInitializationException; | ||
18 | import akka.actor.OneForOneStrategy; | 19 | import akka.actor.OneForOneStrategy; |
19 | import akka.actor.SupervisorStrategy; | 20 | import akka.actor.SupervisorStrategy; |
20 | import org.thingsboard.server.actors.ActorSystemContext; | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
@@ -33,7 +34,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | @@ -33,7 +34,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | ||
33 | private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId) { | 34 | private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId) { |
34 | super(systemContext, tenantId, ruleChainId); | 35 | super(systemContext, tenantId, ruleChainId); |
35 | setProcessor(new RuleChainActorMessageProcessor(tenantId, ruleChainId, systemContext, | 36 | setProcessor(new RuleChainActorMessageProcessor(tenantId, ruleChainId, systemContext, |
36 | - logger, context().parent(), context().self())); | 37 | + context().parent(), context().self())); |
37 | } | 38 | } |
38 | 39 | ||
39 | @Override | 40 | @Override |
@@ -79,7 +80,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | @@ -79,7 +80,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | ||
79 | } | 80 | } |
80 | 81 | ||
81 | @Override | 82 | @Override |
82 | - public RuleChainActor create() throws Exception { | 83 | + public RuleChainActor create() { |
83 | return new RuleChainActor(context, tenantId, ruleChainId); | 84 | return new RuleChainActor(context, tenantId, ruleChainId); |
84 | } | 85 | } |
85 | } | 86 | } |
@@ -23,9 +23,9 @@ import com.datastax.driver.core.utils.UUIDs; | @@ -23,9 +23,9 @@ import com.datastax.driver.core.utils.UUIDs; | ||
23 | 23 | ||
24 | import java.util.Optional; | 24 | import java.util.Optional; |
25 | 25 | ||
26 | +import lombok.extern.slf4j.Slf4j; | ||
26 | import org.thingsboard.server.actors.ActorSystemContext; | 27 | import org.thingsboard.server.actors.ActorSystemContext; |
27 | import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg; | 28 | import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg; |
28 | -import org.thingsboard.server.actors.device.RuleEngineQueuePutAckMsg; | ||
29 | import org.thingsboard.server.actors.service.DefaultActorService; | 29 | import org.thingsboard.server.actors.service.DefaultActorService; |
30 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | 30 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
31 | import org.thingsboard.server.common.data.EntityType; | 31 | import org.thingsboard.server.common.data.EntityType; |
@@ -56,6 +56,7 @@ import java.util.stream.Collectors; | @@ -56,6 +56,7 @@ import java.util.stream.Collectors; | ||
56 | /** | 56 | /** |
57 | * @author Andrew Shvayka | 57 | * @author Andrew Shvayka |
58 | */ | 58 | */ |
59 | +@Slf4j | ||
59 | public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleChainId> { | 60 | public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleChainId> { |
60 | 61 | ||
61 | private static final long DEFAULT_CLUSTER_PARTITION = 0L; | 62 | private static final long DEFAULT_CLUSTER_PARTITION = 0L; |
@@ -68,59 +69,58 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -68,59 +69,58 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
68 | private RuleNodeId firstId; | 69 | private RuleNodeId firstId; |
69 | private RuleNodeCtx firstNode; | 70 | private RuleNodeCtx firstNode; |
70 | private boolean started; | 71 | private boolean started; |
72 | + private String ruleChainName; | ||
71 | 73 | ||
72 | RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext | 74 | RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext |
73 | - , LoggingAdapter logger, ActorRef parent, ActorRef self) { | ||
74 | - super(systemContext, logger, tenantId, ruleChainId); | 75 | + , ActorRef parent, ActorRef self) { |
76 | + super(systemContext, tenantId, ruleChainId); | ||
75 | this.parent = parent; | 77 | this.parent = parent; |
76 | this.self = self; | 78 | this.self = self; |
77 | this.nodeActors = new HashMap<>(); | 79 | this.nodeActors = new HashMap<>(); |
78 | this.nodeRoutes = new HashMap<>(); | 80 | this.nodeRoutes = new HashMap<>(); |
79 | this.service = systemContext.getRuleChainService(); | 81 | this.service = systemContext.getRuleChainService(); |
82 | + this.ruleChainName = ruleChainId.toString(); | ||
80 | } | 83 | } |
81 | 84 | ||
82 | @Override | 85 | @Override |
83 | - public void start(ActorContext context) throws Exception { | 86 | + public String getComponentName() { |
87 | + return null; | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + public void start(ActorContext context) { | ||
84 | if (!started) { | 92 | if (!started) { |
85 | RuleChain ruleChain = service.findRuleChainById(entityId); | 93 | RuleChain ruleChain = service.findRuleChainById(entityId); |
94 | + ruleChainName = ruleChain.getName(); | ||
86 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); | 95 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); |
96 | + log.trace("[{}][{}] Starting rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); | ||
87 | // Creating and starting the actors; | 97 | // Creating and starting the actors; |
88 | for (RuleNode ruleNode : ruleNodeList) { | 98 | for (RuleNode ruleNode : ruleNodeList) { |
99 | + log.trace("[{}][{}] Creating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); | ||
89 | ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | 100 | ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); |
90 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | 101 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); |
91 | } | 102 | } |
92 | initRoutes(ruleChain, ruleNodeList); | 103 | initRoutes(ruleChain, ruleNodeList); |
93 | - reprocess(ruleNodeList); | ||
94 | started = true; | 104 | started = true; |
95 | } else { | 105 | } else { |
96 | onUpdate(context); | 106 | onUpdate(context); |
97 | } | 107 | } |
98 | } | 108 | } |
99 | 109 | ||
100 | - private void reprocess(List<RuleNode> ruleNodeList) { | ||
101 | - for (RuleNode ruleNode : ruleNodeList) { | ||
102 | - for (TbMsg tbMsg : queue.findUnprocessed(tenantId, ruleNode.getId().getId(), systemContext.getQueuePartitionId())) { | ||
103 | - pushMsgToNode(nodeActors.get(ruleNode.getId()), tbMsg, ""); | ||
104 | - } | ||
105 | - } | ||
106 | - if (firstNode != null) { | ||
107 | - for (TbMsg tbMsg : queue.findUnprocessed(tenantId, entityId.getId(), systemContext.getQueuePartitionId())) { | ||
108 | - pushMsgToNode(firstNode, tbMsg, ""); | ||
109 | - } | ||
110 | - } | ||
111 | - } | ||
112 | - | ||
113 | @Override | 110 | @Override |
114 | - public void onUpdate(ActorContext context) throws Exception { | 111 | + public void onUpdate(ActorContext context) { |
115 | RuleChain ruleChain = service.findRuleChainById(entityId); | 112 | RuleChain ruleChain = service.findRuleChainById(entityId); |
113 | + ruleChainName = ruleChain.getName(); | ||
116 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); | 114 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); |
117 | - | 115 | + log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); |
118 | for (RuleNode ruleNode : ruleNodeList) { | 116 | for (RuleNode ruleNode : ruleNodeList) { |
119 | RuleNodeCtx existing = nodeActors.get(ruleNode.getId()); | 117 | RuleNodeCtx existing = nodeActors.get(ruleNode.getId()); |
120 | if (existing == null) { | 118 | if (existing == null) { |
119 | + log.trace("[{}][{}] Creating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); | ||
121 | ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | 120 | ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); |
122 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | 121 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); |
123 | } else { | 122 | } else { |
123 | + log.trace("[{}][{}] Updating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); | ||
124 | existing.setSelf(ruleNode); | 124 | existing.setSelf(ruleNode); |
125 | existing.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, existing.getSelf().getId(), ComponentLifecycleEvent.UPDATED), self); | 125 | existing.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, existing.getSelf().getId(), ComponentLifecycleEvent.UPDATED), self); |
126 | } | 126 | } |
@@ -129,16 +129,17 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -129,16 +129,17 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
129 | Set<RuleNodeId> existingNodes = ruleNodeList.stream().map(RuleNode::getId).collect(Collectors.toSet()); | 129 | Set<RuleNodeId> existingNodes = ruleNodeList.stream().map(RuleNode::getId).collect(Collectors.toSet()); |
130 | List<RuleNodeId> removedRules = nodeActors.keySet().stream().filter(node -> !existingNodes.contains(node)).collect(Collectors.toList()); | 130 | List<RuleNodeId> removedRules = nodeActors.keySet().stream().filter(node -> !existingNodes.contains(node)).collect(Collectors.toList()); |
131 | removedRules.forEach(ruleNodeId -> { | 131 | removedRules.forEach(ruleNodeId -> { |
132 | + log.trace("[{}][{}] Removing rule node [{}]", tenantId, entityId, ruleNodeId); | ||
132 | RuleNodeCtx removed = nodeActors.remove(ruleNodeId); | 133 | RuleNodeCtx removed = nodeActors.remove(ruleNodeId); |
133 | removed.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, removed.getSelf().getId(), ComponentLifecycleEvent.DELETED), self); | 134 | removed.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, removed.getSelf().getId(), ComponentLifecycleEvent.DELETED), self); |
134 | }); | 135 | }); |
135 | 136 | ||
136 | initRoutes(ruleChain, ruleNodeList); | 137 | initRoutes(ruleChain, ruleNodeList); |
137 | - reprocess(ruleNodeList); | ||
138 | } | 138 | } |
139 | 139 | ||
140 | @Override | 140 | @Override |
141 | - public void stop(ActorContext context) throws Exception { | 141 | + public void stop(ActorContext context) { |
142 | + log.trace("[{}][{}] Stopping rule chain with {} nodes", tenantId, entityId, nodeActors.size()); | ||
142 | nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); | 143 | nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); |
143 | nodeActors.clear(); | 144 | nodeActors.clear(); |
144 | nodeRoutes.clear(); | 145 | nodeRoutes.clear(); |
@@ -147,7 +148,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -147,7 +148,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
147 | } | 148 | } |
148 | 149 | ||
149 | @Override | 150 | @Override |
150 | - public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | 151 | + public void onClusterEventMsg(ClusterEventMsg msg) { |
151 | 152 | ||
152 | } | 153 | } |
153 | 154 | ||
@@ -164,10 +165,12 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -164,10 +165,12 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
164 | // Populating the routes map; | 165 | // Populating the routes map; |
165 | for (RuleNode ruleNode : ruleNodeList) { | 166 | for (RuleNode ruleNode : ruleNodeList) { |
166 | List<EntityRelation> relations = service.getRuleNodeRelations(ruleNode.getId()); | 167 | List<EntityRelation> relations = service.getRuleNodeRelations(ruleNode.getId()); |
168 | + log.trace("[{}][{}][{}] Processing rule node relations [{}]", tenantId, entityId, ruleNode.getId(), relations.size()); | ||
167 | if (relations.size() == 0) { | 169 | if (relations.size() == 0) { |
168 | nodeRoutes.put(ruleNode.getId(), Collections.emptyList()); | 170 | nodeRoutes.put(ruleNode.getId(), Collections.emptyList()); |
169 | } else { | 171 | } else { |
170 | for (EntityRelation relation : relations) { | 172 | for (EntityRelation relation : relations) { |
173 | + log.trace("[{}][{}][{}] Processing rule node relation [{}]", tenantId, entityId, ruleNode.getId(), relation.getTo()); | ||
171 | if (relation.getTo().getEntityType() == EntityType.RULE_NODE) { | 174 | if (relation.getTo().getEntityType() == EntityType.RULE_NODE) { |
172 | RuleNodeCtx ruleNodeCtx = nodeActors.get(new RuleNodeId(relation.getTo().getId())); | 175 | RuleNodeCtx ruleNodeCtx = nodeActors.get(new RuleNodeId(relation.getTo().getId())); |
173 | if (ruleNodeCtx == null) { | 176 | if (ruleNodeCtx == null) { |
@@ -181,24 +184,23 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -181,24 +184,23 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
181 | } | 184 | } |
182 | 185 | ||
183 | firstId = ruleChain.getFirstRuleNodeId(); | 186 | firstId = ruleChain.getFirstRuleNodeId(); |
184 | - firstNode = nodeActors.get(ruleChain.getFirstRuleNodeId()); | 187 | + firstNode = nodeActors.get(firstId); |
185 | state = ComponentLifecycleState.ACTIVE; | 188 | state = ComponentLifecycleState.ACTIVE; |
186 | } | 189 | } |
187 | 190 | ||
188 | void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg envelope) { | 191 | void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg envelope) { |
192 | + log.trace("[{}][{}] Processing message [{}]: {}", entityId, firstId, envelope.getTbMsg().getId(), envelope.getTbMsg()); | ||
189 | checkActive(); | 193 | checkActive(); |
190 | if (firstNode != null) { | 194 | if (firstNode != null) { |
191 | - putToQueue(enrichWithRuleChainId(envelope.getTbMsg()), msg -> pushMsgToNode(firstNode, msg, "")); | 195 | + log.trace("[{}][{}] Pushing message to first rule node", entityId, firstId); |
196 | + pushMsgToNode(firstNode, enrichWithRuleChainId(envelope.getTbMsg()), ""); | ||
192 | } | 197 | } |
193 | } | 198 | } |
194 | 199 | ||
195 | void onDeviceActorToRuleEngineMsg(DeviceActorToRuleEngineMsg envelope) { | 200 | void onDeviceActorToRuleEngineMsg(DeviceActorToRuleEngineMsg envelope) { |
196 | checkActive(); | 201 | checkActive(); |
197 | if (firstNode != null) { | 202 | if (firstNode != null) { |
198 | - putToQueue(enrichWithRuleChainId(envelope.getTbMsg()), msg -> { | ||
199 | - pushMsgToNode(firstNode, msg, ""); | ||
200 | - envelope.getCallbackRef().tell(new RuleEngineQueuePutAckMsg(msg.getId()), self); | ||
201 | - }); | 203 | + pushMsgToNode(firstNode, enrichWithRuleChainId(envelope.getTbMsg()), ""); |
202 | } | 204 | } |
203 | } | 205 | } |
204 | 206 | ||
@@ -206,15 +208,16 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -206,15 +208,16 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
206 | checkActive(); | 208 | checkActive(); |
207 | if (envelope.isEnqueue()) { | 209 | if (envelope.isEnqueue()) { |
208 | if (firstNode != null) { | 210 | if (firstNode != null) { |
209 | - putToQueue(enrichWithRuleChainId(envelope.getMsg()), msg -> pushMsgToNode(firstNode, msg, envelope.getFromRelationType())); | 211 | + pushMsgToNode(firstNode, enrichWithRuleChainId(envelope.getMsg()), envelope.getFromRelationType()); |
210 | } | 212 | } |
211 | } else { | 213 | } else { |
212 | if (firstNode != null) { | 214 | if (firstNode != null) { |
213 | pushMsgToNode(firstNode, envelope.getMsg(), envelope.getFromRelationType()); | 215 | pushMsgToNode(firstNode, envelope.getMsg(), envelope.getFromRelationType()); |
214 | } else { | 216 | } else { |
215 | - TbMsg msg = envelope.getMsg(); | ||
216 | - EntityId ackId = msg.getRuleNodeId() != null ? msg.getRuleNodeId() : msg.getRuleChainId(); | ||
217 | - queue.ack(tenantId, envelope.getMsg(), ackId.getId(), msg.getClusterPartition()); | 217 | +// TODO: Ack this message in Kafka |
218 | +// TbMsg msg = envelope.getMsg(); | ||
219 | +// EntityId ackId = msg.getRuleNodeId() != null ? msg.getRuleNodeId() : msg.getRuleChainId(); | ||
220 | +// queue.ack(tenantId, envelope.getMsg(), ackId.getId(), msg.getClusterPartition()); | ||
218 | } | 221 | } |
219 | } | 222 | } |
220 | } | 223 | } |
@@ -234,7 +237,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -234,7 +237,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
234 | 237 | ||
235 | private void onRemoteTellNext(ServerAddress serverAddress, RuleNodeToRuleChainTellNextMsg envelope) { | 238 | private void onRemoteTellNext(ServerAddress serverAddress, RuleNodeToRuleChainTellNextMsg envelope) { |
236 | TbMsg msg = envelope.getMsg(); | 239 | TbMsg msg = envelope.getMsg(); |
237 | - logger.debug("Forwarding [{}] msg to remote server [{}] due to changed originator id: [{}]", msg.getId(), serverAddress, msg.getOriginator()); | 240 | + log.debug("Forwarding [{}] msg to remote server [{}] due to changed originator id: [{}]", msg.getId(), serverAddress, msg.getOriginator()); |
238 | envelope = new RemoteToRuleChainTellNextMsg(envelope, tenantId, entityId); | 241 | envelope = new RemoteToRuleChainTellNextMsg(envelope, tenantId, entityId); |
239 | systemContext.getRpcService().tell(systemContext.getEncodingService().convertToProtoDataMessage(serverAddress, envelope)); | 242 | systemContext.getRpcService().tell(systemContext.getEncodingService().convertToProtoDataMessage(serverAddress, envelope)); |
240 | } | 243 | } |
@@ -248,16 +251,20 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -248,16 +251,20 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
248 | int relationsCount = relations.size(); | 251 | int relationsCount = relations.size(); |
249 | EntityId ackId = msg.getRuleNodeId() != null ? msg.getRuleNodeId() : msg.getRuleChainId(); | 252 | EntityId ackId = msg.getRuleNodeId() != null ? msg.getRuleNodeId() : msg.getRuleChainId(); |
250 | if (relationsCount == 0) { | 253 | if (relationsCount == 0) { |
254 | + log.trace("[{}][{}][{}] No outbound relations to process", tenantId, entityId, msg.getId()); | ||
251 | if (ackId != null) { | 255 | if (ackId != null) { |
252 | - queue.ack(tenantId, msg, ackId.getId(), msg.getClusterPartition()); | 256 | +// TODO: Ack this message in Kafka |
257 | +// queue.ack(tenantId, msg, ackId.getId(), msg.getClusterPartition()); | ||
253 | } | 258 | } |
254 | } else if (relationsCount == 1) { | 259 | } else if (relationsCount == 1) { |
255 | for (RuleNodeRelation relation : relations) { | 260 | for (RuleNodeRelation relation : relations) { |
261 | + log.trace("[{}][{}][{}] Pushing message to single target: [{}]", tenantId, entityId, msg.getId(), relation.getOut()); | ||
256 | pushToTarget(msg, relation.getOut(), relation.getType()); | 262 | pushToTarget(msg, relation.getOut(), relation.getType()); |
257 | } | 263 | } |
258 | } else { | 264 | } else { |
259 | for (RuleNodeRelation relation : relations) { | 265 | for (RuleNodeRelation relation : relations) { |
260 | EntityId target = relation.getOut(); | 266 | EntityId target = relation.getOut(); |
267 | + log.trace("[{}][{}][{}] Pushing message to multiple targets: [{}]", tenantId, entityId, msg.getId(), relation.getOut()); | ||
261 | switch (target.getEntityType()) { | 268 | switch (target.getEntityType()) { |
262 | case RULE_NODE: | 269 | case RULE_NODE: |
263 | enqueueAndForwardMsgCopyToNode(msg, target, relation.getType()); | 270 | enqueueAndForwardMsgCopyToNode(msg, target, relation.getType()); |
@@ -269,7 +276,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -269,7 +276,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
269 | } | 276 | } |
270 | //TODO: Ideally this should happen in async way when all targets confirm that the copied messages are successfully written to corresponding target queues. | 277 | //TODO: Ideally this should happen in async way when all targets confirm that the copied messages are successfully written to corresponding target queues. |
271 | if (ackId != null) { | 278 | if (ackId != null) { |
272 | - queue.ack(tenantId, msg, ackId.getId(), msg.getClusterPartition()); | 279 | +// TODO: Ack this message in Kafka |
280 | +// queue.ack(tenantId, msg, ackId.getId(), msg.getClusterPartition()); | ||
273 | } | 281 | } |
274 | } | 282 | } |
275 | } | 283 | } |
@@ -296,7 +304,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -296,7 +304,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
296 | RuleNodeId targetId = new RuleNodeId(target.getId()); | 304 | RuleNodeId targetId = new RuleNodeId(target.getId()); |
297 | RuleNodeCtx targetNodeCtx = nodeActors.get(targetId); | 305 | RuleNodeCtx targetNodeCtx = nodeActors.get(targetId); |
298 | TbMsg copy = msg.copy(UUIDs.timeBased(), entityId, targetId, DEFAULT_CLUSTER_PARTITION); | 306 | TbMsg copy = msg.copy(UUIDs.timeBased(), entityId, targetId, DEFAULT_CLUSTER_PARTITION); |
299 | - putToQueue(copy, queuedMsg -> pushMsgToNode(targetNodeCtx, queuedMsg, fromRelationType)); | 307 | + pushMsgToNode(targetNodeCtx, copy, fromRelationType); |
300 | } | 308 | } |
301 | 309 | ||
302 | private void pushToTarget(TbMsg msg, EntityId target, String fromRelationType) { | 310 | private void pushToTarget(TbMsg msg, EntityId target, String fromRelationType) { |
@@ -32,7 +32,7 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | @@ -32,7 +32,7 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | ||
32 | super(systemContext, tenantId, ruleNodeId); | 32 | super(systemContext, tenantId, ruleNodeId); |
33 | this.ruleChainId = ruleChainId; | 33 | this.ruleChainId = ruleChainId; |
34 | setProcessor(new RuleNodeActorMessageProcessor(tenantId, ruleChainId, ruleNodeId, systemContext, | 34 | setProcessor(new RuleNodeActorMessageProcessor(tenantId, ruleChainId, ruleNodeId, systemContext, |
35 | - logger, context().parent(), context().self())); | 35 | + context().parent(), context().self())); |
36 | } | 36 | } |
37 | 37 | ||
38 | @Override | 38 | @Override |
@@ -60,7 +60,9 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | @@ -60,7 +60,9 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | ||
60 | } | 60 | } |
61 | 61 | ||
62 | private void onRuleNodeToSelfMsg(RuleNodeToSelfMsg msg) { | 62 | private void onRuleNodeToSelfMsg(RuleNodeToSelfMsg msg) { |
63 | - logger.debug("[{}] Going to process rule msg: {}", id, msg.getMsg()); | 63 | + if (log.isDebugEnabled()) { |
64 | + log.debug("[{}][{}][{}] Going to process rule msg: {}", ruleChainId, id, processor.getComponentName(), msg.getMsg()); | ||
65 | + } | ||
64 | try { | 66 | try { |
65 | processor.onRuleToSelfMsg(msg); | 67 | processor.onRuleToSelfMsg(msg); |
66 | increaseMessagesProcessedCount(); | 68 | increaseMessagesProcessedCount(); |
@@ -70,7 +72,9 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | @@ -70,7 +72,9 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | ||
70 | } | 72 | } |
71 | 73 | ||
72 | private void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) { | 74 | private void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) { |
73 | - logger.debug("[{}] Going to process rule msg: {}", id, msg.getMsg()); | 75 | + if (log.isDebugEnabled()) { |
76 | + log.debug("[{}][{}][{}] Going to process rule msg: {}", ruleChainId, id, processor.getComponentName(), msg.getMsg()); | ||
77 | + } | ||
74 | try { | 78 | try { |
75 | processor.onRuleChainToRuleNodeMsg(msg); | 79 | processor.onRuleChainToRuleNodeMsg(msg); |
76 | increaseMessagesProcessedCount(); | 80 | increaseMessagesProcessedCount(); |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
@@ -44,8 +44,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -44,8 +44,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
44 | private TbContext defaultCtx; | 44 | private TbContext defaultCtx; |
45 | 45 | ||
46 | RuleNodeActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId, ActorSystemContext systemContext | 46 | RuleNodeActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId, ActorSystemContext systemContext |
47 | - , LoggingAdapter logger, ActorRef parent, ActorRef self) { | ||
48 | - super(systemContext, logger, tenantId, ruleNodeId); | 47 | + , ActorRef parent, ActorRef self) { |
48 | + super(systemContext, tenantId, ruleNodeId); | ||
49 | this.parent = parent; | 49 | this.parent = parent; |
50 | this.self = self; | 50 | this.self = self; |
51 | this.service = systemContext.getRuleChainService(); | 51 | this.service = systemContext.getRuleChainService(); |
@@ -75,7 +75,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -75,7 +75,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
75 | } | 75 | } |
76 | 76 | ||
77 | @Override | 77 | @Override |
78 | - public void stop(ActorContext context) throws Exception { | 78 | + public void stop(ActorContext context) { |
79 | if (tbNode != null) { | 79 | if (tbNode != null) { |
80 | tbNode.destroy(); | 80 | tbNode.destroy(); |
81 | } | 81 | } |
@@ -83,7 +83,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -83,7 +83,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
83 | } | 83 | } |
84 | 84 | ||
85 | @Override | 85 | @Override |
86 | - public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | 86 | + public void onClusterEventMsg(ClusterEventMsg msg) { |
87 | 87 | ||
88 | } | 88 | } |
89 | 89 | ||
@@ -111,6 +111,11 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -111,6 +111,11 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | + @Override | ||
115 | + public String getComponentName() { | ||
116 | + return ruleNode.getName(); | ||
117 | + } | ||
118 | + | ||
114 | private TbNode initComponent(RuleNode ruleNode) throws Exception { | 119 | private TbNode initComponent(RuleNode ruleNode) throws Exception { |
115 | Class<?> componentClazz = Class.forName(ruleNode.getType()); | 120 | Class<?> componentClazz = Class.forName(ruleNode.getType()); |
116 | TbNode tbNode = (TbNode) (componentClazz.newInstance()); | 121 | TbNode tbNode = (TbNode) (componentClazz.newInstance()); |
@@ -35,5 +35,4 @@ public interface ActorService extends SessionMsgProcessor, RpcMsgListener, Disco | @@ -35,5 +35,4 @@ public interface ActorService extends SessionMsgProcessor, RpcMsgListener, Disco | ||
35 | 35 | ||
36 | void onDeviceNameOrTypeUpdate(TenantId tenantId, DeviceId deviceId, String deviceName, String deviceType); | 36 | void onDeviceNameOrTypeUpdate(TenantId tenantId, DeviceId deviceId, String deviceName, String deviceType); |
37 | 37 | ||
38 | - void onMsg(ServiceToRuleEngineMsg serviceToRuleEngineMsg); | ||
39 | } | 38 | } |
@@ -18,6 +18,7 @@ package org.thingsboard.server.actors.service; | @@ -18,6 +18,7 @@ package org.thingsboard.server.actors.service; | ||
18 | import akka.actor.ActorRef; | 18 | import akka.actor.ActorRef; |
19 | import akka.event.Logging; | 19 | import akka.event.Logging; |
20 | import akka.event.LoggingAdapter; | 20 | import akka.event.LoggingAdapter; |
21 | +import lombok.extern.slf4j.Slf4j; | ||
21 | import org.thingsboard.server.actors.ActorSystemContext; | 22 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | 23 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
23 | import org.thingsboard.server.actors.stats.StatsPersistMsg; | 24 | import org.thingsboard.server.actors.stats.StatsPersistMsg; |
@@ -32,8 +33,6 @@ import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | @@ -32,8 +33,6 @@ import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | ||
32 | */ | 33 | */ |
33 | public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgProcessor<T>> extends ContextAwareActor { | 34 | public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgProcessor<T>> extends ContextAwareActor { |
34 | 35 | ||
35 | - protected final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | ||
36 | - | ||
37 | private long lastPersistedErrorTs = 0L; | 36 | private long lastPersistedErrorTs = 0L; |
38 | protected final TenantId tenantId; | 37 | protected final TenantId tenantId; |
39 | protected final T id; | 38 | protected final T id; |
@@ -54,13 +53,14 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -54,13 +53,14 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
54 | @Override | 53 | @Override |
55 | public void preStart() { | 54 | public void preStart() { |
56 | try { | 55 | try { |
56 | + log.debug("[{}][{}][{}] Starting processor.", tenantId, id, id.getEntityType()); | ||
57 | processor.start(context()); | 57 | processor.start(context()); |
58 | logLifecycleEvent(ComponentLifecycleEvent.STARTED); | 58 | logLifecycleEvent(ComponentLifecycleEvent.STARTED); |
59 | if (systemContext.isStatisticsEnabled()) { | 59 | if (systemContext.isStatisticsEnabled()) { |
60 | scheduleStatsPersistTick(); | 60 | scheduleStatsPersistTick(); |
61 | } | 61 | } |
62 | } catch (Exception e) { | 62 | } catch (Exception e) { |
63 | - logger.warning("[{}][{}] Failed to start {} processor: {}", tenantId, id, id.getEntityType(), e); | 63 | + log.warn("[{}][{}] Failed to start {} processor: {}", tenantId, id, id.getEntityType(), e); |
64 | logAndPersist("OnStart", e, true); | 64 | logAndPersist("OnStart", e, true); |
65 | logLifecycleEvent(ComponentLifecycleEvent.STARTED, e); | 65 | logLifecycleEvent(ComponentLifecycleEvent.STARTED, e); |
66 | } | 66 | } |
@@ -70,7 +70,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -70,7 +70,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
70 | try { | 70 | try { |
71 | processor.scheduleStatsPersistTick(context(), systemContext.getStatisticsPersistFrequency()); | 71 | processor.scheduleStatsPersistTick(context(), systemContext.getStatisticsPersistFrequency()); |
72 | } catch (Exception e) { | 72 | } catch (Exception e) { |
73 | - logger.error("[{}][{}] Failed to schedule statistics store message. No statistics is going to be stored: {}", tenantId, id, e.getMessage()); | 73 | + log.error("[{}][{}] Failed to schedule statistics store message. No statistics is going to be stored: {}", tenantId, id, e.getMessage()); |
74 | logAndPersist("onScheduleStatsPersistMsg", e); | 74 | logAndPersist("onScheduleStatsPersistMsg", e); |
75 | } | 75 | } |
76 | } | 76 | } |
@@ -78,16 +78,18 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -78,16 +78,18 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
78 | @Override | 78 | @Override |
79 | public void postStop() { | 79 | public void postStop() { |
80 | try { | 80 | try { |
81 | + log.debug("[{}][{}] Stopping processor.", tenantId, id, id.getEntityType()); | ||
81 | processor.stop(context()); | 82 | processor.stop(context()); |
82 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED); | 83 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED); |
83 | } catch (Exception e) { | 84 | } catch (Exception e) { |
84 | - logger.warning("[{}][{}] Failed to stop {} processor: {}", tenantId, id, id.getEntityType(), e.getMessage()); | 85 | + log.warn("[{}][{}] Failed to stop {} processor: {}", tenantId, id, id.getEntityType(), e.getMessage()); |
85 | logAndPersist("OnStop", e, true); | 86 | logAndPersist("OnStop", e, true); |
86 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED, e); | 87 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED, e); |
87 | } | 88 | } |
88 | } | 89 | } |
89 | 90 | ||
90 | protected void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 91 | protected void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
92 | + log.debug("[{}][{}][{}] onComponentLifecycleMsg: [{}]", tenantId, id, id.getEntityType(), msg.getEvent()); | ||
91 | try { | 93 | try { |
92 | switch (msg.getEvent()) { | 94 | switch (msg.getEvent()) { |
93 | case CREATED: | 95 | case CREATED: |
@@ -148,9 +150,9 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -148,9 +150,9 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
148 | private void logAndPersist(String method, Exception e, boolean critical) { | 150 | private void logAndPersist(String method, Exception e, boolean critical) { |
149 | errorsOccurred++; | 151 | errorsOccurred++; |
150 | if (critical) { | 152 | if (critical) { |
151 | - logger.warning("[{}][{}] Failed to process {} msg: {}", id, tenantId, method, e); | 153 | + log.warn("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, processor.getComponentName(), method, e); |
152 | } else { | 154 | } else { |
153 | - logger.debug("[{}][{}] Failed to process {} msg: {}", id, tenantId, method, e); | 155 | + log.debug("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, processor.getComponentName(), method, e); |
154 | } | 156 | } |
155 | long ts = System.currentTimeMillis(); | 157 | long ts = System.currentTimeMillis(); |
156 | if (ts - lastPersistedErrorTs > getErrorPersistFrequency()) { | 158 | if (ts - lastPersistedErrorTs > getErrorPersistFrequency()) { |
@@ -15,14 +15,17 @@ | @@ -15,14 +15,17 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | +import akka.actor.Terminated; | ||
18 | import akka.actor.UntypedActor; | 19 | import akka.actor.UntypedActor; |
19 | -import akka.event.Logging; | ||
20 | -import akka.event.LoggingAdapter; | 20 | +import org.slf4j.Logger; |
21 | +import org.slf4j.LoggerFactory; | ||
21 | import org.thingsboard.server.actors.ActorSystemContext; | 22 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | import org.thingsboard.server.common.msg.TbActorMsg; | 23 | import org.thingsboard.server.common.msg.TbActorMsg; |
23 | 24 | ||
25 | + | ||
24 | public abstract class ContextAwareActor extends UntypedActor { | 26 | public abstract class ContextAwareActor extends UntypedActor { |
25 | - protected final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | 27 | + |
28 | + protected final Logger log = LoggerFactory.getLogger(getClass()); | ||
26 | 29 | ||
27 | public static final int ENTITY_PACK_LIMIT = 1024; | 30 | public static final int ENTITY_PACK_LIMIT = 1024; |
28 | 31 | ||
@@ -35,21 +38,26 @@ public abstract class ContextAwareActor extends UntypedActor { | @@ -35,21 +38,26 @@ public abstract class ContextAwareActor extends UntypedActor { | ||
35 | 38 | ||
36 | @Override | 39 | @Override |
37 | public void onReceive(Object msg) throws Exception { | 40 | public void onReceive(Object msg) throws Exception { |
38 | - if (logger.isDebugEnabled()) { | ||
39 | - logger.debug("Processing msg: {}", msg); | 41 | + if (log.isDebugEnabled()) { |
42 | + log.debug("Processing msg: {}", msg); | ||
40 | } | 43 | } |
41 | if (msg instanceof TbActorMsg) { | 44 | if (msg instanceof TbActorMsg) { |
42 | try { | 45 | try { |
43 | if (!process((TbActorMsg) msg)) { | 46 | if (!process((TbActorMsg) msg)) { |
44 | - logger.warning("Unknown message: {}!", msg); | 47 | + log.warn("Unknown message: {}!", msg); |
45 | } | 48 | } |
46 | } catch (Exception e) { | 49 | } catch (Exception e) { |
47 | throw e; | 50 | throw e; |
48 | } | 51 | } |
52 | + } else if (msg instanceof Terminated) { | ||
53 | + processTermination((Terminated) msg); | ||
49 | } else { | 54 | } else { |
50 | - logger.warning("Unknown message: {}!", msg); | 55 | + log.warn("Unknown message: {}!", msg); |
51 | } | 56 | } |
52 | } | 57 | } |
53 | 58 | ||
59 | + protected void processTermination(Terminated msg) { | ||
60 | + } | ||
61 | + | ||
54 | protected abstract boolean process(TbActorMsg msg); | 62 | protected abstract boolean process(TbActorMsg msg); |
55 | } | 63 | } |
@@ -30,7 +30,6 @@ import org.thingsboard.server.actors.app.AppActor; | @@ -30,7 +30,6 @@ import org.thingsboard.server.actors.app.AppActor; | ||
30 | import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; | 30 | import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; |
31 | import org.thingsboard.server.actors.rpc.RpcManagerActor; | 31 | import org.thingsboard.server.actors.rpc.RpcManagerActor; |
32 | import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; | 32 | import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; |
33 | -import org.thingsboard.server.actors.session.SessionManagerActor; | ||
34 | import org.thingsboard.server.actors.stats.StatsActor; | 33 | import org.thingsboard.server.actors.stats.StatsActor; |
35 | import org.thingsboard.server.common.data.Device; | 34 | import org.thingsboard.server.common.data.Device; |
36 | import org.thingsboard.server.common.data.id.DeviceId; | 35 | import org.thingsboard.server.common.data.id.DeviceId; |
@@ -38,13 +37,11 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -38,13 +37,11 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
38 | import org.thingsboard.server.common.data.id.TenantId; | 37 | import org.thingsboard.server.common.data.id.TenantId; |
39 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 38 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
40 | import org.thingsboard.server.common.msg.TbActorMsg; | 39 | import org.thingsboard.server.common.msg.TbActorMsg; |
41 | -import org.thingsboard.server.common.msg.aware.SessionAwareMsg; | ||
42 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 40 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
43 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | 41 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; |
44 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 42 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
45 | import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; | 43 | import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; |
46 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 44 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
47 | -import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
48 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; | 45 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
49 | import org.thingsboard.server.service.cluster.discovery.DiscoveryService; | 46 | import org.thingsboard.server.service.cluster.discovery.DiscoveryService; |
50 | import org.thingsboard.server.service.cluster.discovery.ServerInstance; | 47 | import org.thingsboard.server.service.cluster.discovery.ServerInstance; |
@@ -68,10 +65,7 @@ public class DefaultActorService implements ActorService { | @@ -68,10 +65,7 @@ public class DefaultActorService implements ActorService { | ||
68 | public static final String APP_DISPATCHER_NAME = "app-dispatcher"; | 65 | public static final String APP_DISPATCHER_NAME = "app-dispatcher"; |
69 | public static final String CORE_DISPATCHER_NAME = "core-dispatcher"; | 66 | public static final String CORE_DISPATCHER_NAME = "core-dispatcher"; |
70 | public static final String SYSTEM_RULE_DISPATCHER_NAME = "system-rule-dispatcher"; | 67 | public static final String SYSTEM_RULE_DISPATCHER_NAME = "system-rule-dispatcher"; |
71 | - public static final String SYSTEM_PLUGIN_DISPATCHER_NAME = "system-plugin-dispatcher"; | ||
72 | public static final String TENANT_RULE_DISPATCHER_NAME = "rule-dispatcher"; | 68 | public static final String TENANT_RULE_DISPATCHER_NAME = "rule-dispatcher"; |
73 | - public static final String TENANT_PLUGIN_DISPATCHER_NAME = "plugin-dispatcher"; | ||
74 | - public static final String SESSION_DISPATCHER_NAME = "session-dispatcher"; | ||
75 | public static final String RPC_DISPATCHER_NAME = "rpc-dispatcher"; | 69 | public static final String RPC_DISPATCHER_NAME = "rpc-dispatcher"; |
76 | 70 | ||
77 | @Autowired | 71 | @Autowired |
@@ -90,8 +84,6 @@ public class DefaultActorService implements ActorService { | @@ -90,8 +84,6 @@ public class DefaultActorService implements ActorService { | ||
90 | 84 | ||
91 | private ActorRef appActor; | 85 | private ActorRef appActor; |
92 | 86 | ||
93 | - private ActorRef sessionManagerActor; | ||
94 | - | ||
95 | private ActorRef rpcManagerActor; | 87 | private ActorRef rpcManagerActor; |
96 | 88 | ||
97 | @PostConstruct | 89 | @PostConstruct |
@@ -104,10 +96,6 @@ public class DefaultActorService implements ActorService { | @@ -104,10 +96,6 @@ public class DefaultActorService implements ActorService { | ||
104 | appActor = system.actorOf(Props.create(new AppActor.ActorCreator(actorContext)).withDispatcher(APP_DISPATCHER_NAME), "appActor"); | 96 | appActor = system.actorOf(Props.create(new AppActor.ActorCreator(actorContext)).withDispatcher(APP_DISPATCHER_NAME), "appActor"); |
105 | actorContext.setAppActor(appActor); | 97 | actorContext.setAppActor(appActor); |
106 | 98 | ||
107 | - sessionManagerActor = system.actorOf(Props.create(new SessionManagerActor.ActorCreator(actorContext)).withDispatcher(CORE_DISPATCHER_NAME), | ||
108 | - "sessionManagerActor"); | ||
109 | - actorContext.setSessionManagerActor(sessionManagerActor); | ||
110 | - | ||
111 | rpcManagerActor = system.actorOf(Props.create(new RpcManagerActor.ActorCreator(actorContext)).withDispatcher(CORE_DISPATCHER_NAME), | 99 | rpcManagerActor = system.actorOf(Props.create(new RpcManagerActor.ActorCreator(actorContext)).withDispatcher(CORE_DISPATCHER_NAME), |
112 | "rpcManagerActor"); | 100 | "rpcManagerActor"); |
113 | 101 | ||
@@ -115,8 +103,6 @@ public class DefaultActorService implements ActorService { | @@ -115,8 +103,6 @@ public class DefaultActorService implements ActorService { | ||
115 | actorContext.setStatsActor(statsActor); | 103 | actorContext.setStatsActor(statsActor); |
116 | 104 | ||
117 | rpcService.init(this); | 105 | rpcService.init(this); |
118 | - | ||
119 | - discoveryService.addListener(this); | ||
120 | log.info("Actor system initialized."); | 106 | log.info("Actor system initialized."); |
121 | } | 107 | } |
122 | 108 | ||
@@ -137,12 +123,6 @@ public class DefaultActorService implements ActorService { | @@ -137,12 +123,6 @@ public class DefaultActorService implements ActorService { | ||
137 | } | 123 | } |
138 | 124 | ||
139 | @Override | 125 | @Override |
140 | - public void process(SessionAwareMsg msg) { | ||
141 | - log.debug("Processing session aware msg: {}", msg); | ||
142 | - sessionManagerActor.tell(msg, ActorRef.noSender()); | ||
143 | - } | ||
144 | - | ||
145 | - @Override | ||
146 | public void onServerAdded(ServerInstance server) { | 126 | public void onServerAdded(ServerInstance server) { |
147 | log.trace("Processing onServerAdded msg: {}", server); | 127 | log.trace("Processing onServerAdded msg: {}", server); |
148 | broadcast(new ClusterEventMsg(server.getServerAddress(), true)); | 128 | broadcast(new ClusterEventMsg(server.getServerAddress(), true)); |
@@ -178,11 +158,6 @@ public class DefaultActorService implements ActorService { | @@ -178,11 +158,6 @@ public class DefaultActorService implements ActorService { | ||
178 | appActor.tell(new SendToClusterMsg(deviceId, msg), ActorRef.noSender()); | 158 | appActor.tell(new SendToClusterMsg(deviceId, msg), ActorRef.noSender()); |
179 | } | 159 | } |
180 | 160 | ||
181 | - @Override | ||
182 | - public void onMsg(ServiceToRuleEngineMsg msg) { | ||
183 | - appActor.tell(msg, ActorRef.noSender()); | ||
184 | - } | ||
185 | - | ||
186 | public void broadcast(ToAllNodesMsg msg) { | 161 | public void broadcast(ToAllNodesMsg msg) { |
187 | actorContext.getEncodingService().encode(msg); | 162 | actorContext.getEncodingService().encode(msg); |
188 | rpcService.broadcast(new RpcBroadcastMsg(ClusterAPIProtos.ClusterMessage | 163 | rpcService.broadcast(new RpcBroadcastMsg(ClusterAPIProtos.ClusterMessage |
@@ -196,16 +171,15 @@ public class DefaultActorService implements ActorService { | @@ -196,16 +171,15 @@ public class DefaultActorService implements ActorService { | ||
196 | 171 | ||
197 | private void broadcast(ClusterEventMsg msg) { | 172 | private void broadcast(ClusterEventMsg msg) { |
198 | this.appActor.tell(msg, ActorRef.noSender()); | 173 | this.appActor.tell(msg, ActorRef.noSender()); |
199 | - this.sessionManagerActor.tell(msg, ActorRef.noSender()); | ||
200 | this.rpcManagerActor.tell(msg, ActorRef.noSender()); | 174 | this.rpcManagerActor.tell(msg, ActorRef.noSender()); |
201 | } | 175 | } |
202 | 176 | ||
203 | @Override | 177 | @Override |
204 | public void onReceivedMsg(ServerAddress source, ClusterAPIProtos.ClusterMessage msg) { | 178 | public void onReceivedMsg(ServerAddress source, ClusterAPIProtos.ClusterMessage msg) { |
205 | - ServerAddress serverAddress = new ServerAddress(source.getHost(), source.getPort()); | ||
206 | - log.info("Received msg [{}] from [{}]", msg.getMessageType().name(), serverAddress); | 179 | + ServerAddress serverAddress = new ServerAddress(source.getHost(), source.getPort(), source.getServerType()); |
207 | if (log.isDebugEnabled()) { | 180 | if (log.isDebugEnabled()) { |
208 | - log.info("MSG: ", msg); | 181 | + log.info("Received msg [{}] from [{}]", msg.getMessageType().name(), serverAddress); |
182 | + log.info("MSG: {}", msg); | ||
209 | } | 183 | } |
210 | switch (msg.getMessageType()) { | 184 | switch (msg.getMessageType()) { |
211 | case CLUSTER_ACTOR_MESSAGE: | 185 | case CLUSTER_ACTOR_MESSAGE: |
@@ -239,7 +213,7 @@ public class DefaultActorService implements ActorService { | @@ -239,7 +213,7 @@ public class DefaultActorService implements ActorService { | ||
239 | actorContext.getTsSubService().onRemoteTsUpdate(serverAddress, msg.getPayload().toByteArray()); | 213 | actorContext.getTsSubService().onRemoteTsUpdate(serverAddress, msg.getPayload().toByteArray()); |
240 | break; | 214 | break; |
241 | case CLUSTER_RPC_FROM_DEVICE_RESPONSE_MESSAGE: | 215 | case CLUSTER_RPC_FROM_DEVICE_RESPONSE_MESSAGE: |
242 | - actorContext.getDeviceRpcService().processRemoteResponseFromDevice(serverAddress, msg.getPayload().toByteArray()); | 216 | + actorContext.getDeviceRpcService().processResponseToServerSideRPCRequestFromRemoteServer(serverAddress, msg.getPayload().toByteArray()); |
243 | break; | 217 | break; |
244 | case CLUSTER_DEVICE_STATE_SERVICE_MESSAGE: | 218 | case CLUSTER_DEVICE_STATE_SERVICE_MESSAGE: |
245 | actorContext.getDeviceStateService().onRemoteMsg(serverAddress, msg.getPayload().toByteArray()); | 219 | actorContext.getDeviceStateService().onRemoteMsg(serverAddress, msg.getPayload().toByteArray()); |
application/src/main/java/org/thingsboard/server/actors/session/ASyncMsgProcessor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.actors.session; | ||
17 | - | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.event.LoggingAdapter; | ||
20 | -import org.thingsboard.server.actors.ActorSystemContext; | ||
21 | -import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | ||
22 | -import org.thingsboard.server.common.data.id.SessionId; | ||
23 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
24 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
25 | -import org.thingsboard.server.common.msg.core.AttributesSubscribeMsg; | ||
26 | -import org.thingsboard.server.common.msg.core.ResponseMsg; | ||
27 | -import org.thingsboard.server.common.msg.core.RpcSubscribeMsg; | ||
28 | -import org.thingsboard.server.common.msg.core.SessionCloseMsg; | ||
29 | -import org.thingsboard.server.common.msg.core.SessionOpenMsg; | ||
30 | -import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg; | ||
31 | -import org.thingsboard.server.common.msg.session.BasicSessionActorToAdaptorMsg; | ||
32 | -import org.thingsboard.server.common.msg.session.FromDeviceMsg; | ||
33 | -import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg; | ||
34 | -import org.thingsboard.server.common.msg.session.SessionMsgType; | ||
35 | -import org.thingsboard.server.common.msg.session.SessionType; | ||
36 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | ||
37 | -import org.thingsboard.server.common.msg.session.TransportToDeviceSessionActorMsg; | ||
38 | -import org.thingsboard.server.common.msg.session.ex.SessionException; | ||
39 | - | ||
40 | -import java.util.HashMap; | ||
41 | -import java.util.Map; | ||
42 | -import java.util.Optional; | ||
43 | - | ||
44 | -class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor { | ||
45 | - | ||
46 | - private boolean firstMsg = true; | ||
47 | - private Map<Integer, DeviceToDeviceActorMsg> pendingMap = new HashMap<>(); | ||
48 | - private Optional<ServerAddress> currentTargetServer; | ||
49 | - private boolean subscribedToAttributeUpdates; | ||
50 | - private boolean subscribedToRpcCommands; | ||
51 | - | ||
52 | - public ASyncMsgProcessor(ActorSystemContext ctx, LoggingAdapter logger, SessionId sessionId) { | ||
53 | - super(ctx, logger, sessionId); | ||
54 | - } | ||
55 | - | ||
56 | - @Override | ||
57 | - protected void processToDeviceActorMsg(ActorContext ctx, TransportToDeviceSessionActorMsg msg) { | ||
58 | - updateSessionCtx(msg, SessionType.ASYNC); | ||
59 | - DeviceToDeviceActorMsg pendingMsg = toDeviceMsg(msg); | ||
60 | - FromDeviceMsg fromDeviceMsg = pendingMsg.getPayload(); | ||
61 | - if (firstMsg) { | ||
62 | - if (fromDeviceMsg.getMsgType() != SessionMsgType.SESSION_OPEN) { | ||
63 | - toDeviceMsg(new SessionOpenMsg()).ifPresent(m -> forwardToAppActor(ctx, m)); | ||
64 | - } | ||
65 | - firstMsg = false; | ||
66 | - } | ||
67 | - switch (fromDeviceMsg.getMsgType()) { | ||
68 | - case POST_TELEMETRY_REQUEST: | ||
69 | - case POST_ATTRIBUTES_REQUEST: | ||
70 | - FromDeviceRequestMsg requestMsg = (FromDeviceRequestMsg) fromDeviceMsg; | ||
71 | - if (requestMsg.getRequestId() >= 0) { | ||
72 | - logger.debug("[{}] Pending request {} registered", requestMsg.getRequestId(), requestMsg.getMsgType()); | ||
73 | - //TODO: handle duplicates. | ||
74 | - pendingMap.put(requestMsg.getRequestId(), pendingMsg); | ||
75 | - } | ||
76 | - break; | ||
77 | - case SUBSCRIBE_ATTRIBUTES_REQUEST: | ||
78 | - subscribedToAttributeUpdates = true; | ||
79 | - break; | ||
80 | - case UNSUBSCRIBE_ATTRIBUTES_REQUEST: | ||
81 | - subscribedToAttributeUpdates = false; | ||
82 | - break; | ||
83 | - case SUBSCRIBE_RPC_COMMANDS_REQUEST: | ||
84 | - subscribedToRpcCommands = true; | ||
85 | - break; | ||
86 | - case UNSUBSCRIBE_RPC_COMMANDS_REQUEST: | ||
87 | - subscribedToRpcCommands = false; | ||
88 | - break; | ||
89 | - default: | ||
90 | - break; | ||
91 | - } | ||
92 | - currentTargetServer = forwardToAppActor(ctx, pendingMsg); | ||
93 | - } | ||
94 | - | ||
95 | - @Override | ||
96 | - public void processToDeviceMsg(ActorContext context, ToDeviceMsg msg) { | ||
97 | - try { | ||
98 | - if (msg.getSessionMsgType() != SessionMsgType.SESSION_CLOSE) { | ||
99 | - switch (msg.getSessionMsgType()) { | ||
100 | - case STATUS_CODE_RESPONSE: | ||
101 | - case GET_ATTRIBUTES_RESPONSE: | ||
102 | - ResponseMsg responseMsg = (ResponseMsg) msg; | ||
103 | - if (responseMsg.getRequestId() >= 0) { | ||
104 | - logger.debug("[{}] Pending request processed: {}", responseMsg.getRequestId(), responseMsg); | ||
105 | - pendingMap.remove(responseMsg.getRequestId()); | ||
106 | - } | ||
107 | - break; | ||
108 | - default: | ||
109 | - break; | ||
110 | - } | ||
111 | - sessionCtx.onMsg(new BasicSessionActorToAdaptorMsg(this.sessionCtx, msg)); | ||
112 | - } else { | ||
113 | - sessionCtx.onMsg(org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg.onCredentialsRevoked(sessionCtx.getSessionId())); | ||
114 | - } | ||
115 | - } catch (SessionException e) { | ||
116 | - logger.warning("Failed to push session response msg", e); | ||
117 | - } | ||
118 | - } | ||
119 | - | ||
120 | - @Override | ||
121 | - public void processTimeoutMsg(ActorContext context, SessionTimeoutMsg msg) { | ||
122 | - // TODO Auto-generated method stub | ||
123 | - } | ||
124 | - | ||
125 | - @Override | ||
126 | - protected void cleanupSession(ActorContext ctx) { | ||
127 | - toDeviceMsg(new SessionCloseMsg()).ifPresent(m -> forwardToAppActor(ctx, m)); | ||
128 | - } | ||
129 | - | ||
130 | - @Override | ||
131 | - public void processClusterEvent(ActorContext context, ClusterEventMsg msg) { | ||
132 | - if (pendingMap.size() > 0 || subscribedToAttributeUpdates || subscribedToRpcCommands) { | ||
133 | - Optional<ServerAddress> newTargetServer = systemContext.getRoutingService().resolveById(getDeviceId()); | ||
134 | - if (!newTargetServer.equals(currentTargetServer)) { | ||
135 | - firstMsg = true; | ||
136 | - currentTargetServer = newTargetServer; | ||
137 | - pendingMap.values().forEach(v -> { | ||
138 | - forwardToAppActor(context, v, currentTargetServer); | ||
139 | - if (currentTargetServer.isPresent()) { | ||
140 | - logger.debug("[{}] Forwarded msg to new server: {}", sessionId, currentTargetServer.get()); | ||
141 | - } else { | ||
142 | - logger.debug("[{}] Forwarded msg to local server.", sessionId); | ||
143 | - } | ||
144 | - }); | ||
145 | - if (subscribedToAttributeUpdates) { | ||
146 | - toDeviceMsg(new AttributesSubscribeMsg()).ifPresent(m -> forwardToAppActor(context, m, currentTargetServer)); | ||
147 | - logger.debug("[{}] Forwarded attributes subscription.", sessionId); | ||
148 | - } | ||
149 | - if (subscribedToRpcCommands) { | ||
150 | - toDeviceMsg(new RpcSubscribeMsg()).ifPresent(m -> forwardToAppActor(context, m, currentTargetServer)); | ||
151 | - logger.debug("[{}] Forwarded rpc commands subscription.", sessionId); | ||
152 | - } | ||
153 | - } | ||
154 | - } | ||
155 | - } | ||
156 | -} |
application/src/main/java/org/thingsboard/server/actors/session/AbstractSessionActorMsgProcessor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.actors.session; | ||
17 | - | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.event.LoggingAdapter; | ||
21 | -import org.thingsboard.server.actors.ActorSystemContext; | ||
22 | -import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; | ||
23 | -import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | ||
24 | -import org.thingsboard.server.common.data.id.DeviceId; | ||
25 | -import org.thingsboard.server.common.data.id.SessionId; | ||
26 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
27 | -import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | ||
28 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
29 | -import org.thingsboard.server.common.msg.device.BasicDeviceToDeviceActorMsg; | ||
30 | -import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg; | ||
31 | -import org.thingsboard.server.common.msg.session.AdaptorToSessionActorMsg; | ||
32 | -import org.thingsboard.server.common.msg.session.FromDeviceMsg; | ||
33 | -import org.thingsboard.server.common.msg.session.SessionContext; | ||
34 | -import org.thingsboard.server.common.msg.session.SessionCtrlMsg; | ||
35 | -import org.thingsboard.server.common.msg.session.SessionType; | ||
36 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | ||
37 | -import org.thingsboard.server.common.msg.session.TransportToDeviceSessionActorMsg; | ||
38 | -import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; | ||
39 | - | ||
40 | -import java.util.Optional; | ||
41 | - | ||
42 | -abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgProcessor { | ||
43 | - | ||
44 | - protected final SessionId sessionId; | ||
45 | - protected SessionContext sessionCtx; | ||
46 | - protected DeviceToDeviceActorMsg deviceToDeviceActorMsgPrototype; | ||
47 | - | ||
48 | - protected AbstractSessionActorMsgProcessor(ActorSystemContext ctx, LoggingAdapter logger, SessionId sessionId) { | ||
49 | - super(ctx, logger); | ||
50 | - this.sessionId = sessionId; | ||
51 | - } | ||
52 | - | ||
53 | - protected abstract void processToDeviceActorMsg(ActorContext ctx, TransportToDeviceSessionActorMsg msg); | ||
54 | - | ||
55 | - protected abstract void processTimeoutMsg(ActorContext context, SessionTimeoutMsg msg); | ||
56 | - | ||
57 | - protected abstract void processToDeviceMsg(ActorContext context, ToDeviceMsg msg); | ||
58 | - | ||
59 | - public abstract void processClusterEvent(ActorContext context, ClusterEventMsg msg); | ||
60 | - | ||
61 | - protected void processSessionCtrlMsg(ActorContext ctx, SessionCtrlMsg msg) { | ||
62 | - if (msg instanceof SessionCloseMsg) { | ||
63 | - cleanupSession(ctx); | ||
64 | - terminateSession(ctx, sessionId); | ||
65 | - } | ||
66 | - } | ||
67 | - | ||
68 | - protected void cleanupSession(ActorContext ctx) { | ||
69 | - } | ||
70 | - | ||
71 | - protected void updateSessionCtx(TransportToDeviceSessionActorMsg msg, SessionType type) { | ||
72 | - sessionCtx = msg.getSessionMsg().getSessionContext(); | ||
73 | - deviceToDeviceActorMsgPrototype = new BasicDeviceToDeviceActorMsg(msg, type); | ||
74 | - } | ||
75 | - | ||
76 | - protected DeviceToDeviceActorMsg toDeviceMsg(TransportToDeviceSessionActorMsg msg) { | ||
77 | - AdaptorToSessionActorMsg adaptorMsg = msg.getSessionMsg(); | ||
78 | - return new BasicDeviceToDeviceActorMsg(deviceToDeviceActorMsgPrototype, adaptorMsg.getMsg()); | ||
79 | - } | ||
80 | - | ||
81 | - protected Optional<DeviceToDeviceActorMsg> toDeviceMsg(FromDeviceMsg msg) { | ||
82 | - if (deviceToDeviceActorMsgPrototype != null) { | ||
83 | - return Optional.of(new BasicDeviceToDeviceActorMsg(deviceToDeviceActorMsgPrototype, msg)); | ||
84 | - } else { | ||
85 | - return Optional.empty(); | ||
86 | - } | ||
87 | - } | ||
88 | - | ||
89 | - protected Optional<ServerAddress> forwardToAppActor(ActorContext ctx, DeviceToDeviceActorMsg toForward) { | ||
90 | - Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(toForward.getDeviceId()); | ||
91 | - forwardToAppActor(ctx, toForward, address); | ||
92 | - return address; | ||
93 | - } | ||
94 | - | ||
95 | - protected Optional<ServerAddress> forwardToAppActorIfAddressChanged(ActorContext ctx, DeviceToDeviceActorMsg toForward, Optional<ServerAddress> oldAddress) { | ||
96 | - | ||
97 | - Optional<ServerAddress> newAddress = systemContext.getRoutingService().resolveById(toForward.getDeviceId()); | ||
98 | - if (!newAddress.equals(oldAddress)) { | ||
99 | - getAppActor().tell(new SendToClusterMsg(toForward.getDeviceId(), toForward | ||
100 | - .toOtherAddress(systemContext.getRoutingService().getCurrentServer())), ctx.self()); | ||
101 | - } | ||
102 | - return newAddress; | ||
103 | - } | ||
104 | - | ||
105 | - protected void forwardToAppActor(ActorContext ctx, DeviceToDeviceActorMsg toForward, Optional<ServerAddress> address) { | ||
106 | - if (address.isPresent()) { | ||
107 | - systemContext.getRpcService().tell(systemContext.getEncodingService().convertToProtoDataMessage(address.get(), | ||
108 | - toForward.toOtherAddress(systemContext.getRoutingService().getCurrentServer()))); | ||
109 | - } else { | ||
110 | - getAppActor().tell(toForward, ctx.self()); | ||
111 | - } | ||
112 | - } | ||
113 | - | ||
114 | - public static void terminateSession(ActorContext ctx, SessionId sessionId) { | ||
115 | - ctx.parent().tell(new SessionTerminationMsg(sessionId), ActorRef.noSender()); | ||
116 | - ctx.stop(ctx.self()); | ||
117 | - } | ||
118 | - | ||
119 | - public DeviceId getDeviceId() { | ||
120 | - return deviceToDeviceActorMsgPrototype.getDeviceId(); | ||
121 | - } | ||
122 | -} |
application/src/main/java/org/thingsboard/server/actors/session/SessionActor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.actors.session; | ||
17 | - | ||
18 | -import akka.actor.OneForOneStrategy; | ||
19 | -import akka.actor.SupervisorStrategy; | ||
20 | -import akka.event.Logging; | ||
21 | -import akka.event.LoggingAdapter; | ||
22 | -import org.thingsboard.server.actors.ActorSystemContext; | ||
23 | -import org.thingsboard.server.actors.service.ContextAwareActor; | ||
24 | -import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
25 | -import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | ||
26 | -import org.thingsboard.server.common.data.id.SessionId; | ||
27 | -import org.thingsboard.server.common.msg.TbActorMsg; | ||
28 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
29 | -import org.thingsboard.server.common.msg.core.ActorSystemToDeviceSessionActorMsg; | ||
30 | -import org.thingsboard.server.common.msg.session.SessionCtrlMsg; | ||
31 | -import org.thingsboard.server.common.msg.session.SessionMsg; | ||
32 | -import org.thingsboard.server.common.msg.session.SessionType; | ||
33 | -import org.thingsboard.server.common.msg.session.TransportToDeviceSessionActorMsg; | ||
34 | -import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; | ||
35 | -import scala.concurrent.duration.Duration; | ||
36 | - | ||
37 | -public class SessionActor extends ContextAwareActor { | ||
38 | - | ||
39 | - private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | ||
40 | - | ||
41 | - private final SessionId sessionId; | ||
42 | - private AbstractSessionActorMsgProcessor processor; | ||
43 | - | ||
44 | - private SessionActor(ActorSystemContext systemContext, SessionId sessionId) { | ||
45 | - super(systemContext); | ||
46 | - this.sessionId = sessionId; | ||
47 | - } | ||
48 | - | ||
49 | - @Override | ||
50 | - public SupervisorStrategy supervisorStrategy() { | ||
51 | - return new OneForOneStrategy(-1, Duration.Inf(), | ||
52 | - throwable -> { | ||
53 | - logger.error(throwable, "Unknown session error"); | ||
54 | - if (throwable instanceof Error) { | ||
55 | - return OneForOneStrategy.escalate(); | ||
56 | - } else { | ||
57 | - return OneForOneStrategy.resume(); | ||
58 | - } | ||
59 | - }); | ||
60 | - } | ||
61 | - | ||
62 | - @Override | ||
63 | - protected boolean process(TbActorMsg msg) { | ||
64 | - switch (msg.getMsgType()) { | ||
65 | - case TRANSPORT_TO_DEVICE_SESSION_ACTOR_MSG: | ||
66 | - processTransportToSessionMsg((TransportToDeviceSessionActorMsg) msg); | ||
67 | - break; | ||
68 | - case ACTOR_SYSTEM_TO_DEVICE_SESSION_ACTOR_MSG: | ||
69 | - processActorsToSessionMsg((ActorSystemToDeviceSessionActorMsg) msg); | ||
70 | - break; | ||
71 | - case SESSION_TIMEOUT_MSG: | ||
72 | - processTimeoutMsg((SessionTimeoutMsg) msg); | ||
73 | - break; | ||
74 | - case SESSION_CTRL_MSG: | ||
75 | - processSessionCloseMsg((SessionCtrlMsg) msg); | ||
76 | - break; | ||
77 | - case CLUSTER_EVENT_MSG: | ||
78 | - processClusterEvent((ClusterEventMsg) msg); | ||
79 | - break; | ||
80 | - default: return false; | ||
81 | - } | ||
82 | - return true; | ||
83 | - } | ||
84 | - | ||
85 | - private void processClusterEvent(ClusterEventMsg msg) { | ||
86 | - processor.processClusterEvent(context(), msg); | ||
87 | - } | ||
88 | - | ||
89 | - private void processTransportToSessionMsg(TransportToDeviceSessionActorMsg msg) { | ||
90 | - initProcessor(msg); | ||
91 | - processor.processToDeviceActorMsg(context(), msg); | ||
92 | - } | ||
93 | - | ||
94 | - private void processActorsToSessionMsg(ActorSystemToDeviceSessionActorMsg msg) { | ||
95 | - processor.processToDeviceMsg(context(), msg.getMsg()); | ||
96 | - } | ||
97 | - | ||
98 | - private void processTimeoutMsg(SessionTimeoutMsg msg) { | ||
99 | - if (processor != null) { | ||
100 | - processor.processTimeoutMsg(context(), msg); | ||
101 | - } else { | ||
102 | - logger.warning("[{}] Can't process timeout msg: {} without processor", sessionId, msg); | ||
103 | - } | ||
104 | - } | ||
105 | - | ||
106 | - private void processSessionCloseMsg(SessionCtrlMsg msg) { | ||
107 | - if (processor != null) { | ||
108 | - processor.processSessionCtrlMsg(context(), msg); | ||
109 | - } else if (msg instanceof SessionCloseMsg) { | ||
110 | - AbstractSessionActorMsgProcessor.terminateSession(context(), sessionId); | ||
111 | - } else { | ||
112 | - logger.warning("[{}] Can't process session ctrl msg: {} without processor", sessionId, msg); | ||
113 | - } | ||
114 | - } | ||
115 | - | ||
116 | - private void initProcessor(TransportToDeviceSessionActorMsg msg) { | ||
117 | - if (processor == null) { | ||
118 | - SessionMsg sessionMsg = (SessionMsg) msg.getSessionMsg(); | ||
119 | - if (sessionMsg.getSessionContext().getSessionType() == SessionType.SYNC) { | ||
120 | - processor = new SyncMsgProcessor(systemContext, logger, sessionId); | ||
121 | - } else { | ||
122 | - processor = new ASyncMsgProcessor(systemContext, logger, sessionId); | ||
123 | - } | ||
124 | - } | ||
125 | - } | ||
126 | - | ||
127 | - public static class ActorCreator extends ContextBasedCreator<SessionActor> { | ||
128 | - private static final long serialVersionUID = 1L; | ||
129 | - | ||
130 | - private final SessionId sessionId; | ||
131 | - | ||
132 | - public ActorCreator(ActorSystemContext context, SessionId sessionId) { | ||
133 | - super(context); | ||
134 | - this.sessionId = sessionId; | ||
135 | - } | ||
136 | - | ||
137 | - @Override | ||
138 | - public SessionActor create() throws Exception { | ||
139 | - return new SessionActor(context, sessionId); | ||
140 | - } | ||
141 | - } | ||
142 | - | ||
143 | -} |
application/src/main/java/org/thingsboard/server/actors/session/SessionManagerActor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.actors.session; | ||
17 | - | ||
18 | -import akka.actor.ActorInitializationException; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.actor.InvalidActorNameException; | ||
21 | -import akka.actor.LocalActorRef; | ||
22 | -import akka.actor.OneForOneStrategy; | ||
23 | -import akka.actor.Props; | ||
24 | -import akka.actor.SupervisorStrategy; | ||
25 | -import akka.actor.Terminated; | ||
26 | -import akka.event.Logging; | ||
27 | -import akka.event.LoggingAdapter; | ||
28 | -import akka.japi.Function; | ||
29 | -import org.thingsboard.server.actors.ActorSystemContext; | ||
30 | -import org.thingsboard.server.actors.service.ContextAwareActor; | ||
31 | -import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
32 | -import org.thingsboard.server.actors.service.DefaultActorService; | ||
33 | -import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | ||
34 | -import org.thingsboard.server.common.data.id.SessionId; | ||
35 | -import org.thingsboard.server.common.msg.TbActorMsg; | ||
36 | -import org.thingsboard.server.common.msg.aware.SessionAwareMsg; | ||
37 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
38 | -import org.thingsboard.server.common.msg.core.ActorSystemToDeviceSessionActorMsg; | ||
39 | -import org.thingsboard.server.common.msg.core.SessionCloseMsg; | ||
40 | -import org.thingsboard.server.common.msg.session.SessionCtrlMsg; | ||
41 | -import scala.concurrent.duration.Duration; | ||
42 | - | ||
43 | -import java.util.HashMap; | ||
44 | -import java.util.Map; | ||
45 | - | ||
46 | -public class SessionManagerActor extends ContextAwareActor { | ||
47 | - | ||
48 | - private static final int INITIAL_SESSION_MAP_SIZE = 1024; | ||
49 | - | ||
50 | - private final LoggingAdapter log = Logging.getLogger(getContext().system(), this); | ||
51 | - | ||
52 | - private final Map<String, ActorRef> sessionActors; | ||
53 | - | ||
54 | - SessionManagerActor(ActorSystemContext systemContext) { | ||
55 | - super(systemContext); | ||
56 | - this.sessionActors = new HashMap<>(INITIAL_SESSION_MAP_SIZE); | ||
57 | - } | ||
58 | - | ||
59 | - @Override | ||
60 | - public SupervisorStrategy supervisorStrategy() { | ||
61 | - return strategy; | ||
62 | - } | ||
63 | - | ||
64 | - @Override | ||
65 | - protected boolean process(TbActorMsg msg) { | ||
66 | - //TODO Move everything here, to work with TbActorMsg | ||
67 | - return false; | ||
68 | - } | ||
69 | - | ||
70 | - @Override | ||
71 | - public void onReceive(Object msg) throws Exception { | ||
72 | - if (msg instanceof SessionCtrlMsg) { | ||
73 | - onSessionCtrlMsg((SessionCtrlMsg) msg); | ||
74 | - } else if (msg instanceof SessionAwareMsg) { | ||
75 | - forwardToSessionActor((SessionAwareMsg) msg); | ||
76 | - } else if (msg instanceof SessionTerminationMsg) { | ||
77 | - onSessionTermination((SessionTerminationMsg) msg); | ||
78 | - } else if (msg instanceof Terminated) { | ||
79 | - onTermination((Terminated) msg); | ||
80 | - } else if (msg instanceof SessionTimeoutMsg) { | ||
81 | - onSessionTimeout((SessionTimeoutMsg) msg); | ||
82 | - } else if (msg instanceof ClusterEventMsg) { | ||
83 | - broadcast(msg); | ||
84 | - } | ||
85 | - } | ||
86 | - | ||
87 | - private void broadcast(Object msg) { | ||
88 | - sessionActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | ||
89 | - } | ||
90 | - | ||
91 | - private void onSessionTimeout(SessionTimeoutMsg msg) { | ||
92 | - String sessionIdStr = msg.getSessionId().toUidStr(); | ||
93 | - ActorRef sessionActor = sessionActors.get(sessionIdStr); | ||
94 | - if (sessionActor != null) { | ||
95 | - sessionActor.tell(msg, ActorRef.noSender()); | ||
96 | - } | ||
97 | - } | ||
98 | - | ||
99 | - private void onSessionCtrlMsg(SessionCtrlMsg msg) { | ||
100 | - String sessionIdStr = msg.getSessionId().toUidStr(); | ||
101 | - ActorRef sessionActor = sessionActors.get(sessionIdStr); | ||
102 | - if (sessionActor != null) { | ||
103 | - sessionActor.tell(msg, ActorRef.noSender()); | ||
104 | - } | ||
105 | - } | ||
106 | - | ||
107 | - private void onSessionTermination(SessionTerminationMsg msg) { | ||
108 | - String sessionIdStr = msg.getId().toUidStr(); | ||
109 | - ActorRef sessionActor = sessionActors.remove(sessionIdStr); | ||
110 | - if (sessionActor != null) { | ||
111 | - log.debug("[{}] Removed session actor.", sessionIdStr); | ||
112 | - //TODO: onSubscriptionUpdate device actor about session close; | ||
113 | - } else { | ||
114 | - log.debug("[{}] Session actor was already removed.", sessionIdStr); | ||
115 | - } | ||
116 | - } | ||
117 | - | ||
118 | - private void forwardToSessionActor(SessionAwareMsg msg) { | ||
119 | - if (msg instanceof ActorSystemToDeviceSessionActorMsg || msg instanceof SessionCloseMsg) { | ||
120 | - String sessionIdStr = msg.getSessionId().toUidStr(); | ||
121 | - ActorRef sessionActor = sessionActors.get(sessionIdStr); | ||
122 | - if (sessionActor != null) { | ||
123 | - sessionActor.tell(msg, ActorRef.noSender()); | ||
124 | - } else { | ||
125 | - log.debug("[{}] Session actor was already removed.", sessionIdStr); | ||
126 | - } | ||
127 | - } else { | ||
128 | - try { | ||
129 | - getOrCreateSessionActor(msg.getSessionId()).tell(msg, self()); | ||
130 | - } catch (InvalidActorNameException e) { | ||
131 | - log.info("Invalid msg : {}", msg); | ||
132 | - } | ||
133 | - } | ||
134 | - } | ||
135 | - | ||
136 | - private ActorRef getOrCreateSessionActor(SessionId sessionId) { | ||
137 | - String sessionIdStr = sessionId.toUidStr(); | ||
138 | - ActorRef sessionActor = sessionActors.get(sessionIdStr); | ||
139 | - if (sessionActor == null) { | ||
140 | - log.debug("[{}] Creating session actor.", sessionIdStr); | ||
141 | - sessionActor = context().actorOf( | ||
142 | - Props.create(new SessionActor.ActorCreator(systemContext, sessionId)).withDispatcher(DefaultActorService.SESSION_DISPATCHER_NAME), | ||
143 | - sessionIdStr); | ||
144 | - sessionActors.put(sessionIdStr, sessionActor); | ||
145 | - log.debug("[{}] Created session actor.", sessionIdStr); | ||
146 | - } | ||
147 | - return sessionActor; | ||
148 | - } | ||
149 | - | ||
150 | - private void onTermination(Terminated message) { | ||
151 | - ActorRef terminated = message.actor(); | ||
152 | - if (terminated instanceof LocalActorRef) { | ||
153 | - log.info("Removed actor: {}.", terminated); | ||
154 | - //TODO: cleanup session actors map | ||
155 | - } else { | ||
156 | - throw new IllegalStateException("Remote actors are not supported!"); | ||
157 | - } | ||
158 | - } | ||
159 | - | ||
160 | - public static class ActorCreator extends ContextBasedCreator<SessionManagerActor> { | ||
161 | - private static final long serialVersionUID = 1L; | ||
162 | - | ||
163 | - public ActorCreator(ActorSystemContext context) { | ||
164 | - super(context); | ||
165 | - } | ||
166 | - | ||
167 | - @Override | ||
168 | - public SessionManagerActor create() throws Exception { | ||
169 | - return new SessionManagerActor(context); | ||
170 | - } | ||
171 | - } | ||
172 | - | ||
173 | - private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), new Function<Throwable, SupervisorStrategy.Directive>() { | ||
174 | - @Override | ||
175 | - public SupervisorStrategy.Directive apply(Throwable t) { | ||
176 | - logger.error(t, "Unknown failure"); | ||
177 | - return SupervisorStrategy.stop(); | ||
178 | - } | ||
179 | - }); | ||
180 | -} |
application/src/main/java/org/thingsboard/server/actors/session/SyncMsgProcessor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.actors.session; | ||
17 | - | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.event.LoggingAdapter; | ||
20 | -import org.thingsboard.server.actors.ActorSystemContext; | ||
21 | -import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | ||
22 | -import org.thingsboard.server.common.data.id.SessionId; | ||
23 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
24 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
25 | -import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg; | ||
26 | -import org.thingsboard.server.common.msg.session.BasicSessionActorToAdaptorMsg; | ||
27 | -import org.thingsboard.server.common.msg.session.SessionContext; | ||
28 | -import org.thingsboard.server.common.msg.session.SessionType; | ||
29 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | ||
30 | -import org.thingsboard.server.common.msg.session.TransportToDeviceSessionActorMsg; | ||
31 | -import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; | ||
32 | -import org.thingsboard.server.common.msg.session.ex.SessionException; | ||
33 | - | ||
34 | -import java.util.Optional; | ||
35 | - | ||
36 | -class SyncMsgProcessor extends AbstractSessionActorMsgProcessor { | ||
37 | - private DeviceToDeviceActorMsg pendingMsg; | ||
38 | - private Optional<ServerAddress> currentTargetServer; | ||
39 | - private boolean pendingResponse; | ||
40 | - | ||
41 | - public SyncMsgProcessor(ActorSystemContext ctx, LoggingAdapter logger, SessionId sessionId) { | ||
42 | - super(ctx, logger, sessionId); | ||
43 | - } | ||
44 | - | ||
45 | - @Override | ||
46 | - protected void processToDeviceActorMsg(ActorContext ctx, TransportToDeviceSessionActorMsg msg) { | ||
47 | - updateSessionCtx(msg, SessionType.SYNC); | ||
48 | - pendingMsg = toDeviceMsg(msg); | ||
49 | - pendingResponse = true; | ||
50 | - currentTargetServer = forwardToAppActor(ctx, pendingMsg); | ||
51 | - scheduleMsgWithDelay(ctx, new SessionTimeoutMsg(sessionId), getTimeout(systemContext, msg.getSessionMsg().getSessionContext()), ctx.parent()); | ||
52 | - } | ||
53 | - | ||
54 | - public void processTimeoutMsg(ActorContext context, SessionTimeoutMsg msg) { | ||
55 | - if (pendingResponse) { | ||
56 | - try { | ||
57 | - sessionCtx.onMsg(SessionCloseMsg.onTimeout(sessionId)); | ||
58 | - } catch (SessionException e) { | ||
59 | - logger.warning("Failed to push session close msg", e); | ||
60 | - } | ||
61 | - terminateSession(context, this.sessionId); | ||
62 | - } | ||
63 | - } | ||
64 | - | ||
65 | - public void processToDeviceMsg(ActorContext context, ToDeviceMsg msg) { | ||
66 | - try { | ||
67 | - sessionCtx.onMsg(new BasicSessionActorToAdaptorMsg(this.sessionCtx, msg)); | ||
68 | - pendingResponse = false; | ||
69 | - } catch (SessionException e) { | ||
70 | - logger.warning("Failed to push session response msg", e); | ||
71 | - } | ||
72 | - terminateSession(context, this.sessionId); | ||
73 | - } | ||
74 | - | ||
75 | - @Override | ||
76 | - public void processClusterEvent(ActorContext context, ClusterEventMsg msg) { | ||
77 | - if (pendingResponse) { | ||
78 | - Optional<ServerAddress> newTargetServer = forwardToAppActorIfAddressChanged(context, pendingMsg, currentTargetServer); | ||
79 | - if (logger.isDebugEnabled()) { | ||
80 | - if (!newTargetServer.equals(currentTargetServer)) { | ||
81 | - if (newTargetServer.isPresent()) { | ||
82 | - logger.debug("[{}] Forwarded msg to new server: {}", sessionId, newTargetServer.get()); | ||
83 | - } else { | ||
84 | - logger.debug("[{}] Forwarded msg to local server.", sessionId); | ||
85 | - } | ||
86 | - } | ||
87 | - } | ||
88 | - currentTargetServer = newTargetServer; | ||
89 | - } | ||
90 | - } | ||
91 | - | ||
92 | - private long getTimeout(ActorSystemContext ctx, SessionContext sessionCtx) { | ||
93 | - return sessionCtx.getTimeout() > 0 ? sessionCtx.getTimeout() : ctx.getSyncSessionTimeout(); | ||
94 | - } | ||
95 | -} |
application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java
@@ -22,61 +22,49 @@ import akka.event.LoggingAdapter; | @@ -22,61 +22,49 @@ import akka.event.LoggingAdapter; | ||
22 | import com.fasterxml.jackson.databind.ObjectMapper; | 22 | import com.fasterxml.jackson.databind.ObjectMapper; |
23 | import lombok.AllArgsConstructor; | 23 | import lombok.AllArgsConstructor; |
24 | import lombok.Data; | 24 | import lombok.Data; |
25 | +import lombok.extern.slf4j.Slf4j; | ||
25 | import org.thingsboard.server.actors.ActorSystemContext; | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
26 | import scala.concurrent.ExecutionContextExecutor; | 27 | import scala.concurrent.ExecutionContextExecutor; |
27 | import scala.concurrent.duration.Duration; | 28 | import scala.concurrent.duration.Duration; |
28 | 29 | ||
29 | import java.util.concurrent.TimeUnit; | 30 | import java.util.concurrent.TimeUnit; |
30 | 31 | ||
32 | +@Slf4j | ||
31 | public abstract class AbstractContextAwareMsgProcessor { | 33 | public abstract class AbstractContextAwareMsgProcessor { |
32 | 34 | ||
33 | protected final ActorSystemContext systemContext; | 35 | protected final ActorSystemContext systemContext; |
34 | - protected final LoggingAdapter logger; | ||
35 | protected final ObjectMapper mapper = new ObjectMapper(); | 36 | protected final ObjectMapper mapper = new ObjectMapper(); |
36 | 37 | ||
37 | - protected AbstractContextAwareMsgProcessor(ActorSystemContext systemContext, LoggingAdapter logger) { | 38 | + protected AbstractContextAwareMsgProcessor(ActorSystemContext systemContext) { |
38 | super(); | 39 | super(); |
39 | this.systemContext = systemContext; | 40 | this.systemContext = systemContext; |
40 | - this.logger = logger; | ||
41 | } | 41 | } |
42 | 42 | ||
43 | - protected ActorRef getAppActor() { | ||
44 | - return systemContext.getAppActor(); | ||
45 | - } | ||
46 | - | ||
47 | - protected Scheduler getScheduler() { | 43 | + private Scheduler getScheduler() { |
48 | return systemContext.getScheduler(); | 44 | return systemContext.getScheduler(); |
49 | } | 45 | } |
50 | 46 | ||
51 | - protected ExecutionContextExecutor getSystemDispatcher() { | 47 | + private ExecutionContextExecutor getSystemDispatcher() { |
52 | return systemContext.getActorSystem().dispatcher(); | 48 | return systemContext.getActorSystem().dispatcher(); |
53 | } | 49 | } |
54 | 50 | ||
55 | protected void schedulePeriodicMsgWithDelay(ActorContext ctx, Object msg, long delayInMs, long periodInMs) { | 51 | protected void schedulePeriodicMsgWithDelay(ActorContext ctx, Object msg, long delayInMs, long periodInMs) { |
56 | - schedulePeriodicMsgWithDelay(ctx, msg, delayInMs, periodInMs, ctx.self()); | 52 | + schedulePeriodicMsgWithDelay(msg, delayInMs, periodInMs, ctx.self()); |
57 | } | 53 | } |
58 | 54 | ||
59 | - protected void schedulePeriodicMsgWithDelay(ActorContext ctx, Object msg, long delayInMs, long periodInMs, ActorRef target) { | ||
60 | - logger.debug("Scheduling periodic msg {} every {} ms with delay {} ms", msg, periodInMs, delayInMs); | 55 | + private void schedulePeriodicMsgWithDelay(Object msg, long delayInMs, long periodInMs, ActorRef target) { |
56 | + log.debug("Scheduling periodic msg {} every {} ms with delay {} ms", msg, periodInMs, delayInMs); | ||
61 | getScheduler().schedule(Duration.create(delayInMs, TimeUnit.MILLISECONDS), Duration.create(periodInMs, TimeUnit.MILLISECONDS), target, msg, getSystemDispatcher(), null); | 57 | getScheduler().schedule(Duration.create(delayInMs, TimeUnit.MILLISECONDS), Duration.create(periodInMs, TimeUnit.MILLISECONDS), target, msg, getSystemDispatcher(), null); |
62 | } | 58 | } |
63 | 59 | ||
64 | - | ||
65 | protected void scheduleMsgWithDelay(ActorContext ctx, Object msg, long delayInMs) { | 60 | protected void scheduleMsgWithDelay(ActorContext ctx, Object msg, long delayInMs) { |
66 | - scheduleMsgWithDelay(ctx, msg, delayInMs, ctx.self()); | 61 | + scheduleMsgWithDelay(msg, delayInMs, ctx.self()); |
67 | } | 62 | } |
68 | 63 | ||
69 | - protected void scheduleMsgWithDelay(ActorContext ctx, Object msg, long delayInMs, ActorRef target) { | ||
70 | - logger.debug("Scheduling msg {} with delay {} ms", msg, delayInMs); | 64 | + private void scheduleMsgWithDelay(Object msg, long delayInMs, ActorRef target) { |
65 | + log.debug("Scheduling msg {} with delay {} ms", msg, delayInMs); | ||
71 | getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, getSystemDispatcher(), null); | 66 | getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, getSystemDispatcher(), null); |
72 | } | 67 | } |
73 | 68 | ||
74 | - @Data | ||
75 | - @AllArgsConstructor | ||
76 | - private static class ComponentConfiguration { | ||
77 | - private final String clazz; | ||
78 | - private final String name; | ||
79 | - private final String configuration; | ||
80 | - } | ||
81 | 69 | ||
82 | } | 70 | } |
@@ -19,6 +19,7 @@ import akka.actor.ActorContext; | @@ -19,6 +19,7 @@ import akka.actor.ActorContext; | ||
19 | import akka.event.LoggingAdapter; | 19 | import akka.event.LoggingAdapter; |
20 | import com.google.common.util.concurrent.FutureCallback; | 20 | import com.google.common.util.concurrent.FutureCallback; |
21 | import com.google.common.util.concurrent.Futures; | 21 | import com.google.common.util.concurrent.Futures; |
22 | +import lombok.extern.slf4j.Slf4j; | ||
22 | import org.thingsboard.server.actors.ActorSystemContext; | 23 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | import org.thingsboard.server.actors.stats.StatsPersistTick; | 24 | import org.thingsboard.server.actors.stats.StatsPersistTick; |
24 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
@@ -26,25 +27,25 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -26,25 +27,25 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
26 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | 27 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; |
27 | import org.thingsboard.server.common.msg.TbMsg; | 28 | import org.thingsboard.server.common.msg.TbMsg; |
28 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 29 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
29 | -import org.thingsboard.server.service.queue.MsgQueueService; | ||
30 | 30 | ||
31 | import javax.annotation.Nullable; | 31 | import javax.annotation.Nullable; |
32 | import java.util.function.Consumer; | 32 | import java.util.function.Consumer; |
33 | 33 | ||
34 | +@Slf4j | ||
34 | public abstract class ComponentMsgProcessor<T extends EntityId> extends AbstractContextAwareMsgProcessor { | 35 | public abstract class ComponentMsgProcessor<T extends EntityId> extends AbstractContextAwareMsgProcessor { |
35 | 36 | ||
36 | protected final TenantId tenantId; | 37 | protected final TenantId tenantId; |
37 | protected final T entityId; | 38 | protected final T entityId; |
38 | - protected final MsgQueueService queue; | ||
39 | protected ComponentLifecycleState state; | 39 | protected ComponentLifecycleState state; |
40 | 40 | ||
41 | - protected ComponentMsgProcessor(ActorSystemContext systemContext, LoggingAdapter logger, TenantId tenantId, T id) { | ||
42 | - super(systemContext, logger); | 41 | + protected ComponentMsgProcessor(ActorSystemContext systemContext, TenantId tenantId, T id) { |
42 | + super(systemContext); | ||
43 | this.tenantId = tenantId; | 43 | this.tenantId = tenantId; |
44 | this.entityId = id; | 44 | this.entityId = id; |
45 | - this.queue = systemContext.getMsgQueueService(); | ||
46 | } | 45 | } |
47 | 46 | ||
47 | + public abstract String getComponentName(); | ||
48 | + | ||
48 | public abstract void start(ActorContext context) throws Exception; | 49 | public abstract void start(ActorContext context) throws Exception; |
49 | 50 | ||
50 | public abstract void stop(ActorContext context) throws Exception; | 51 | public abstract void stop(ActorContext context) throws Exception; |
@@ -82,22 +83,9 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract | @@ -82,22 +83,9 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract | ||
82 | 83 | ||
83 | protected void checkActive() { | 84 | protected void checkActive() { |
84 | if (state != ComponentLifecycleState.ACTIVE) { | 85 | if (state != ComponentLifecycleState.ACTIVE) { |
85 | - throw new IllegalStateException("Rule chain is not active!"); | 86 | + log.warn("Rule chain is not active. Current state [{}] for processor [{}] tenant [{}]", state, tenantId, entityId); |
87 | + throw new IllegalStateException("Rule chain is not active! " + entityId + " - " + tenantId); | ||
86 | } | 88 | } |
87 | } | 89 | } |
88 | 90 | ||
89 | - protected void putToQueue(final TbMsg tbMsg, final Consumer<TbMsg> onSuccess) { | ||
90 | - EntityId entityId = tbMsg.getRuleNodeId() != null ? tbMsg.getRuleNodeId() : tbMsg.getRuleChainId(); | ||
91 | - Futures.addCallback(queue.put(this.tenantId, tbMsg, entityId.getId(), tbMsg.getClusterPartition()), new FutureCallback<Void>() { | ||
92 | - @Override | ||
93 | - public void onSuccess(@Nullable Void result) { | ||
94 | - onSuccess.accept(tbMsg); | ||
95 | - } | ||
96 | - | ||
97 | - @Override | ||
98 | - public void onFailure(Throwable t) { | ||
99 | - logger.debug("Failed to push message [{}] to queue due to [{}]", tbMsg, t); | ||
100 | - } | ||
101 | - }); | ||
102 | - } | ||
103 | } | 91 | } |
@@ -20,6 +20,8 @@ import akka.actor.ActorRef; | @@ -20,6 +20,8 @@ import akka.actor.ActorRef; | ||
20 | import akka.actor.Props; | 20 | import akka.actor.Props; |
21 | import akka.actor.UntypedActor; | 21 | import akka.actor.UntypedActor; |
22 | import akka.japi.Creator; | 22 | import akka.japi.Creator; |
23 | +import com.google.common.collect.BiMap; | ||
24 | +import com.google.common.collect.HashBiMap; | ||
23 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
24 | import org.thingsboard.server.actors.ActorSystemContext; | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
25 | import org.thingsboard.server.actors.service.ContextAwareActor; | 27 | import org.thingsboard.server.actors.service.ContextAwareActor; |
@@ -39,11 +41,11 @@ import java.util.Map; | @@ -39,11 +41,11 @@ import java.util.Map; | ||
39 | public abstract class EntityActorsManager<T extends EntityId, A extends UntypedActor, M extends SearchTextBased<? extends UUIDBased>> { | 41 | public abstract class EntityActorsManager<T extends EntityId, A extends UntypedActor, M extends SearchTextBased<? extends UUIDBased>> { |
40 | 42 | ||
41 | protected final ActorSystemContext systemContext; | 43 | protected final ActorSystemContext systemContext; |
42 | - protected final Map<T, ActorRef> actors; | 44 | + protected final BiMap<T, ActorRef> actors; |
43 | 45 | ||
44 | public EntityActorsManager(ActorSystemContext systemContext) { | 46 | public EntityActorsManager(ActorSystemContext systemContext) { |
45 | this.systemContext = systemContext; | 47 | this.systemContext = systemContext; |
46 | - this.actors = new HashMap<>(); | 48 | + this.actors = HashBiMap.create(); |
47 | } | 49 | } |
48 | 50 | ||
49 | protected abstract TenantId getTenantId(); | 51 | protected abstract TenantId getTenantId(); |
@@ -65,7 +67,8 @@ public abstract class EntityActorsManager<T extends EntityId, A extends UntypedA | @@ -65,7 +67,8 @@ public abstract class EntityActorsManager<T extends EntityId, A extends UntypedA | ||
65 | } | 67 | } |
66 | } | 68 | } |
67 | 69 | ||
68 | - public void visit(M entity, ActorRef actorRef) {} | 70 | + public void visit(M entity, ActorRef actorRef) { |
71 | + } | ||
69 | 72 | ||
70 | public ActorRef getOrCreateActor(ActorContext context, T entityId) { | 73 | public ActorRef getOrCreateActor(ActorContext context, T entityId) { |
71 | return actors.computeIfAbsent(entityId, eId -> | 74 | return actors.computeIfAbsent(entityId, eId -> |
@@ -50,7 +50,7 @@ public abstract class RuleChainManager extends EntityActorsManager<RuleChainId, | @@ -50,7 +50,7 @@ public abstract class RuleChainManager extends EntityActorsManager<RuleChainId, | ||
50 | 50 | ||
51 | @Override | 51 | @Override |
52 | public void visit(RuleChain entity, ActorRef actorRef) { | 52 | public void visit(RuleChain entity, ActorRef actorRef) { |
53 | - if (entity.isRoot()) { | 53 | + if (entity != null && entity.isRoot()) { |
54 | rootChain = entity; | 54 | rootChain = entity; |
55 | rootChainActor = actorRef; | 55 | rootChainActor = actorRef; |
56 | } | 56 | } |
@@ -15,10 +15,9 @@ | @@ -15,10 +15,9 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.stats; | 16 | package org.thingsboard.server.actors.stats; |
17 | 17 | ||
18 | -import akka.event.Logging; | ||
19 | -import akka.event.LoggingAdapter; | ||
20 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
21 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | +import lombok.extern.slf4j.Slf4j; | ||
22 | import org.thingsboard.server.actors.ActorSystemContext; | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | import org.thingsboard.server.actors.service.ContextAwareActor; | 22 | import org.thingsboard.server.actors.service.ContextAwareActor; |
24 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 23 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
@@ -27,9 +26,9 @@ import org.thingsboard.server.common.data.Event; | @@ -27,9 +26,9 @@ import org.thingsboard.server.common.data.Event; | ||
27 | import org.thingsboard.server.common.msg.TbActorMsg; | 26 | import org.thingsboard.server.common.msg.TbActorMsg; |
28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 27 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
29 | 28 | ||
29 | +@Slf4j | ||
30 | public class StatsActor extends ContextAwareActor { | 30 | public class StatsActor extends ContextAwareActor { |
31 | 31 | ||
32 | - private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | ||
33 | private final ObjectMapper mapper = new ObjectMapper(); | 32 | private final ObjectMapper mapper = new ObjectMapper(); |
34 | 33 | ||
35 | public StatsActor(ActorSystemContext context) { | 34 | public StatsActor(ActorSystemContext context) { |
@@ -43,13 +42,13 @@ public class StatsActor extends ContextAwareActor { | @@ -43,13 +42,13 @@ public class StatsActor extends ContextAwareActor { | ||
43 | } | 42 | } |
44 | 43 | ||
45 | @Override | 44 | @Override |
46 | - public void onReceive(Object msg) throws Exception { | ||
47 | - logger.debug("Received message: {}", msg); | 45 | + public void onReceive(Object msg) { |
46 | + log.debug("Received message: {}", msg); | ||
48 | if (msg instanceof StatsPersistMsg) { | 47 | if (msg instanceof StatsPersistMsg) { |
49 | try { | 48 | try { |
50 | onStatsPersistMsg((StatsPersistMsg) msg); | 49 | onStatsPersistMsg((StatsPersistMsg) msg); |
51 | } catch (Exception e) { | 50 | } catch (Exception e) { |
52 | - logger.warning("Failed to persist statistics: {}", msg, e); | 51 | + log.warn("Failed to persist statistics: {}", msg, e); |
53 | } | 52 | } |
54 | } | 53 | } |
55 | } | 54 | } |
@@ -75,7 +74,7 @@ public class StatsActor extends ContextAwareActor { | @@ -75,7 +74,7 @@ public class StatsActor extends ContextAwareActor { | ||
75 | } | 74 | } |
76 | 75 | ||
77 | @Override | 76 | @Override |
78 | - public StatsActor create() throws Exception { | 77 | + public StatsActor create() { |
79 | return new StatsActor(context); | 78 | return new StatsActor(context); |
80 | } | 79 | } |
81 | } | 80 | } |
@@ -17,15 +17,19 @@ package org.thingsboard.server.actors.tenant; | @@ -17,15 +17,19 @@ package org.thingsboard.server.actors.tenant; | ||
17 | 17 | ||
18 | import akka.actor.ActorInitializationException; | 18 | import akka.actor.ActorInitializationException; |
19 | import akka.actor.ActorRef; | 19 | import akka.actor.ActorRef; |
20 | +import akka.actor.LocalActorRef; | ||
20 | import akka.actor.OneForOneStrategy; | 21 | import akka.actor.OneForOneStrategy; |
21 | import akka.actor.Props; | 22 | import akka.actor.Props; |
22 | import akka.actor.SupervisorStrategy; | 23 | import akka.actor.SupervisorStrategy; |
24 | +import akka.actor.Terminated; | ||
23 | import akka.japi.Function; | 25 | import akka.japi.Function; |
26 | +import com.google.common.collect.BiMap; | ||
27 | +import com.google.common.collect.HashBiMap; | ||
28 | +import lombok.extern.slf4j.Slf4j; | ||
24 | import org.thingsboard.server.actors.ActorSystemContext; | 29 | import org.thingsboard.server.actors.ActorSystemContext; |
25 | -import org.thingsboard.server.actors.device.DeviceActor; | 30 | +import org.thingsboard.server.actors.device.DeviceActorCreator; |
26 | import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg; | 31 | import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg; |
27 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; | 32 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; |
28 | -import org.thingsboard.server.actors.ruleChain.RuleChainToRuleChainMsg; | ||
29 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 33 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
30 | import org.thingsboard.server.actors.service.DefaultActorService; | 34 | import org.thingsboard.server.actors.service.DefaultActorService; |
31 | import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager; | 35 | import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager; |
@@ -33,6 +37,7 @@ import org.thingsboard.server.common.data.EntityType; | @@ -33,6 +37,7 @@ import org.thingsboard.server.common.data.EntityType; | ||
33 | import org.thingsboard.server.common.data.id.DeviceId; | 37 | import org.thingsboard.server.common.data.id.DeviceId; |
34 | import org.thingsboard.server.common.data.id.RuleChainId; | 38 | import org.thingsboard.server.common.data.id.RuleChainId; |
35 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
40 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
36 | import org.thingsboard.server.common.data.rule.RuleChain; | 41 | import org.thingsboard.server.common.data.rule.RuleChain; |
37 | import org.thingsboard.server.common.msg.TbActorMsg; | 42 | import org.thingsboard.server.common.msg.TbActorMsg; |
38 | import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; | 43 | import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; |
@@ -47,15 +52,14 @@ import java.util.Map; | @@ -47,15 +52,14 @@ import java.util.Map; | ||
47 | public class TenantActor extends RuleChainManagerActor { | 52 | public class TenantActor extends RuleChainManagerActor { |
48 | 53 | ||
49 | private final TenantId tenantId; | 54 | private final TenantId tenantId; |
50 | - private final Map<DeviceId, ActorRef> deviceActors; | 55 | + private final BiMap<DeviceId, ActorRef> deviceActors; |
51 | 56 | ||
52 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { | 57 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { |
53 | super(systemContext, new TenantRuleChainManager(systemContext, tenantId)); | 58 | super(systemContext, new TenantRuleChainManager(systemContext, tenantId)); |
54 | this.tenantId = tenantId; | 59 | this.tenantId = tenantId; |
55 | - this.deviceActors = new HashMap<>(); | 60 | + this.deviceActors = HashBiMap.create(); |
56 | } | 61 | } |
57 | 62 | ||
58 | - | ||
59 | @Override | 63 | @Override |
60 | public SupervisorStrategy supervisorStrategy() { | 64 | public SupervisorStrategy supervisorStrategy() { |
61 | return strategy; | 65 | return strategy; |
@@ -63,16 +67,21 @@ public class TenantActor extends RuleChainManagerActor { | @@ -63,16 +67,21 @@ public class TenantActor extends RuleChainManagerActor { | ||
63 | 67 | ||
64 | @Override | 68 | @Override |
65 | public void preStart() { | 69 | public void preStart() { |
66 | - logger.info("[{}] Starting tenant actor.", tenantId); | 70 | + log.info("[{}] Starting tenant actor.", tenantId); |
67 | try { | 71 | try { |
68 | initRuleChains(); | 72 | initRuleChains(); |
69 | - logger.info("[{}] Tenant actor started.", tenantId); | 73 | + log.info("[{}] Tenant actor started.", tenantId); |
70 | } catch (Exception e) { | 74 | } catch (Exception e) { |
71 | - logger.error(e, "[{}] Unknown failure", tenantId); | 75 | + log.warn("[{}] Unknown failure", tenantId, e); |
72 | } | 76 | } |
73 | } | 77 | } |
74 | 78 | ||
75 | @Override | 79 | @Override |
80 | + public void postStop() { | ||
81 | + log.info("[{}] Stopping tenant actor.", tenantId); | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
76 | protected boolean process(TbActorMsg msg) { | 85 | protected boolean process(TbActorMsg msg) { |
77 | switch (msg.getMsgType()) { | 86 | switch (msg.getMsgType()) { |
78 | case CLUSTER_EVENT_MSG: | 87 | case CLUSTER_EVENT_MSG: |
@@ -87,7 +96,7 @@ public class TenantActor extends RuleChainManagerActor { | @@ -87,7 +96,7 @@ public class TenantActor extends RuleChainManagerActor { | ||
87 | case DEVICE_ACTOR_TO_RULE_ENGINE_MSG: | 96 | case DEVICE_ACTOR_TO_RULE_ENGINE_MSG: |
88 | onDeviceActorToRuleEngineMsg((DeviceActorToRuleEngineMsg) msg); | 97 | onDeviceActorToRuleEngineMsg((DeviceActorToRuleEngineMsg) msg); |
89 | break; | 98 | break; |
90 | - case DEVICE_SESSION_TO_DEVICE_ACTOR_MSG: | 99 | + case TRANSPORT_TO_DEVICE_ACTOR_MSG: |
91 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: | 100 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: |
92 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: | 101 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
93 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: | 102 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
@@ -105,29 +114,26 @@ public class TenantActor extends RuleChainManagerActor { | @@ -105,29 +114,26 @@ public class TenantActor extends RuleChainManagerActor { | ||
105 | return true; | 114 | return true; |
106 | } | 115 | } |
107 | 116 | ||
108 | - @Override | ||
109 | - protected void broadcast(Object msg) { | ||
110 | - super.broadcast(msg); | ||
111 | - deviceActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | ||
112 | - } | ||
113 | - | ||
114 | private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { | 117 | private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { |
115 | - if (ruleChainManager.getRootChainActor()!=null) | ||
116 | - ruleChainManager.getRootChainActor().tell(msg, self()); | ||
117 | - else logger.info("[{}] No Root Chain", msg); | 118 | + if (ruleChainManager.getRootChainActor() != null) { |
119 | + ruleChainManager.getRootChainActor().tell(msg, self()); | ||
120 | + } else { | ||
121 | + log.info("[{}] No Root Chain: {}", tenantId, msg); | ||
122 | + } | ||
118 | } | 123 | } |
119 | 124 | ||
120 | private void onDeviceActorToRuleEngineMsg(DeviceActorToRuleEngineMsg msg) { | 125 | private void onDeviceActorToRuleEngineMsg(DeviceActorToRuleEngineMsg msg) { |
121 | - if (ruleChainManager.getRootChainActor()!=null) | ||
122 | - ruleChainManager.getRootChainActor().tell(msg, self()); | ||
123 | - else logger.info("[{}] No Root Chain", msg); | 126 | + if (ruleChainManager.getRootChainActor() != null) { |
127 | + ruleChainManager.getRootChainActor().tell(msg, self()); | ||
128 | + } else { | ||
129 | + log.info("[{}] No Root Chain: {}", tenantId, msg); | ||
130 | + } | ||
124 | } | 131 | } |
125 | 132 | ||
126 | private void onRuleChainMsg(RuleChainAwareMsg msg) { | 133 | private void onRuleChainMsg(RuleChainAwareMsg msg) { |
127 | ruleChainManager.getOrCreateActor(context(), msg.getRuleChainId()).tell(msg, self()); | 134 | ruleChainManager.getOrCreateActor(context(), msg.getRuleChainId()).tell(msg, self()); |
128 | } | 135 | } |
129 | 136 | ||
130 | - | ||
131 | private void onToDeviceActorMsg(DeviceAwareMsg msg) { | 137 | private void onToDeviceActorMsg(DeviceAwareMsg msg) { |
132 | getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); | 138 | getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); |
133 | } | 139 | } |
@@ -142,13 +148,35 @@ public class TenantActor extends RuleChainManagerActor { | @@ -142,13 +148,35 @@ public class TenantActor extends RuleChainManagerActor { | ||
142 | } | 148 | } |
143 | target.tell(msg, ActorRef.noSender()); | 149 | target.tell(msg, ActorRef.noSender()); |
144 | } else { | 150 | } else { |
145 | - logger.debug("Invalid component lifecycle msg: {}", msg); | 151 | + log.debug("[{}] Invalid component lifecycle msg: {}", tenantId, msg); |
146 | } | 152 | } |
147 | } | 153 | } |
148 | 154 | ||
149 | private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { | 155 | private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { |
150 | - return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId)) | ||
151 | - .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), deviceId.toString())); | 156 | + return deviceActors.computeIfAbsent(deviceId, k -> { |
157 | + log.debug("[{}][{}] Creating device actor.", tenantId, deviceId); | ||
158 | + ActorRef deviceActor = context().actorOf(Props.create(new DeviceActorCreator(systemContext, tenantId, deviceId)) | ||
159 | + .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME) | ||
160 | + , deviceId.toString()); | ||
161 | + context().watch(deviceActor); | ||
162 | + log.debug("[{}][{}] Created device actor: {}.", tenantId, deviceId, deviceActor); | ||
163 | + return deviceActor; | ||
164 | + }); | ||
165 | + } | ||
166 | + | ||
167 | + @Override | ||
168 | + protected void processTermination(Terminated message) { | ||
169 | + ActorRef terminated = message.actor(); | ||
170 | + if (terminated instanceof LocalActorRef) { | ||
171 | + boolean removed = deviceActors.inverse().remove(terminated) != null; | ||
172 | + if (removed) { | ||
173 | + log.debug("[{}] Removed actor:", terminated); | ||
174 | + } else { | ||
175 | + log.warn("[{}] Removed actor was not found in the device map!"); | ||
176 | + } | ||
177 | + } else { | ||
178 | + throw new IllegalStateException("Remote actors are not supported!"); | ||
179 | + } | ||
152 | } | 180 | } |
153 | 181 | ||
154 | public static class ActorCreator extends ContextBasedCreator<TenantActor> { | 182 | public static class ActorCreator extends ContextBasedCreator<TenantActor> { |
@@ -162,7 +190,7 @@ public class TenantActor extends RuleChainManagerActor { | @@ -162,7 +190,7 @@ public class TenantActor extends RuleChainManagerActor { | ||
162 | } | 190 | } |
163 | 191 | ||
164 | @Override | 192 | @Override |
165 | - public TenantActor create() throws Exception { | 193 | + public TenantActor create() { |
166 | return new TenantActor(context, tenantId); | 194 | return new TenantActor(context, tenantId); |
167 | } | 195 | } |
168 | } | 196 | } |
@@ -170,8 +198,8 @@ public class TenantActor extends RuleChainManagerActor { | @@ -170,8 +198,8 @@ public class TenantActor extends RuleChainManagerActor { | ||
170 | private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), new Function<Throwable, SupervisorStrategy.Directive>() { | 198 | private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), new Function<Throwable, SupervisorStrategy.Directive>() { |
171 | @Override | 199 | @Override |
172 | public SupervisorStrategy.Directive apply(Throwable t) { | 200 | public SupervisorStrategy.Directive apply(Throwable t) { |
173 | - logger.error(t, "Unknown failure"); | ||
174 | - if(t instanceof ActorInitializationException){ | 201 | + log.warn("[{}] Unknown failure", tenantId, t); |
202 | + if (t instanceof ActorInitializationException) { | ||
175 | return SupervisorStrategy.stop(); | 203 | return SupervisorStrategy.stop(); |
176 | } else { | 204 | } else { |
177 | return SupervisorStrategy.resume(); | 205 | return SupervisorStrategy.resume(); |
@@ -83,7 +83,7 @@ public class AlarmController extends BaseController { | @@ -83,7 +83,7 @@ public class AlarmController extends BaseController { | ||
83 | Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm)); | 83 | Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm)); |
84 | logEntityAction(savedAlarm.getId(), savedAlarm, | 84 | logEntityAction(savedAlarm.getId(), savedAlarm, |
85 | getCurrentUser().getCustomerId(), | 85 | getCurrentUser().getCustomerId(), |
86 | - savedAlarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); | 86 | + alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); |
87 | return savedAlarm; | 87 | return savedAlarm; |
88 | } catch (Exception e) { | 88 | } catch (Exception e) { |
89 | logEntityAction(emptyId(EntityType.ALARM), alarm, | 89 | logEntityAction(emptyId(EntityType.ALARM), alarm, |
@@ -19,9 +19,11 @@ import com.datastax.driver.core.utils.UUIDs; | @@ -19,9 +19,11 @@ import com.datastax.driver.core.utils.UUIDs; | ||
19 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | import com.fasterxml.jackson.databind.node.ArrayNode; | 20 | import com.fasterxml.jackson.databind.node.ArrayNode; |
21 | import com.fasterxml.jackson.databind.node.ObjectNode; | 21 | import com.fasterxml.jackson.databind.node.ObjectNode; |
22 | +import lombok.Getter; | ||
22 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
23 | import org.apache.commons.lang3.StringUtils; | 24 | import org.apache.commons.lang3.StringUtils; |
24 | import org.springframework.beans.factory.annotation.Autowired; | 25 | import org.springframework.beans.factory.annotation.Autowired; |
26 | +import org.springframework.beans.factory.annotation.Value; | ||
25 | import org.springframework.security.core.Authentication; | 27 | import org.springframework.security.core.Authentication; |
26 | import org.springframework.security.core.context.SecurityContextHolder; | 28 | import org.springframework.security.core.context.SecurityContextHolder; |
27 | import org.springframework.web.bind.annotation.ExceptionHandler; | 29 | import org.springframework.web.bind.annotation.ExceptionHandler; |
@@ -48,14 +50,17 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; | @@ -48,14 +50,17 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; | ||
48 | import org.thingsboard.server.common.msg.TbMsg; | 50 | import org.thingsboard.server.common.msg.TbMsg; |
49 | import org.thingsboard.server.common.msg.TbMsgDataType; | 51 | import org.thingsboard.server.common.msg.TbMsgDataType; |
50 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 52 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
53 | +import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | ||
51 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | 54 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; |
52 | import org.thingsboard.server.dao.alarm.AlarmService; | 55 | import org.thingsboard.server.dao.alarm.AlarmService; |
53 | import org.thingsboard.server.dao.asset.AssetService; | 56 | import org.thingsboard.server.dao.asset.AssetService; |
57 | +import org.thingsboard.server.dao.attributes.AttributesService; | ||
54 | import org.thingsboard.server.dao.audit.AuditLogService; | 58 | import org.thingsboard.server.dao.audit.AuditLogService; |
55 | import org.thingsboard.server.dao.customer.CustomerService; | 59 | import org.thingsboard.server.dao.customer.CustomerService; |
56 | import org.thingsboard.server.dao.dashboard.DashboardService; | 60 | import org.thingsboard.server.dao.dashboard.DashboardService; |
57 | import org.thingsboard.server.dao.device.DeviceCredentialsService; | 61 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
58 | import org.thingsboard.server.dao.device.DeviceService; | 62 | import org.thingsboard.server.dao.device.DeviceService; |
63 | +import org.thingsboard.server.dao.entityview.EntityViewService; | ||
59 | import org.thingsboard.server.dao.exception.DataValidationException; | 64 | import org.thingsboard.server.dao.exception.DataValidationException; |
60 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 65 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
61 | import org.thingsboard.server.dao.model.ModelConstants; | 66 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -69,6 +74,7 @@ import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; | @@ -69,6 +74,7 @@ import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; | ||
69 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 74 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
70 | import org.thingsboard.server.service.security.model.SecurityUser; | 75 | import org.thingsboard.server.service.security.model.SecurityUser; |
71 | import org.thingsboard.server.service.state.DeviceStateService; | 76 | import org.thingsboard.server.service.state.DeviceStateService; |
77 | +import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | ||
72 | 78 | ||
73 | import javax.mail.MessagingException; | 79 | import javax.mail.MessagingException; |
74 | import javax.servlet.http.HttpServletRequest; | 80 | import javax.servlet.http.HttpServletRequest; |
@@ -139,6 +145,20 @@ public abstract class BaseController { | @@ -139,6 +145,20 @@ public abstract class BaseController { | ||
139 | @Autowired | 145 | @Autowired |
140 | protected DeviceStateService deviceStateService; | 146 | protected DeviceStateService deviceStateService; |
141 | 147 | ||
148 | + @Autowired | ||
149 | + protected EntityViewService entityViewService; | ||
150 | + | ||
151 | + @Autowired | ||
152 | + protected TelemetrySubscriptionService tsSubService; | ||
153 | + | ||
154 | + @Autowired | ||
155 | + protected AttributesService attributesService; | ||
156 | + | ||
157 | + @Value("${server.log_controller_error_stack_trace}") | ||
158 | + @Getter | ||
159 | + private boolean logControllerErrorStackTrace; | ||
160 | + | ||
161 | + | ||
142 | @ExceptionHandler(ThingsboardException.class) | 162 | @ExceptionHandler(ThingsboardException.class) |
143 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { | 163 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { |
144 | errorResponseHandler.handle(ex, response); | 164 | errorResponseHandler.handle(ex, response); |
@@ -149,7 +169,7 @@ public abstract class BaseController { | @@ -149,7 +169,7 @@ public abstract class BaseController { | ||
149 | } | 169 | } |
150 | 170 | ||
151 | private ThingsboardException handleException(Exception exception, boolean logException) { | 171 | private ThingsboardException handleException(Exception exception, boolean logException) { |
152 | - if (logException) { | 172 | + if (logException && logControllerErrorStackTrace) { |
153 | log.error("Error [{}]", exception.getMessage(), exception); | 173 | log.error("Error [{}]", exception.getMessage(), exception); |
154 | } | 174 | } |
155 | 175 | ||
@@ -247,7 +267,6 @@ public abstract class BaseController { | @@ -247,7 +267,6 @@ public abstract class BaseController { | ||
247 | 267 | ||
248 | Customer checkCustomerId(CustomerId customerId) throws ThingsboardException { | 268 | Customer checkCustomerId(CustomerId customerId) throws ThingsboardException { |
249 | try { | 269 | try { |
250 | - validateId(customerId, "Incorrect customerId " + customerId); | ||
251 | SecurityUser authUser = getCurrentUser(); | 270 | SecurityUser authUser = getCurrentUser(); |
252 | if (authUser.getAuthority() == Authority.SYS_ADMIN || | 271 | if (authUser.getAuthority() == Authority.SYS_ADMIN || |
253 | (authUser.getAuthority() != Authority.TENANT_ADMIN && | 272 | (authUser.getAuthority() != Authority.TENANT_ADMIN && |
@@ -255,9 +274,13 @@ public abstract class BaseController { | @@ -255,9 +274,13 @@ public abstract class BaseController { | ||
255 | throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, | 274 | throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, |
256 | ThingsboardErrorCode.PERMISSION_DENIED); | 275 | ThingsboardErrorCode.PERMISSION_DENIED); |
257 | } | 276 | } |
258 | - Customer customer = customerService.findCustomerById(customerId); | ||
259 | - checkCustomer(customer); | ||
260 | - return customer; | 277 | + if (customerId != null && !customerId.isNullUid()) { |
278 | + Customer customer = customerService.findCustomerById(customerId); | ||
279 | + checkCustomer(customer); | ||
280 | + return customer; | ||
281 | + } else { | ||
282 | + return null; | ||
283 | + } | ||
261 | } catch (Exception e) { | 284 | } catch (Exception e) { |
262 | throw handleException(e, false); | 285 | throw handleException(e, false); |
263 | } | 286 | } |
@@ -313,6 +336,9 @@ public abstract class BaseController { | @@ -313,6 +336,9 @@ public abstract class BaseController { | ||
313 | case USER: | 336 | case USER: |
314 | checkUserId(new UserId(entityId.getId())); | 337 | checkUserId(new UserId(entityId.getId())); |
315 | return; | 338 | return; |
339 | + case ENTITY_VIEW: | ||
340 | + checkEntityViewId(new EntityViewId(entityId.getId())); | ||
341 | + return; | ||
316 | default: | 342 | default: |
317 | throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); | 343 | throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); |
318 | } | 344 | } |
@@ -335,11 +361,26 @@ public abstract class BaseController { | @@ -335,11 +361,26 @@ public abstract class BaseController { | ||
335 | protected void checkDevice(Device device) throws ThingsboardException { | 361 | protected void checkDevice(Device device) throws ThingsboardException { |
336 | checkNotNull(device); | 362 | checkNotNull(device); |
337 | checkTenantId(device.getTenantId()); | 363 | checkTenantId(device.getTenantId()); |
338 | - if (device.getCustomerId() != null && !device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { | ||
339 | - checkCustomerId(device.getCustomerId()); | 364 | + checkCustomerId(device.getCustomerId()); |
365 | + } | ||
366 | + | ||
367 | + protected EntityView checkEntityViewId(EntityViewId entityViewId) throws ThingsboardException { | ||
368 | + try { | ||
369 | + validateId(entityViewId, "Incorrect entityViewId " + entityViewId); | ||
370 | + EntityView entityView = entityViewService.findEntityViewById(entityViewId); | ||
371 | + checkEntityView(entityView); | ||
372 | + return entityView; | ||
373 | + } catch (Exception e) { | ||
374 | + throw handleException(e, false); | ||
340 | } | 375 | } |
341 | } | 376 | } |
342 | 377 | ||
378 | + protected void checkEntityView(EntityView entityView) throws ThingsboardException { | ||
379 | + checkNotNull(entityView); | ||
380 | + checkTenantId(entityView.getTenantId()); | ||
381 | + checkCustomerId(entityView.getCustomerId()); | ||
382 | + } | ||
383 | + | ||
343 | Asset checkAssetId(AssetId assetId) throws ThingsboardException { | 384 | Asset checkAssetId(AssetId assetId) throws ThingsboardException { |
344 | try { | 385 | try { |
345 | validateId(assetId, "Incorrect assetId " + assetId); | 386 | validateId(assetId, "Incorrect assetId " + assetId); |
@@ -354,9 +395,7 @@ public abstract class BaseController { | @@ -354,9 +395,7 @@ public abstract class BaseController { | ||
354 | protected void checkAsset(Asset asset) throws ThingsboardException { | 395 | protected void checkAsset(Asset asset) throws ThingsboardException { |
355 | checkNotNull(asset); | 396 | checkNotNull(asset); |
356 | checkTenantId(asset.getTenantId()); | 397 | checkTenantId(asset.getTenantId()); |
357 | - if (asset.getCustomerId() != null && !asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { | ||
358 | - checkCustomerId(asset.getCustomerId()); | ||
359 | - } | 398 | + checkCustomerId(asset.getCustomerId()); |
360 | } | 399 | } |
361 | 400 | ||
362 | Alarm checkAlarmId(AlarmId alarmId) throws ThingsboardException { | 401 | Alarm checkAlarmId(AlarmId alarmId) throws ThingsboardException { |
@@ -465,8 +504,7 @@ public abstract class BaseController { | @@ -465,8 +504,7 @@ public abstract class BaseController { | ||
465 | ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException { | 504 | ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException { |
466 | try { | 505 | try { |
467 | log.debug("[{}] Lookup component descriptor", clazz); | 506 | log.debug("[{}] Lookup component descriptor", clazz); |
468 | - ComponentDescriptor componentDescriptor = checkNotNull(componentDescriptorService.getComponent(clazz)); | ||
469 | - return componentDescriptor; | 507 | + return checkNotNull(componentDescriptorService.getComponent(clazz)); |
470 | } catch (Exception e) { | 508 | } catch (Exception e) { |
471 | throw handleException(e, false); | 509 | throw handleException(e, false); |
472 | } | 510 | } |
@@ -530,16 +568,16 @@ public abstract class BaseController { | @@ -530,16 +568,16 @@ public abstract class BaseController { | ||
530 | } | 568 | } |
531 | 569 | ||
532 | protected <I extends EntityId> I emptyId(EntityType entityType) { | 570 | protected <I extends EntityId> I emptyId(EntityType entityType) { |
533 | - return (I)EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); | 571 | + return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); |
534 | } | 572 | } |
535 | 573 | ||
536 | protected <E extends HasName, I extends EntityId> void logEntityAction(I entityId, E entity, CustomerId customerId, | 574 | protected <E extends HasName, I extends EntityId> void logEntityAction(I entityId, E entity, CustomerId customerId, |
537 | - ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { | 575 | + ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { |
538 | logEntityAction(getCurrentUser(), entityId, entity, customerId, actionType, e, additionalInfo); | 576 | logEntityAction(getCurrentUser(), entityId, entity, customerId, actionType, e, additionalInfo); |
539 | } | 577 | } |
540 | 578 | ||
541 | protected <E extends HasName, I extends EntityId> void logEntityAction(User user, I entityId, E entity, CustomerId customerId, | 579 | protected <E extends HasName, I extends EntityId> void logEntityAction(User user, I entityId, E entity, CustomerId customerId, |
542 | - ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { | 580 | + ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { |
543 | if (customerId == null || customerId.isNullUid()) { | 581 | if (customerId == null || customerId.isNullUid()) { |
544 | customerId = user.getCustomerId(); | 582 | customerId = user.getCustomerId(); |
545 | } | 583 | } |
@@ -555,7 +593,7 @@ public abstract class BaseController { | @@ -555,7 +593,7 @@ public abstract class BaseController { | ||
555 | } | 593 | } |
556 | 594 | ||
557 | private <E extends HasName, I extends EntityId> void pushEntityActionToRuleEngine(I entityId, E entity, User user, CustomerId customerId, | 595 | private <E extends HasName, I extends EntityId> void pushEntityActionToRuleEngine(I entityId, E entity, User user, CustomerId customerId, |
558 | - ActionType actionType, Object... additionalInfo) { | 596 | + ActionType actionType, Object... additionalInfo) { |
559 | String msgType = null; | 597 | String msgType = null; |
560 | switch (actionType) { | 598 | switch (actionType) { |
561 | case ADDED: | 599 | case ADDED: |
@@ -579,6 +617,12 @@ public abstract class BaseController { | @@ -579,6 +617,12 @@ public abstract class BaseController { | ||
579 | case ATTRIBUTES_DELETED: | 617 | case ATTRIBUTES_DELETED: |
580 | msgType = DataConstants.ATTRIBUTES_DELETED; | 618 | msgType = DataConstants.ATTRIBUTES_DELETED; |
581 | break; | 619 | break; |
620 | + case ALARM_ACK: | ||
621 | + msgType = DataConstants.ALARM_ACK; | ||
622 | + break; | ||
623 | + case ALARM_CLEAR: | ||
624 | + msgType = DataConstants.ALARM_CLEAR; | ||
625 | + break; | ||
582 | } | 626 | } |
583 | if (!StringUtils.isEmpty(msgType)) { | 627 | if (!StringUtils.isEmpty(msgType)) { |
584 | try { | 628 | try { |
@@ -628,7 +672,7 @@ public abstract class BaseController { | @@ -628,7 +672,7 @@ public abstract class BaseController { | ||
628 | String scope = extractParameter(String.class, 0, additionalInfo); | 672 | String scope = extractParameter(String.class, 0, additionalInfo); |
629 | List<String> keys = extractParameter(List.class, 1, additionalInfo); | 673 | List<String> keys = extractParameter(List.class, 1, additionalInfo); |
630 | metaData.putValue("scope", scope); | 674 | metaData.putValue("scope", scope); |
631 | - ArrayNode attrsArrayNode = entityNode.putArray("attributes"); | 675 | + ArrayNode attrsArrayNode = entityNode.putArray("attributes"); |
632 | if (keys != null) { | 676 | if (keys != null) { |
633 | keys.forEach(attrsArrayNode::add); | 677 | keys.forEach(attrsArrayNode::add); |
634 | } | 678 | } |
@@ -637,7 +681,7 @@ public abstract class BaseController { | @@ -637,7 +681,7 @@ public abstract class BaseController { | ||
637 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), msgType, entityId, metaData, TbMsgDataType.JSON | 681 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), msgType, entityId, metaData, TbMsgDataType.JSON |
638 | , json.writeValueAsString(entityNode) | 682 | , json.writeValueAsString(entityNode) |
639 | , null, null, 0L); | 683 | , null, null, 0L); |
640 | - actorService.onMsg(new ServiceToRuleEngineMsg(user.getTenantId(), tbMsg)); | 684 | + actorService.onMsg(new SendToClusterMsg(entityId, new ServiceToRuleEngineMsg(user.getTenantId(), tbMsg))); |
641 | } catch (Exception e) { | 685 | } catch (Exception e) { |
642 | log.warn("[{}] Failed to push entity action to rule engine: {}", entityId, actionType, e); | 686 | log.warn("[{}] Failed to push entity action to rule engine: {}", entityId, actionType, e); |
643 | } | 687 | } |
@@ -15,6 +15,8 @@ | @@ -15,6 +15,8 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | +import lombok.Getter; | ||
19 | +import org.springframework.beans.factory.annotation.Value; | ||
18 | import org.springframework.http.HttpStatus; | 20 | import org.springframework.http.HttpStatus; |
19 | import org.springframework.security.access.prepost.PreAuthorize; | 21 | import org.springframework.security.access.prepost.PreAuthorize; |
20 | import org.springframework.web.bind.annotation.PathVariable; | 22 | import org.springframework.web.bind.annotation.PathVariable; |
@@ -49,6 +51,10 @@ public class DashboardController extends BaseController { | @@ -49,6 +51,10 @@ public class DashboardController extends BaseController { | ||
49 | 51 | ||
50 | public static final String DASHBOARD_ID = "dashboardId"; | 52 | public static final String DASHBOARD_ID = "dashboardId"; |
51 | 53 | ||
54 | + @Value("${dashboard.max_datapoints_limit}") | ||
55 | + private long maxDatapointsLimit; | ||
56 | + | ||
57 | + | ||
52 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 58 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
53 | @RequestMapping(value = "/dashboard/serverTime", method = RequestMethod.GET) | 59 | @RequestMapping(value = "/dashboard/serverTime", method = RequestMethod.GET) |
54 | @ResponseBody | 60 | @ResponseBody |
@@ -57,6 +63,13 @@ public class DashboardController extends BaseController { | @@ -57,6 +63,13 @@ public class DashboardController extends BaseController { | ||
57 | } | 63 | } |
58 | 64 | ||
59 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 65 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
66 | + @RequestMapping(value = "/dashboard/maxDatapointsLimit", method = RequestMethod.GET) | ||
67 | + @ResponseBody | ||
68 | + public long getMaxDatapointsLimit() throws ThingsboardException { | ||
69 | + return maxDatapointsLimit; | ||
70 | + } | ||
71 | + | ||
72 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | ||
60 | @RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET) | 73 | @RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET) |
61 | @ResponseBody | 74 | @ResponseBody |
62 | public DashboardInfo getDashboardInfoById(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { | 75 | public DashboardInfo getDashboardInfoById(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { |
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.controller; | ||
17 | + | ||
18 | +import com.google.common.util.concurrent.FutureCallback; | ||
19 | +import com.google.common.util.concurrent.Futures; | ||
20 | +import com.google.common.util.concurrent.ListenableFuture; | ||
21 | +import lombok.extern.slf4j.Slf4j; | ||
22 | +import org.springframework.http.HttpStatus; | ||
23 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
24 | +import org.springframework.web.bind.annotation.PathVariable; | ||
25 | +import org.springframework.web.bind.annotation.RequestBody; | ||
26 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
27 | +import org.springframework.web.bind.annotation.RequestMethod; | ||
28 | +import org.springframework.web.bind.annotation.RequestParam; | ||
29 | +import org.springframework.web.bind.annotation.ResponseBody; | ||
30 | +import org.springframework.web.bind.annotation.ResponseStatus; | ||
31 | +import org.springframework.web.bind.annotation.RestController; | ||
32 | +import org.thingsboard.server.common.data.Customer; | ||
33 | +import org.thingsboard.server.common.data.DataConstants; | ||
34 | +import org.thingsboard.server.common.data.EntitySubtype; | ||
35 | +import org.thingsboard.server.common.data.EntityType; | ||
36 | +import org.thingsboard.server.common.data.EntityView; | ||
37 | +import org.thingsboard.server.common.data.audit.ActionType; | ||
38 | +import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; | ||
39 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
40 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
41 | +import org.thingsboard.server.common.data.id.EntityId; | ||
42 | +import org.thingsboard.server.common.data.id.EntityViewId; | ||
43 | +import org.thingsboard.server.common.data.id.TenantId; | ||
44 | +import org.thingsboard.server.common.data.id.UUIDBased; | ||
45 | +import org.thingsboard.server.common.data.kv.AttributeKvEntry; | ||
46 | +import org.thingsboard.server.common.data.page.TextPageData; | ||
47 | +import org.thingsboard.server.common.data.page.TextPageLink; | ||
48 | +import org.thingsboard.server.dao.exception.IncorrectParameterException; | ||
49 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
50 | +import org.thingsboard.server.service.security.model.SecurityUser; | ||
51 | + | ||
52 | +import javax.annotation.Nullable; | ||
53 | +import java.util.ArrayList; | ||
54 | +import java.util.Collection; | ||
55 | +import java.util.List; | ||
56 | +import java.util.concurrent.ExecutionException; | ||
57 | +import java.util.stream.Collectors; | ||
58 | + | ||
59 | +import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID; | ||
60 | + | ||
61 | +/** | ||
62 | + * Created by Victor Basanets on 8/28/2017. | ||
63 | + */ | ||
64 | +@RestController | ||
65 | +@RequestMapping("/api") | ||
66 | +@Slf4j | ||
67 | +public class EntityViewController extends BaseController { | ||
68 | + | ||
69 | + public static final String ENTITY_VIEW_ID = "entityViewId"; | ||
70 | + | ||
71 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
72 | + @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET) | ||
73 | + @ResponseBody | ||
74 | + public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { | ||
75 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | ||
76 | + try { | ||
77 | + return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId))); | ||
78 | + } catch (Exception e) { | ||
79 | + throw handleException(e); | ||
80 | + } | ||
81 | + } | ||
82 | + | ||
83 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
84 | + @RequestMapping(value = "/entityView", method = RequestMethod.POST) | ||
85 | + @ResponseBody | ||
86 | + public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { | ||
87 | + try { | ||
88 | + entityView.setTenantId(getCurrentUser().getTenantId()); | ||
89 | + EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); | ||
90 | + List<ListenableFuture<List<Void>>> futures = new ArrayList<>(); | ||
91 | + if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) { | ||
92 | + futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs(), getCurrentUser())); | ||
93 | + futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs(), getCurrentUser())); | ||
94 | + futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh(), getCurrentUser())); | ||
95 | + } | ||
96 | + for (ListenableFuture<List<Void>> future : futures) { | ||
97 | + try { | ||
98 | + future.get(); | ||
99 | + } catch (InterruptedException | ExecutionException e) { | ||
100 | + throw new RuntimeException("Failed to copy attributes to entity view", e); | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + logEntityAction(savedEntityView.getId(), savedEntityView, null, | ||
105 | + entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); | ||
106 | + return savedEntityView; | ||
107 | + } catch (Exception e) { | ||
108 | + logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, | ||
109 | + entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); | ||
110 | + throw handleException(e); | ||
111 | + } | ||
112 | + } | ||
113 | + | ||
114 | + private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys, SecurityUser user) throws ThingsboardException { | ||
115 | + EntityViewId entityId = entityView.getId(); | ||
116 | + if (keys != null && !keys.isEmpty()) { | ||
117 | + ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys); | ||
118 | + return Futures.transform(getAttrFuture, attributeKvEntries -> { | ||
119 | + List<AttributeKvEntry> attributes; | ||
120 | + if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) { | ||
121 | + attributes = | ||
122 | + attributeKvEntries.stream() | ||
123 | + .filter(attributeKvEntry -> { | ||
124 | + long startTime = entityView.getStartTimeMs(); | ||
125 | + long endTime = entityView.getEndTimeMs(); | ||
126 | + long lastUpdateTs = attributeKvEntry.getLastUpdateTs(); | ||
127 | + return startTime == 0 && endTime == 0 || | ||
128 | + (endTime == 0 && startTime < lastUpdateTs) || | ||
129 | + (startTime == 0 && endTime > lastUpdateTs) | ||
130 | + ? true : startTime < lastUpdateTs && endTime > lastUpdateTs; | ||
131 | + }).collect(Collectors.toList()); | ||
132 | + tsSubService.saveAndNotify(entityId, scope, attributes, new FutureCallback<Void>() { | ||
133 | + @Override | ||
134 | + public void onSuccess(@Nullable Void tmp) { | ||
135 | + try { | ||
136 | + logAttributesUpdated(user, entityId, scope, attributes, null); | ||
137 | + } catch (ThingsboardException e) { | ||
138 | + log.error("Failed to log attribute updates", e); | ||
139 | + } | ||
140 | + } | ||
141 | + | ||
142 | + @Override | ||
143 | + public void onFailure(Throwable t) { | ||
144 | + try { | ||
145 | + logAttributesUpdated(user, entityId, scope, attributes, t); | ||
146 | + } catch (ThingsboardException e) { | ||
147 | + log.error("Failed to log attribute updates", e); | ||
148 | + } | ||
149 | + } | ||
150 | + }); | ||
151 | + } | ||
152 | + return null; | ||
153 | + }); | ||
154 | + } else { | ||
155 | + return Futures.immediateFuture(null); | ||
156 | + } | ||
157 | + } | ||
158 | + | ||
159 | + private void logAttributesUpdated(SecurityUser user, EntityId entityId, String scope, List<AttributeKvEntry> attributes, Throwable e) throws ThingsboardException { | ||
160 | + logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.ATTRIBUTES_UPDATED, toException(e), | ||
161 | + scope, attributes); | ||
162 | + } | ||
163 | + | ||
164 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
165 | + @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE) | ||
166 | + @ResponseStatus(value = HttpStatus.OK) | ||
167 | + public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { | ||
168 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | ||
169 | + try { | ||
170 | + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); | ||
171 | + EntityView entityView = checkEntityViewId(entityViewId); | ||
172 | + entityViewService.deleteEntityView(entityViewId); | ||
173 | + logEntityAction(entityViewId, entityView, entityView.getCustomerId(), | ||
174 | + ActionType.DELETED, null, strEntityViewId); | ||
175 | + } catch (Exception e) { | ||
176 | + logEntityAction(emptyId(EntityType.ENTITY_VIEW), | ||
177 | + null, | ||
178 | + null, | ||
179 | + ActionType.DELETED, e, strEntityViewId); | ||
180 | + throw handleException(e); | ||
181 | + } | ||
182 | + } | ||
183 | + | ||
184 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
185 | + @RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET) | ||
186 | + @ResponseBody | ||
187 | + public EntityView getTenantEntityView( | ||
188 | + @RequestParam String entityViewName) throws ThingsboardException { | ||
189 | + try { | ||
190 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
191 | + return checkNotNull(entityViewService.findEntityViewByTenantIdAndName(tenantId, entityViewName)); | ||
192 | + } catch (Exception e) { | ||
193 | + throw handleException(e); | ||
194 | + } | ||
195 | + } | ||
196 | + | ||
197 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
198 | + @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST) | ||
199 | + @ResponseBody | ||
200 | + public EntityView assignEntityViewToCustomer(@PathVariable(CUSTOMER_ID) String strCustomerId, | ||
201 | + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { | ||
202 | + checkParameter(CUSTOMER_ID, strCustomerId); | ||
203 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | ||
204 | + try { | ||
205 | + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | ||
206 | + Customer customer = checkCustomerId(customerId); | ||
207 | + | ||
208 | + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); | ||
209 | + checkEntityViewId(entityViewId); | ||
210 | + | ||
211 | + EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(entityViewId, customerId)); | ||
212 | + logEntityAction(entityViewId, savedEntityView, | ||
213 | + savedEntityView.getCustomerId(), | ||
214 | + ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, strCustomerId, customer.getName()); | ||
215 | + return savedEntityView; | ||
216 | + } catch (Exception e) { | ||
217 | + logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, | ||
218 | + null, | ||
219 | + ActionType.ASSIGNED_TO_CUSTOMER, e, strEntityViewId, strCustomerId); | ||
220 | + throw handleException(e); | ||
221 | + } | ||
222 | + } | ||
223 | + | ||
224 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
225 | + @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE) | ||
226 | + @ResponseBody | ||
227 | + public EntityView unassignEntityViewFromCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { | ||
228 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | ||
229 | + try { | ||
230 | + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); | ||
231 | + EntityView entityView = checkEntityViewId(entityViewId); | ||
232 | + if (entityView.getCustomerId() == null || entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { | ||
233 | + throw new IncorrectParameterException("Entity View isn't assigned to any customer!"); | ||
234 | + } | ||
235 | + Customer customer = checkCustomerId(entityView.getCustomerId()); | ||
236 | + EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(entityViewId)); | ||
237 | + logEntityAction(entityViewId, entityView, | ||
238 | + entityView.getCustomerId(), | ||
239 | + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName()); | ||
240 | + | ||
241 | + return savedEntityView; | ||
242 | + } catch (Exception e) { | ||
243 | + logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, | ||
244 | + null, | ||
245 | + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strEntityViewId); | ||
246 | + throw handleException(e); | ||
247 | + } | ||
248 | + } | ||
249 | + | ||
250 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
251 | + @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"limit"}, method = RequestMethod.GET) | ||
252 | + @ResponseBody | ||
253 | + public TextPageData<EntityView> getCustomerEntityViews( | ||
254 | + @PathVariable("customerId") String strCustomerId, | ||
255 | + @RequestParam int limit, | ||
256 | + @RequestParam(required = false) String type, | ||
257 | + @RequestParam(required = false) String textSearch, | ||
258 | + @RequestParam(required = false) String idOffset, | ||
259 | + @RequestParam(required = false) String textOffset) throws ThingsboardException { | ||
260 | + checkParameter("customerId", strCustomerId); | ||
261 | + try { | ||
262 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
263 | + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | ||
264 | + checkCustomerId(customerId); | ||
265 | + TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | ||
266 | + if (type != null && type.trim().length() > 0) { | ||
267 | + return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type)); | ||
268 | + } else { | ||
269 | + return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
270 | + } | ||
271 | + } catch (Exception e) { | ||
272 | + throw handleException(e); | ||
273 | + } | ||
274 | + } | ||
275 | + | ||
276 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
277 | + @RequestMapping(value = "/tenant/entityViews", params = {"limit"}, method = RequestMethod.GET) | ||
278 | + @ResponseBody | ||
279 | + public TextPageData<EntityView> getTenantEntityViews( | ||
280 | + @RequestParam int limit, | ||
281 | + @RequestParam(required = false) String type, | ||
282 | + @RequestParam(required = false) String textSearch, | ||
283 | + @RequestParam(required = false) String idOffset, | ||
284 | + @RequestParam(required = false) String textOffset) throws ThingsboardException { | ||
285 | + try { | ||
286 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
287 | + TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | ||
288 | + | ||
289 | + if (type != null && type.trim().length() > 0) { | ||
290 | + return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type)); | ||
291 | + } else { | ||
292 | + return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink)); | ||
293 | + } | ||
294 | + } catch (Exception e) { | ||
295 | + throw handleException(e); | ||
296 | + } | ||
297 | + } | ||
298 | + | ||
299 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
300 | + @RequestMapping(value = "/entityViews", method = RequestMethod.POST) | ||
301 | + @ResponseBody | ||
302 | + public List<EntityView> findByQuery(@RequestBody EntityViewSearchQuery query) throws ThingsboardException { | ||
303 | + checkNotNull(query); | ||
304 | + checkNotNull(query.getParameters()); | ||
305 | + checkNotNull(query.getEntityViewTypes()); | ||
306 | + checkEntityId(query.getParameters().getEntityId()); | ||
307 | + try { | ||
308 | + List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(query).get()); | ||
309 | + entityViews = entityViews.stream().filter(entityView -> { | ||
310 | + try { | ||
311 | + checkEntityView(entityView); | ||
312 | + return true; | ||
313 | + } catch (ThingsboardException e) { | ||
314 | + return false; | ||
315 | + } | ||
316 | + }).collect(Collectors.toList()); | ||
317 | + return entityViews; | ||
318 | + } catch (Exception e) { | ||
319 | + throw handleException(e); | ||
320 | + } | ||
321 | + } | ||
322 | + | ||
323 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
324 | + @RequestMapping(value = "/entityView/types", method = RequestMethod.GET) | ||
325 | + @ResponseBody | ||
326 | + public List<EntitySubtype> getEntityViewTypes() throws ThingsboardException { | ||
327 | + try { | ||
328 | + SecurityUser user = getCurrentUser(); | ||
329 | + TenantId tenantId = user.getTenantId(); | ||
330 | + ListenableFuture<List<EntitySubtype>> entityViewTypes = entityViewService.findEntityViewTypesByTenantId(tenantId); | ||
331 | + return checkNotNull(entityViewTypes.get()); | ||
332 | + } catch (Exception e) { | ||
333 | + throw handleException(e); | ||
334 | + } | ||
335 | + } | ||
336 | +} |
@@ -50,7 +50,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | @@ -50,7 +50,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
50 | import org.thingsboard.server.common.msg.TbMsg; | 50 | import org.thingsboard.server.common.msg.TbMsg; |
51 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 51 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
52 | import org.thingsboard.server.dao.event.EventService; | 52 | import org.thingsboard.server.dao.event.EventService; |
53 | -import org.thingsboard.server.service.script.JsSandboxService; | 53 | +import org.thingsboard.server.service.script.JsInvokeService; |
54 | import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; | 54 | import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; |
55 | 55 | ||
56 | import java.util.List; | 56 | import java.util.List; |
@@ -71,7 +71,7 @@ public class RuleChainController extends BaseController { | @@ -71,7 +71,7 @@ public class RuleChainController extends BaseController { | ||
71 | private EventService eventService; | 71 | private EventService eventService; |
72 | 72 | ||
73 | @Autowired | 73 | @Autowired |
74 | - private JsSandboxService jsSandboxService; | 74 | + private JsInvokeService jsInvokeService; |
75 | 75 | ||
76 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | 76 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
77 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) | 77 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) |
@@ -276,7 +276,7 @@ public class RuleChainController extends BaseController { | @@ -276,7 +276,7 @@ public class RuleChainController extends BaseController { | ||
276 | String errorText = ""; | 276 | String errorText = ""; |
277 | ScriptEngine engine = null; | 277 | ScriptEngine engine = null; |
278 | try { | 278 | try { |
279 | - engine = new RuleNodeJsScriptEngine(jsSandboxService, script, argNames); | 279 | + engine = new RuleNodeJsScriptEngine(jsInvokeService, getCurrentUser().getId(), script, argNames); |
280 | TbMsg inMsg = new TbMsg(UUIDs.timeBased(), msgType, null, new TbMsgMetaData(metadata), data, null, null, 0L); | 280 | TbMsg inMsg = new TbMsg(UUIDs.timeBased(), msgType, null, new TbMsgMetaData(metadata), data, null, null, 0L); |
281 | switch (scriptType) { | 281 | switch (scriptType) { |
282 | case "update": | 282 | case "update": |
@@ -49,9 +49,11 @@ import org.thingsboard.server.common.data.kv.Aggregation; | @@ -49,9 +49,11 @@ import org.thingsboard.server.common.data.kv.Aggregation; | ||
49 | import org.thingsboard.server.common.data.kv.AttributeKey; | 49 | import org.thingsboard.server.common.data.kv.AttributeKey; |
50 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 50 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
51 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 51 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
52 | +import org.thingsboard.server.common.data.kv.BaseDeleteTsKvQuery; | ||
52 | import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; | 53 | import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; |
53 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | 54 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
54 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; | 55 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
56 | +import org.thingsboard.server.common.data.kv.DeleteTsKvQuery; | ||
55 | import org.thingsboard.server.common.data.kv.DoubleDataEntry; | 57 | import org.thingsboard.server.common.data.kv.DoubleDataEntry; |
56 | import org.thingsboard.server.common.data.kv.KvEntry; | 58 | import org.thingsboard.server.common.data.kv.KvEntry; |
57 | import org.thingsboard.server.common.data.kv.LongDataEntry; | 59 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
@@ -59,14 +61,11 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; | @@ -59,14 +61,11 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; | ||
59 | import org.thingsboard.server.common.data.kv.StringDataEntry; | 61 | import org.thingsboard.server.common.data.kv.StringDataEntry; |
60 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 62 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
61 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | 63 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; |
62 | -import org.thingsboard.server.common.msg.core.TelemetryUploadRequest; | ||
63 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; | 64 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
64 | -import org.thingsboard.server.dao.attributes.AttributesService; | ||
65 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 65 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
66 | import org.thingsboard.server.service.security.AccessValidator; | 66 | import org.thingsboard.server.service.security.AccessValidator; |
67 | import org.thingsboard.server.service.security.model.SecurityUser; | 67 | import org.thingsboard.server.service.security.model.SecurityUser; |
68 | import org.thingsboard.server.service.telemetry.AttributeData; | 68 | import org.thingsboard.server.service.telemetry.AttributeData; |
69 | -import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | ||
70 | import org.thingsboard.server.service.telemetry.TsData; | 69 | import org.thingsboard.server.service.telemetry.TsData; |
71 | import org.thingsboard.server.service.telemetry.exception.InvalidParametersException; | 70 | import org.thingsboard.server.service.telemetry.exception.InvalidParametersException; |
72 | import org.thingsboard.server.service.telemetry.exception.UncheckedApiException; | 71 | import org.thingsboard.server.service.telemetry.exception.UncheckedApiException; |
@@ -94,15 +93,9 @@ import java.util.stream.Collectors; | @@ -94,15 +93,9 @@ import java.util.stream.Collectors; | ||
94 | public class TelemetryController extends BaseController { | 93 | public class TelemetryController extends BaseController { |
95 | 94 | ||
96 | @Autowired | 95 | @Autowired |
97 | - private AttributesService attributesService; | ||
98 | - | ||
99 | - @Autowired | ||
100 | private TimeseriesService tsService; | 96 | private TimeseriesService tsService; |
101 | 97 | ||
102 | @Autowired | 98 | @Autowired |
103 | - private TelemetrySubscriptionService tsSubService; | ||
104 | - | ||
105 | - @Autowired | ||
106 | private AccessValidator accessValidator; | 99 | private AccessValidator accessValidator; |
107 | 100 | ||
108 | private ExecutorService executor; | 101 | private ExecutorService executor; |
@@ -257,6 +250,60 @@ public class TelemetryController extends BaseController { | @@ -257,6 +250,60 @@ public class TelemetryController extends BaseController { | ||
257 | } | 250 | } |
258 | 251 | ||
259 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 252 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
253 | + @RequestMapping(value = "/{entityType}/{entityId}/timeseries/delete", method = RequestMethod.DELETE) | ||
254 | + @ResponseBody | ||
255 | + public DeferredResult<ResponseEntity> deleteEntityTimeseries(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | ||
256 | + @RequestParam(name = "keys") String keysStr, | ||
257 | + @RequestParam(name = "deleteAllDataForKeys", defaultValue = "false") boolean deleteAllDataForKeys, | ||
258 | + @RequestParam(name = "startTs", required = false) Long startTs, | ||
259 | + @RequestParam(name = "endTs", required = false) Long endTs, | ||
260 | + @RequestParam(name = "rewriteLatestIfDeleted", defaultValue = "false") boolean rewriteLatestIfDeleted) throws ThingsboardException { | ||
261 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
262 | + return deleteTimeseries(entityId, keysStr, deleteAllDataForKeys, startTs, endTs, rewriteLatestIfDeleted); | ||
263 | + } | ||
264 | + | ||
265 | + private DeferredResult<ResponseEntity> deleteTimeseries(EntityId entityIdStr, String keysStr, boolean deleteAllDataForKeys, | ||
266 | + Long startTs, Long endTs, boolean rewriteLatestIfDeleted) throws ThingsboardException { | ||
267 | + List<String> keys = toKeysList(keysStr); | ||
268 | + if (keys.isEmpty()) { | ||
269 | + return getImmediateDeferredResult("Empty keys: " + keysStr, HttpStatus.BAD_REQUEST); | ||
270 | + } | ||
271 | + SecurityUser user = getCurrentUser(); | ||
272 | + | ||
273 | + long deleteFromTs; | ||
274 | + long deleteToTs; | ||
275 | + if (deleteAllDataForKeys) { | ||
276 | + deleteFromTs = 0L; | ||
277 | + deleteToTs = System.currentTimeMillis(); | ||
278 | + } else { | ||
279 | + deleteFromTs = startTs; | ||
280 | + deleteToTs = endTs; | ||
281 | + } | ||
282 | + | ||
283 | + return accessValidator.validateEntityAndCallback(user, entityIdStr, (result, entityId) -> { | ||
284 | + List<DeleteTsKvQuery> deleteTsKvQueries = new ArrayList<>(); | ||
285 | + for (String key : keys) { | ||
286 | + deleteTsKvQueries.add(new BaseDeleteTsKvQuery(key, deleteFromTs, deleteToTs, rewriteLatestIfDeleted)); | ||
287 | + } | ||
288 | + | ||
289 | + ListenableFuture<List<Void>> future = tsService.remove(entityId, deleteTsKvQueries); | ||
290 | + Futures.addCallback(future, new FutureCallback<List<Void>>() { | ||
291 | + @Override | ||
292 | + public void onSuccess(@Nullable List<Void> tmp) { | ||
293 | + logTimeseriesDeleted(user, entityId, keys, null); | ||
294 | + result.setResult(new ResponseEntity<>(HttpStatus.OK)); | ||
295 | + } | ||
296 | + | ||
297 | + @Override | ||
298 | + public void onFailure(Throwable t) { | ||
299 | + logTimeseriesDeleted(user, entityId, keys, t); | ||
300 | + result.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); | ||
301 | + } | ||
302 | + }, executor); | ||
303 | + }); | ||
304 | + } | ||
305 | + | ||
306 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | ||
260 | @RequestMapping(value = "/{deviceId}/{scope}", method = RequestMethod.DELETE) | 307 | @RequestMapping(value = "/{deviceId}/{scope}", method = RequestMethod.DELETE) |
261 | @ResponseBody | 308 | @ResponseBody |
262 | public DeferredResult<ResponseEntity> deleteEntityAttributes(@PathVariable("deviceId") String deviceIdStr, | 309 | public DeferredResult<ResponseEntity> deleteEntityAttributes(@PathVariable("deviceId") String deviceIdStr, |
@@ -352,7 +399,7 @@ public class TelemetryController extends BaseController { | @@ -352,7 +399,7 @@ public class TelemetryController extends BaseController { | ||
352 | } | 399 | } |
353 | 400 | ||
354 | private DeferredResult<ResponseEntity> saveTelemetry(EntityId entityIdSrc, String requestBody, long ttl) throws ThingsboardException { | 401 | private DeferredResult<ResponseEntity> saveTelemetry(EntityId entityIdSrc, String requestBody, long ttl) throws ThingsboardException { |
355 | - TelemetryUploadRequest telemetryRequest; | 402 | + Map<Long, List<KvEntry>> telemetryRequest; |
356 | JsonElement telemetryJson; | 403 | JsonElement telemetryJson; |
357 | try { | 404 | try { |
358 | telemetryJson = new JsonParser().parse(requestBody); | 405 | telemetryJson = new JsonParser().parse(requestBody); |
@@ -360,12 +407,12 @@ public class TelemetryController extends BaseController { | @@ -360,12 +407,12 @@ public class TelemetryController extends BaseController { | ||
360 | return getImmediateDeferredResult("Unable to parse timeseries payload: Invalid JSON body!", HttpStatus.BAD_REQUEST); | 407 | return getImmediateDeferredResult("Unable to parse timeseries payload: Invalid JSON body!", HttpStatus.BAD_REQUEST); |
361 | } | 408 | } |
362 | try { | 409 | try { |
363 | - telemetryRequest = JsonConverter.convertToTelemetry(telemetryJson); | 410 | + telemetryRequest = JsonConverter.convertToTelemetry(telemetryJson, System.currentTimeMillis()); |
364 | } catch (Exception e) { | 411 | } catch (Exception e) { |
365 | return getImmediateDeferredResult("Unable to parse timeseries payload. Invalid JSON body: " + e.getMessage(), HttpStatus.BAD_REQUEST); | 412 | return getImmediateDeferredResult("Unable to parse timeseries payload. Invalid JSON body: " + e.getMessage(), HttpStatus.BAD_REQUEST); |
366 | } | 413 | } |
367 | List<TsKvEntry> entries = new ArrayList<>(); | 414 | List<TsKvEntry> entries = new ArrayList<>(); |
368 | - for (Map.Entry<Long, List<KvEntry>> entry : telemetryRequest.getData().entrySet()) { | 415 | + for (Map.Entry<Long, List<KvEntry>> entry : telemetryRequest.entrySet()) { |
369 | for (KvEntry kv : entry.getValue()) { | 416 | for (KvEntry kv : entry.getValue()) { |
370 | entries.add(new BasicTsKvEntry(entry.getKey(), kv)); | 417 | entries.add(new BasicTsKvEntry(entry.getKey(), kv)); |
371 | } | 418 | } |
@@ -513,6 +560,15 @@ public class TelemetryController extends BaseController { | @@ -513,6 +560,15 @@ public class TelemetryController extends BaseController { | ||
513 | }; | 560 | }; |
514 | } | 561 | } |
515 | 562 | ||
563 | + private void logTimeseriesDeleted(SecurityUser user, EntityId entityId, List<String> keys, Throwable e) { | ||
564 | + try { | ||
565 | + logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.TIMESERIES_DELETED, toException(e), | ||
566 | + keys); | ||
567 | + } catch (ThingsboardException te) { | ||
568 | + log.warn("Failed to log timeseries delete", te); | ||
569 | + } | ||
570 | + } | ||
571 | + | ||
516 | private void logAttributesDeleted(SecurityUser user, EntityId entityId, String scope, List<String> keys, Throwable e) { | 572 | private void logAttributesDeleted(SecurityUser user, EntityId entityId, String scope, List<String> keys, Throwable e) { |
517 | try { | 573 | try { |
518 | logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.ATTRIBUTES_DELETED, toException(e), | 574 | logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.ATTRIBUTES_DELETED, toException(e), |
@@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
32 | import org.thingsboard.server.common.data.id.TenantId; | 32 | import org.thingsboard.server.common.data.id.TenantId; |
33 | import org.thingsboard.server.common.data.page.TextPageData; | 33 | import org.thingsboard.server.common.data.page.TextPageData; |
34 | import org.thingsboard.server.common.data.page.TextPageLink; | 34 | import org.thingsboard.server.common.data.page.TextPageLink; |
35 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
35 | import org.thingsboard.server.dao.tenant.TenantService; | 36 | import org.thingsboard.server.dao.tenant.TenantService; |
36 | import org.thingsboard.server.service.install.InstallScripts; | 37 | import org.thingsboard.server.service.install.InstallScripts; |
37 | 38 | ||
@@ -84,6 +85,8 @@ public class TenantController extends BaseController { | @@ -84,6 +85,8 @@ public class TenantController extends BaseController { | ||
84 | try { | 85 | try { |
85 | TenantId tenantId = new TenantId(toUUID(strTenantId)); | 86 | TenantId tenantId = new TenantId(toUUID(strTenantId)); |
86 | tenantService.deleteTenant(tenantId); | 87 | tenantService.deleteTenant(tenantId); |
88 | + | ||
89 | + actorService.onEntityStateChange(tenantId, tenantId, ComponentLifecycleEvent.DELETED); | ||
87 | } catch (Exception e) { | 90 | } catch (Exception e) { |
88 | throw handleException(e); | 91 | throw handleException(e); |
89 | } | 92 | } |
@@ -24,9 +24,10 @@ import org.springframework.context.annotation.Profile; | @@ -24,9 +24,10 @@ import org.springframework.context.annotation.Profile; | ||
24 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
25 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 25 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
26 | import org.thingsboard.server.service.install.DataUpdateService; | 26 | import org.thingsboard.server.service.install.DataUpdateService; |
27 | -import org.thingsboard.server.service.install.DatabaseSchemaService; | ||
28 | import org.thingsboard.server.service.install.DatabaseUpgradeService; | 27 | import org.thingsboard.server.service.install.DatabaseUpgradeService; |
28 | +import org.thingsboard.server.service.install.EntityDatabaseSchemaService; | ||
29 | import org.thingsboard.server.service.install.SystemDataLoaderService; | 29 | import org.thingsboard.server.service.install.SystemDataLoaderService; |
30 | +import org.thingsboard.server.service.install.TsDatabaseSchemaService; | ||
30 | 31 | ||
31 | @Service | 32 | @Service |
32 | @Profile("install") | 33 | @Profile("install") |
@@ -43,7 +44,10 @@ public class ThingsboardInstallService { | @@ -43,7 +44,10 @@ public class ThingsboardInstallService { | ||
43 | private Boolean loadDemo; | 44 | private Boolean loadDemo; |
44 | 45 | ||
45 | @Autowired | 46 | @Autowired |
46 | - private DatabaseSchemaService databaseSchemaService; | 47 | + private EntityDatabaseSchemaService entityDatabaseSchemaService; |
48 | + | ||
49 | + @Autowired | ||
50 | + private TsDatabaseSchemaService tsDatabaseSchemaService; | ||
47 | 51 | ||
48 | @Autowired | 52 | @Autowired |
49 | private DatabaseUpgradeService databaseUpgradeService; | 53 | private DatabaseUpgradeService databaseUpgradeService; |
@@ -88,6 +92,20 @@ public class ThingsboardInstallService { | @@ -88,6 +92,20 @@ public class ThingsboardInstallService { | ||
88 | 92 | ||
89 | dataUpdateService.updateData("1.4.0"); | 93 | dataUpdateService.updateData("1.4.0"); |
90 | 94 | ||
95 | + case "2.0.0": | ||
96 | + log.info("Upgrading ThingsBoard from version 2.0.0 to 2.1.1 ..."); | ||
97 | + | ||
98 | + databaseUpgradeService.upgradeDatabase("2.0.0"); | ||
99 | + | ||
100 | + case "2.1.1": | ||
101 | + log.info("Upgrading ThingsBoard from version 2.1.1 to 2.1.2 ..."); | ||
102 | + | ||
103 | + databaseUpgradeService.upgradeDatabase("2.1.1"); | ||
104 | + case "2.1.3": | ||
105 | + log.info("Upgrading ThingsBoard from version 2.1.3 to 2.2.0 ..."); | ||
106 | + | ||
107 | + databaseUpgradeService.upgradeDatabase("2.1.3"); | ||
108 | + | ||
91 | log.info("Updating system data..."); | 109 | log.info("Updating system data..."); |
92 | 110 | ||
93 | systemDataLoaderService.deleteSystemWidgetBundle("charts"); | 111 | systemDataLoaderService.deleteSystemWidgetBundle("charts"); |
@@ -114,9 +132,13 @@ public class ThingsboardInstallService { | @@ -114,9 +132,13 @@ public class ThingsboardInstallService { | ||
114 | 132 | ||
115 | log.info("Starting ThingsBoard Installation..."); | 133 | log.info("Starting ThingsBoard Installation..."); |
116 | 134 | ||
117 | - log.info("Installing DataBase schema..."); | 135 | + log.info("Installing DataBase schema for entities..."); |
136 | + | ||
137 | + entityDatabaseSchemaService.createDatabaseSchema(); | ||
138 | + | ||
139 | + log.info("Installing DataBase schema for timeseries..."); | ||
118 | 140 | ||
119 | - databaseSchemaService.createDatabaseSchema(); | 141 | + tsDatabaseSchemaService.createDatabaseSchema(); |
120 | 142 | ||
121 | log.info("Loading system data..."); | 143 | log.info("Loading system data..."); |
122 | 144 |
@@ -19,7 +19,8 @@ import lombok.extern.slf4j.Slf4j; | @@ -19,7 +19,8 @@ import lombok.extern.slf4j.Slf4j; | ||
19 | import org.springframework.beans.factory.annotation.Value; | 19 | import org.springframework.beans.factory.annotation.Value; |
20 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
21 | import org.springframework.util.Assert; | 21 | import org.springframework.util.Assert; |
22 | -import org.thingsboard.server.gen.discovery.ServerInstanceProtos; | 22 | +import org.thingsboard.server.common.msg.cluster.ServerAddress; |
23 | +import org.thingsboard.server.common.msg.cluster.ServerType; | ||
23 | 24 | ||
24 | import javax.annotation.PostConstruct; | 25 | import javax.annotation.PostConstruct; |
25 | 26 | ||
@@ -43,8 +44,7 @@ public class CurrentServerInstanceService implements ServerInstanceService { | @@ -43,8 +44,7 @@ public class CurrentServerInstanceService implements ServerInstanceService { | ||
43 | public void init() { | 44 | public void init() { |
44 | Assert.hasLength(rpcHost, missingProperty("rpc.bind_host")); | 45 | Assert.hasLength(rpcHost, missingProperty("rpc.bind_host")); |
45 | Assert.notNull(rpcPort, missingProperty("rpc.bind_port")); | 46 | Assert.notNull(rpcPort, missingProperty("rpc.bind_port")); |
46 | - | ||
47 | - self = new ServerInstance(ServerInstanceProtos.ServerInfo.newBuilder().setHost(rpcHost).setPort(rpcPort).setTs(System.currentTimeMillis()).build()); | 47 | + self = new ServerInstance(new ServerAddress(rpcHost, rpcPort, ServerType.CORE)); |
48 | log.info("Current server instance: [{};{}]", self.getHost(), self.getPort()); | 48 | log.info("Current server instance: [{};{}]", self.getHost(), self.getPort()); |
49 | } | 49 | } |
50 | 50 |
@@ -30,8 +30,4 @@ public interface DiscoveryService { | @@ -30,8 +30,4 @@ public interface DiscoveryService { | ||
30 | 30 | ||
31 | List<ServerInstance> getOtherServers(); | 31 | List<ServerInstance> getOtherServers(); |
32 | 32 | ||
33 | - boolean addListener(DiscoveryServiceListener listener); | ||
34 | - | ||
35 | - boolean removeListener(DiscoveryServiceListener listener); | ||
36 | - | ||
37 | } | 33 | } |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.service.cluster.discovery; | 16 | package org.thingsboard.server.service.cluster.discovery; |
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | +import org.apache.commons.lang3.RandomStringUtils; | ||
19 | import org.springframework.beans.factory.annotation.Autowired; | 20 | import org.springframework.beans.factory.annotation.Autowired; |
20 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
21 | import org.springframework.context.annotation.DependsOn; | 22 | import org.springframework.context.annotation.DependsOn; |
@@ -62,13 +63,5 @@ public class DummyDiscoveryService implements DiscoveryService { | @@ -62,13 +63,5 @@ public class DummyDiscoveryService implements DiscoveryService { | ||
62 | return Collections.emptyList(); | 63 | return Collections.emptyList(); |
63 | } | 64 | } |
64 | 65 | ||
65 | - @Override | ||
66 | - public boolean addListener(DiscoveryServiceListener listener) { | ||
67 | - return false; | ||
68 | - } | ||
69 | 66 | ||
70 | - @Override | ||
71 | - public boolean removeListener(DiscoveryServiceListener listener) { | ||
72 | - return false; | ||
73 | - } | ||
74 | } | 67 | } |
@@ -19,7 +19,6 @@ import lombok.EqualsAndHashCode; | @@ -19,7 +19,6 @@ import lombok.EqualsAndHashCode; | ||
19 | import lombok.Getter; | 19 | import lombok.Getter; |
20 | import lombok.ToString; | 20 | import lombok.ToString; |
21 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 21 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
22 | -import org.thingsboard.server.gen.discovery.ServerInstanceProtos; | ||
23 | 22 | ||
24 | /** | 23 | /** |
25 | * @author Andrew Shvayka | 24 | * @author Andrew Shvayka |
@@ -41,12 +40,6 @@ public final class ServerInstance implements Comparable<ServerInstance> { | @@ -41,12 +40,6 @@ public final class ServerInstance implements Comparable<ServerInstance> { | ||
41 | this.port = serverAddress.getPort(); | 40 | this.port = serverAddress.getPort(); |
42 | } | 41 | } |
43 | 42 | ||
44 | - public ServerInstance(ServerInstanceProtos.ServerInfo serverInfo) { | ||
45 | - this.host = serverInfo.getHost(); | ||
46 | - this.port = serverInfo.getPort(); | ||
47 | - this.serverAddress = new ServerAddress(host, port); | ||
48 | - } | ||
49 | - | ||
50 | @Override | 43 | @Override |
51 | public int compareTo(ServerInstance o) { | 44 | public int compareTo(ServerInstance o) { |
52 | return this.serverAddress.compareTo(o.serverAddress); | 45 | return this.serverAddress.compareTo(o.serverAddress); |