소스 검색

Merge branch 'master' of http://114.215.146.132:3000/Mqy/Wisdom-Data into mqy20260511

mqy20260511
lenovo 2 주 전
부모
커밋
510d67a89e

+ 62
- 4
deploy/README.md 파일 보기

@@ -31,9 +31,9 @@
31 31
 
32 32
 ## 容器架构
33 33
 
34
-| 容器 | 网络模式 | 端口映射 | 数据持久化 |
35
-|------|---------|---------|-----------|
36
-| `tdengine-operator` | host | 6031, 6041 | `/mnt/tdengine-operator/data` |
34
+| 容器 | 网络模式 | 端口 | 数据持久化 |
35
+|------|---------|------|-----------|
36
+| `tdengine-operator` | host | 6031 (taosd), 6041 (taosadapter) | `/mnt/tdengine-operator/data` |
37 37
 | `taos-explorer` | bridge | `127.0.0.1:6060->6060` | `/mnt/taos-explorer-data` |
38 38
 | `iot-platform` | bridge | `0.0.0.0:8887->8887` | `/mnt/iot-platform/logs` |
39 39
 
@@ -183,6 +183,62 @@ podman run -d \
183 183
     localhost/iot-platform:latest
184 184
 ```
185 185
 
186
+## TDengine 容器管理
187
+
188
+```bash
189
+# 查看所有 TDengine 相关容器
190
+podman ps | grep -E 'tdengine|taos'
191
+
192
+# 重启 tdengine-operator(taosd + taosadapter)
193
+podman restart tdengine-operator
194
+
195
+# 重启 taos-explorer
196
+podman restart taos-explorer
197
+
198
+# 查看 tdengine-operator 日志
199
+podman logs -f tdengine-operator
200
+
201
+# 查看 taos-explorer 日志
202
+podman logs -f taos-explorer
203
+
204
+# 验证 taosadapter REST API
205
+curl -s -u root:taosdata http://127.0.0.1:6041/rest/sql -X POST -d "SHOW DATABASES"
206
+```
207
+
208
+### 启动脚本位置
209
+
210
+| 脚本 | 用途 |
211
+|------|------|
212
+| `scripts/start-tdengine-operator.sh` | 启动 tdengine-operator(host 网络,taosd + taosadapter) |
213
+| `scripts/start-taos-explorer.sh` | 启动 taos-explorer(bridge 网络,REST API) |
214
+
215
+## 架构说明
216
+
217
+```
218
+┌─────────────────────────────────────────────┐
219
+│                    宿主机                     │
220
+│  ┌─────────────┐      ┌─────────────────┐   │
221
+│  │ nginx :6060 │─────▶│ taos-explorer   │   │
222
+│  └─────────────┘      │ (REST API)      │   │
223
+│                       └────────┬────────┘   │
224
+│                                │            │
225
+│  ┌─────────────────────────────┼────────┐   │
226
+│  │         iot-platform        │        │   │
227
+│  │         (bridge)            │        │   │
228
+│  └─────────────────────────────┘        │   │
229
+│                                         │   │
230
+│  ┌──────────────────────────────────────┘   │
231
+│  │  tdengine-operator (host网络)            │
232
+│  │  taosd :6031  +  taosadapter :6041       │
233
+│  └──────────────────────────────────────────┘
234
+└─────────────────────────────────────────────┘
235
+```
236
+
237
+- `tdengine-operator` 使用 **host 网络**,内部同时运行 `taosd`(6031)和 `taosadapter`(6041)
238
+- `taos-explorer` 通过 `host.containers.internal:6041` 使用 **REST API** 连接
239
+- `iot-platform` 通过 `host.containers.internal:6031` 使用 **native 协议** 连接
240
+- `taosadapter` 配置通过覆盖镜像 `entrypoint.sh` 读取 `/etc/taos/taosadapter.toml`
241
+
186 242
 ## 配置文件说明
187 243
 
188 244
 | 文件 | 说明 |
@@ -194,5 +250,7 @@ podman run -d \
194 250
 | `start-container.sh` | 容器内启动脚本(加载 .env) |
195 251
 | `iot-platform.service` | systemd 服务定义(已废弃,保留备用) |
196 252
 | `config/taos.cfg` | TDengine 服务端配置 |
197
-| `config/explorer.toml` | taos-explorer 配置 |
253
+| `config/entrypoint.sh` | 覆盖容器默认 entrypoint,使 taosadapter 读取配置文件 |
254
+| `config/explorer.toml` | taos-explorer 配置(REST API) |
255
+| `config/taosadapter.toml` | taosadapter 配置(禁用未使用插件) |
198 256
 | `config/tdengine-explorer.conf` | nginx 代理配置 |

+ 164
- 0
deploy/config/entrypoint.sh 파일 보기

@@ -0,0 +1,164 @@
1
+#!/bin/bash
2
+set -ex
3
+# for TZ awareness
4
+if [ "$TZ" != "" ]; then
5
+    ln -sf /usr/share/zoneinfo/$TZ /etc/localtime
6
+    echo $TZ >/etc/timezone
7
+fi
8
+
9
+TAOS_ROOT_PASSWORD=${TAOS_ROOT_PASSWORD:-taosdata}
10
+export TAOS_KEEPER_TDENGINE_PASSWORD=${TAOS_ROOT_PASSWORD}
11
+
12
+INITDB_DIR=/docker-entrypoint-initdb.d/
13
+
14
+# option to disable taosadapter, default is no
15
+DISABLE_ADAPTER=${TAOS_DISABLE_ADAPTER:-0}
16
+unset TAOS_DISABLE_ADAPTER
17
+
18
+DISABLE_KEEPER=${TAOS_DISABLE_KEEPER:-0}
19
+unset TAOS_DISABLE_KEEPER
20
+
21
+DISABLE_EXPLORER=${TAOS_DISABLE_EXPLORER:-0}
22
+unset TAOS_DISABLE_EXPLORER
23
+
24
+# Get DATA_DIR from taosd -C
25
+DATA_DIR=$(taosd -C|grep -E 'dataDir\s+(\S+)' -o |head -n1|sed 's/dataDir *//')
26
+DATA_DIR=${DATA_DIR:-/var/lib/taos}
27
+
28
+# Get FQDN from taosd -C
29
+FQDN=$(taosd -C|grep -E 'fqdn\s+(\S+)' -o |head -n1|sed 's/fqdn *//')
30
+# ensure the fqdn is resolved as localhost
31
+grep "$FQDN" /etc/hosts >/dev/null || echo "127.0.0.1 $FQDN" >>/etc/hosts
32
+
33
+# Get first ep from taosd -C
34
+FIRSET_EP=$(taosd -C|grep -E 'firstEp\s+(\S+)' -o |head -n1|sed 's/firstEp *//')
35
+# parse first ep host and port
36
+FIRST_EP_HOST=${FIRSET_EP%:*}
37
+FIRST_EP_PORT=${FIRSET_EP#*:}
38
+
39
+# in case of custom server port
40
+SERVER_PORT=$(taosd -C|grep -E 'serverPort\s+(\S+)' -o |head -n1|sed 's/serverPort *//')
41
+SERVER_PORT=${SERVER_PORT:-6030}
42
+
43
+set +e
44
+ulimit -c unlimited
45
+# set core files pattern, maybe failed
46
+sysctl -w kernel.core_pattern=/corefile/core-$FQDN-%e-%p >/dev/null >&1
47
+set -e
48
+
49
+if [ $# -gt 0 ]; then
50
+    exec $@
51
+    exit 0
52
+fi
53
+
54
+NEEDS_INITDB=0
55
+
56
+# if dnode has been created or has mnode ep set or the host is first ep or not for cluster, just start.
57
+if [ -f "$DATA_DIR/dnode/dnode.json" ] ||
58
+    [ -f "$DATA_DIR/dnode/mnodeEpSet.json" ] ||
59
+    [ "$FQDN" = "$FIRST_EP_HOST" ]; then
60
+    echo "start taosd with mnode ep set"
61
+    taosd &
62
+    while true; do
63
+        es=$(taos -h $FIRST_EP_HOST -P $FIRST_EP_PORT --check | grep "^[0-9]*:")
64
+        echo ${es}
65
+        if [ "${es%%:*}" -eq 2 ]; then
66
+
67
+            # Initialization scripts should only work in first node.
68
+            if [ "$FQDN" = "$FIRST_EP_HOST" ]; then
69
+                if [ ! -f "${DATA_DIR}/.docker-entrypoint-root-password-changed" ]; then
70
+                    if [ "$TAOS_ROOT_PASSWORD" != "taosdata" ]; then
71
+                        # change default root password
72
+                        taos -s "ALTER USER root PASS '$TAOS_ROOT_PASSWORD'"
73
+                        touch "${DATA_DIR}/.docker-entrypoint-root-password-changed"
74
+                    fi
75
+                fi
76
+                # Initialization scripts should only work in first node.
77
+                if [ ! -f "${DATA_DIR}/.docker-entrypoint-inited" ]; then
78
+                    NEEDS_INITDB=1
79
+                fi
80
+            fi
81
+
82
+            break
83
+        fi
84
+        sleep 1s
85
+    done
86
+# others will first wait the first ep ready.
87
+else
88
+    if [ "$TAOS_FIRST_EP" = "" ]; then
89
+        echo "run TDengine with single node."
90
+        taosd &
91
+    fi
92
+    while true; do
93
+        es=$(taos -h $FIRST_EP_HOST -P $FIRST_EP_PORT --check | grep "^[0-9]*:")
94
+        echo ${es}
95
+        if [ "${es%%:*}" -eq 2 ]; then
96
+            echo "execute create dnode"
97
+            sh -c "taos -p'$TAOS_ROOT_PASSWORD' -h $FIRST_EP_HOST -P $FIRST_EP_PORT -s 'create dnode \"$FQDN:$SERVER_PORT\";'"
98
+            break
99
+        fi
100
+        sleep 1s
101
+    done
102
+    if ps aux | grep -v grep | grep taosd > dev/null; then
103
+        echo "TDengine is running"
104
+      else
105
+        taosd &
106
+    fi
107
+fi
108
+
109
+if [ "$DISABLE_ADAPTER" = "0" ]; then
110
+    which taosadapter >/dev/null && taosadapter -c /etc/taos/taosadapter.toml &
111
+    # wait for 6041 port ready
112
+    for _ in $(seq 1 20); do
113
+        nc -z localhost 6041 && break
114
+        sleep 0.5
115
+    done
116
+fi
117
+
118
+if [ "$DISABLE_KEEPER" = "0" ]; then
119
+    sleep 3
120
+    which taoskeeper >/dev/null && taoskeeper &
121
+    # wait for 6043 port ready
122
+    for _ in $(seq 1 20); do
123
+        nc -z localhost 6043 && break
124
+        sleep 0.5
125
+    done
126
+fi
127
+
128
+if [ "$DISABLE_EXPLORER" = "0" ]; then
129
+    which taos-explorer >/dev/null && taos-explorer &
130
+    # wait for 6060 port ready
131
+    for _ in $(seq 1 20); do
132
+        nc -z localhost 6060 && break
133
+        sleep 0.5
134
+    done
135
+fi
136
+
137
+if [ "$NEEDS_INITDB" = "1" ]; then
138
+    # check if initdb.d exists
139
+    if [ -d "${INITDB_DIR}" ]; then
140
+        # execute initdb scripts in sql
141
+        for FILE in "$INITDB_DIR"*.sql; do
142
+            echo "Initialize db with file $FILE"
143
+            MAX_RETRIES=5
144
+            RETRY_COUNT=0
145
+            SUCCESS=0
146
+            while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ "$SUCCESS" = "0" ]; do
147
+                set -x
148
+                OUTPUT=$(sh -c "taos -f $FILE -p'$TAOS_ROOT_PASSWORD'")
149
+                set +x
150
+                echo $OUTPUT
151
+                if [[ "$OUTPUT" =~ "DB error" ]]; then
152
+                    echo "Retrying in 2 seconds..."
153
+                    sleep 2
154
+                else
155
+                    SUCCESS=1
156
+                fi
157
+            done
158
+        done
159
+    fi
160
+
161
+    touch "${DATA_DIR}/.docker-entrypoint-inited"
162
+fi
163
+
164
+while true; do sleep 1000; done

+ 8
- 6
deploy/config/explorer.toml 파일 보기

@@ -32,17 +32,19 @@ log_level = "info"
32 32
 
33 33
 # REST API endpoint to connect to the cluster.
34 34
 # This configuration is also the target for data migration tasks.
35
-# 
35
+#
36 36
 # Default is "http://localhost:6041" - the default endpoint for REST API.
37
+# Note: taos-explorer requires REST API for registration/login.
38
+# Use host.containers.internal for bridge network containers to reach host network services.
37 39
 #
38
-cluster = "http://172.21.185.173:6041"
40
+cluster = "http://host.containers.internal:6041"
39 41
 
40 42
 # native endpoint to connect to the cluster.
41
-# Default is disabled. To enable it, set it to the native API URL like "taos://localhost:6030" and uncomment it.
42
-# If you enable it, you will get more performance for data migration tasks.
43
-# If modify this config item, you must relogin to clear the cache in browser local storage.
43
+# Default is disabled. Native connection from bridge network to host network
44
+# does not work due to TDengine FQDN reconnection mechanism (epset contains 127.0.0.1).
45
+# Keep disabled; REST API is sufficient.
44 46
 #
45
-# cluster_native = "taos://localhost:6030"
47
+# cluster_native = "taos://host.containers.internal:6031"
46 48
 
47 49
 # API endpoint for data replication/backup/data sources. No default option.
48 50
 #   Set it to API URL like "http://localhost:6050".

+ 40
- 0
deploy/config/taosadapter.toml 파일 보기

@@ -0,0 +1,40 @@
1
+# taosAdapter configuration (runs inside tdengine-operator container)
2
+# Mounted to /etc/taos/taosadapter.toml
3
+
4
+debug = false
5
+port = 6041
6
+logLevel = "info"
7
+
8
+[cors]
9
+allowAllOrigins = true
10
+
11
+[log]
12
+rotationCount = 30
13
+rotationTime = "24h"
14
+rotationSize = "1GB"
15
+
16
+# Disable keeper upload (keeper is not running)
17
+[uploadKeeper]
18
+enable = false
19
+
20
+# Disable unused plugins
21
+[opentsdb]
22
+enable = false
23
+
24
+[influxdb]
25
+enable = false
26
+
27
+[statsd]
28
+enable = false
29
+
30
+[collectd]
31
+enable = false
32
+
33
+[opentsdb_telnet]
34
+enable = false
35
+
36
+[node_exporter]
37
+enable = false
38
+
39
+[prometheus]
40
+enable = false

+ 37
- 0
deploy/scripts/start-taos-explorer.sh 파일 보기

@@ -0,0 +1,37 @@
1
+#!/bin/bash
2
+# Start taos-explorer container
3
+# Uses REST API (taosAdapter) via host.containers.internal
4
+# TDengine native connection from bridge network does not work due to FQDN mechanism
5
+#
6
+# Data mount note: TDengine image defines VOLUME /var/lib/taos which creates
7
+# an anonymous volume that overrides child bind mounts. We mount the parent
8
+# directory here; actual explorer data lives in DATA_DIR/explorer/ subdirectory.
9
+
10
+set -e
11
+
12
+CONTAINER_NAME="taos-explorer"
13
+IMAGE="docker.io/tdengine/tdengine:3.3.6.13"
14
+DATA_DIR="/mnt/taos-explorer-data"
15
+CFG_FILE="/mnt/iot-platform/config/explorer.toml"
16
+REGISTER_FILE="/mnt/iot-platform/config/explorer-register.cfg"
17
+
18
+echo "Starting ${CONTAINER_NAME}..."
19
+
20
+# Stop and remove existing container if present
21
+podman rm -f "${CONTAINER_NAME}" 2>/dev/null || true
22
+
23
+podman run -d \
24
+    --name "${CONTAINER_NAME}" \
25
+    --network bridge \
26
+    --restart unless-stopped \
27
+    -p 127.0.0.1:6060:6060 \
28
+    -v "${DATA_DIR}:/var/lib/taos" \
29
+    -v "${CFG_FILE}:/etc/taos/explorer.toml:ro" \
30
+    -v "${REGISTER_FILE}:/etc/taos/explorer-register.cfg" \
31
+    -e EXPLORER_SKIP_REGISTER=true \
32
+    "${IMAGE}" \
33
+    taos-explorer
34
+
35
+echo "${CONTAINER_NAME} started."
36
+echo "Port: 127.0.0.1:6060 (nginx proxy)"
37
+echo "Connection: REST API via host.containers.internal:6041"

+ 39
- 0
deploy/scripts/start-tdengine-operator.sh 파일 보기

@@ -0,0 +1,39 @@
1
+#!/bin/bash
2
+# Start tdengine-operator container (taosd + taosadapter)
3
+# Data directory: /mnt/tdengine-operator/data
4
+# Network: host (required for TDengine FQDN mechanism)
5
+# taosadapter runs inside this container, listening on host port 6041
6
+# taoskeeper and taos-explorer are disabled (deployed separately)
7
+# Note: entrypoint.sh is overridden to add `-c /etc/taos/taosadapter.toml`
8
+#       because the upstream image starts taosadapter without config flag.
9
+
10
+set -e
11
+
12
+CONTAINER_NAME="tdengine-operator"
13
+IMAGE="docker.io/tdengine/tdengine:3.3.6.13"
14
+DATA_DIR="/mnt/tdengine-operator/data"
15
+LOG_DIR="/mnt/tdengine-operator/log"
16
+CFG_FILE="/mnt/tdengine-operator/taos.cfg"
17
+ADAPTER_CFG="/mnt/iot-platform/config/taosadapter.toml"
18
+ENTRYPOINT_FILE="/mnt/iot-platform/config/entrypoint.sh"
19
+
20
+echo "Starting ${CONTAINER_NAME}..."
21
+
22
+# Stop and remove existing container if present
23
+podman rm -f "${CONTAINER_NAME}" 2>/dev/null || true
24
+
25
+podman run -d \
26
+    --name "${CONTAINER_NAME}" \
27
+    --network host \
28
+    --restart unless-stopped \
29
+    -e TAOS_DISABLE_KEEPER=1 \
30
+    -e TAOS_DISABLE_EXPLORER=1 \
31
+    -v "${DATA_DIR}:/var/lib/taos" \
32
+    -v "${LOG_DIR}:/var/log/taos" \
33
+    -v "${CFG_FILE}:/etc/taos/taos.cfg:ro" \
34
+    -v "${ADAPTER_CFG}:/etc/taos/taosadapter.toml:ro" \
35
+    -v "${ENTRYPOINT_FILE}:/usr/bin/entrypoint.sh:ro" \
36
+    "${IMAGE}"
37
+
38
+echo "${CONTAINER_NAME} started."
39
+echo "Ports: 6031 (taosd native), 6041 (taosadapter REST API)"

+ 1
- 1
iot-platform/src/main/java/com/iot/platform/config/IotProperties.java 파일 보기

@@ -115,7 +115,7 @@ public class IotProperties {
115 115
      * TDengine配置
116 116
      */
117 117
     public static class TDengine {
118
-        private String url = "jdbc:TAOS://172.21.185.173:6031/";
118
+        private String url = "jdbc:TAOS://host.containers.internal:6031/";
119 119
         private String username = "";
120 120
         private String password = "";
121 121
 

+ 2
- 1
iot-platform/src/main/java/com/iot/platform/mqtt/MqttChargeStationConsumer.java 파일 보기

@@ -70,7 +70,8 @@ public class MqttChargeStationConsumer extends AbstractDynamicMqttConsumer {
70 70
         }
71 71
 
72 72
         String dbName = topicParts[1];
73
-        String dbNamePrefix = "pe_iot_"+dbName.substring(0, 2);
73
+        String dbPrefix = dbName.length() >= 2 ? dbName.substring(0, 2) : dbName;
74
+        String dbNamePrefix = "pe_iot_" + dbPrefix;
74 75
         //先传输为deviceid,到后面进行优化
75 76
         String superTable = topicParts[3];
76 77
 //        String tableName = superTable + "_" + date.getYear() + String.format("%02d", date.getMonthValue());

+ 2
- 1
iot-platform/src/main/java/com/iot/platform/mqtt/MqttDynamicConsumer.java 파일 보기

@@ -105,7 +105,8 @@ public class MqttDynamicConsumer extends AbstractDynamicMqttConsumer {
105 105
         data.put("device_id", ctx.deviceId);
106 106
         List<Map<String, Object>> batch = Collections.singletonList(data);
107 107
 
108
-        String dbNamePrefix = "pe_iot_"+ctx.controllerId.substring(0, 2);
108
+        String controllerPrefix = ctx.controllerId.length() >= 2 ? ctx.controllerId.substring(0, 2) : ctx.controllerId;
109
+        String dbNamePrefix = "pe_iot_" + controllerPrefix;
109 110
         String controllerId = ctx.controllerId;
110 111
         tdengineService.insertBatch(dbNamePrefix, ctx.deviceId, controllerId, batch);
111 112
     }

+ 12
- 6
iot-platform/src/main/java/com/iot/platform/task/VehicleSyncTask.java 파일 보기

@@ -77,15 +77,21 @@ public class VehicleSyncTask {
77 77
                 }
78 78
 
79 79
                 // redisKey 格式: pe_iot_<controllerId>_<deviceId>
80
-                // 从右往左取,避免 id 本身含下划线的问题
81
-                String[] parts = redisKey.split("_");
82
-                if (parts.length < 3) {
80
+                String prefix = "pe_iot_";
81
+                if (!redisKey.startsWith(prefix) || redisKey.length() <= prefix.length()) {
83 82
                     log.warn("跳过非法 redis key: {}", redisKey);
84 83
                     continue;
85 84
                 }
86
-                String controllerId = parts[parts.length - 2];
87
-                String deviceId = parts[parts.length - 1];
88
-                String tableName = "pe_iot_" + controllerId.substring(0, 2);
85
+                String remainder = redisKey.substring(prefix.length());
86
+                int lastUnderscore = remainder.lastIndexOf('_');
87
+                if (lastUnderscore <= 0 || lastUnderscore == remainder.length() - 1) {
88
+                    log.warn("跳过非法 redis key: {}", redisKey);
89
+                    continue;
90
+                }
91
+                String controllerId = remainder.substring(0, lastUnderscore);
92
+                String deviceId = remainder.substring(lastUnderscore + 1);
93
+                String dbPrefix = controllerId.length() >= 2 ? controllerId.substring(0, 2) : controllerId;
94
+                String tableName = "pe_iot_" + dbPrefix;
89 95
 
90 96
                 try {
91 97
                     sysrealtimeService.createRealtime(tableName);

+ 1
- 1
iot-platform/src/main/resources/application.yml 파일 보기

@@ -70,6 +70,6 @@ iot:
70 70
     password: ${MQTT_PASSWORD:}
71 71
     charge-station-topic: ${MQTT_CHARGE_STATION_TOPIC:station/ChargeStation/device/+/post/json}
72 72
   tdengine:
73
-    url: jdbc:TAOS://172.21.185.173:6031/
73
+    url: jdbc:TAOS://host.containers.internal:6031/
74 74
     username: ${TDENGINE_USERNAME:}
75 75
     password: ${TDENGINE_PASSWORD:}

+ 3
- 8
iot-platform/src/test/java/com/iot/platform/mqtt/MqttChargeStationConsumerTest.java 파일 보기

@@ -96,12 +96,9 @@ class MqttChargeStationConsumerTest {
96 96
         List<Map<String, Object>> dataList = Collections.singletonList(data1);
97 97
         String topic = "prefix/myDb/suffix/mySuperTable/extra";
98 98
 
99
-        LocalDate now = LocalDate.now();
100
-        String expectedTable = "mySuperTable_" + now.getYear() + String.format("%02d", now.getMonthValue());
101
-
102 99
         method.invoke(consumer, dataList, topic);
103 100
 
104
-        verify(tdengineService).insertBatch(eq("myDb"), "mySuperTable_",eq(expectedTable), anyList());
101
+        verify(tdengineService).insertBatch(eq("pe_iot_my"), eq("mySuperTable"), eq("myDb"), anyList());
105 102
     }
106 103
 
107 104
     @Test
@@ -113,7 +110,7 @@ class MqttChargeStationConsumerTest {
113 110
 
114 111
         method.invoke(consumer, Collections.emptyList(), "prefix/db/suffix/table/extra");
115 112
 
116
-        verify(tdengineService, never()).insertBatch(anyString(), "mySuperTable_",anyString(), anyList());
113
+        verify(tdengineService, never()).insertBatch(anyString(), anyString(), anyString(), anyList());
117 114
     }
118 115
 
119 116
     @Test
@@ -146,11 +143,9 @@ class MqttChargeStationConsumerTest {
146 143
         dataList.add(valid);
147 144
 
148 145
         String topic = "prefix/myDb/suffix/mySuperTable/extra";
149
-        LocalDate now = LocalDate.now();
150
-        String expectedTable = "mySuperTable_" + now.getYear() + String.format("%02d", now.getMonthValue());
151 146
 
152 147
         method.invoke(consumer, dataList, topic);
153 148
 
154
-        verify(tdengineService).insertBatch(eq("myDb"), "mySuperTable_",eq(expectedTable), argThat(list -> list.size() == 1));
149
+        verify(tdengineService).insertBatch(eq("pe_iot_my"), eq("mySuperTable"), eq("myDb"), argThat(list -> list.size() == 1));
155 150
     }
156 151
 }

+ 6
- 6
iot-platform/src/test/java/com/iot/platform/service/SysRealtimeServiceTest.java 파일 보기

@@ -54,7 +54,7 @@ class SysRealtimeServiceTest {
54 54
     @Test
55 55
     @DisplayName("insertTables: 非法表名应抛出异常且不调用 mapper")
56 56
     void inserttables_invalidTableName_throwsWithoutCallingMapper() {
57
-        assertThatThrownBy(() -> service.insertTables("bad;name", "2024-01-01", "D1", "ts", "k", "v"))
57
+        assertThatThrownBy(() -> service.insertTables("bad;name", "2024-01-01", "C1", "D1", "ts", "k", "v"))
58 58
             .isInstanceOf(IllegalArgumentException.class);
59 59
         verifyNoInteractions(sysRealtimeMapper);
60 60
     }
@@ -62,14 +62,14 @@ class SysRealtimeServiceTest {
62 62
     @Test
63 63
     @DisplayName("updateTables: 合法表名应调用 mapper")
64 64
     void updatetables_validTableName_callsMapper() {
65
-        service.updateTables("dev_001", "2024-01-01", "v1", "ts", "key1", "D1");
66
-        verify(sysRealtimeMapper).updateTables("dev_001", "2024-01-01", "v1", "ts", "key1", "D1");
65
+        service.updateTables("dev_001", "2024-01-01", "v1", "ts", "key1", "C1", "D1");
66
+        verify(sysRealtimeMapper).updateTables("dev_001", "2024-01-01", "v1", "ts", "key1", "C1", "D1");
67 67
     }
68 68
 
69 69
     @Test
70 70
     @DisplayName("selectKey: 非法表名应抛出异常")
71 71
     void selectkey_invalidTableName_throws() {
72
-        assertThatThrownBy(() -> service.selectKey("--comment", "k"))
72
+        assertThatThrownBy(() -> service.selectKey("--comment", "k", "C1"))
73 73
             .isInstanceOf(IllegalArgumentException.class)
74 74
             .hasMessageContaining("非法表名");
75 75
     }
@@ -77,7 +77,7 @@ class SysRealtimeServiceTest {
77 77
     @Test
78 78
     @DisplayName("selectAllKeys: 合法表名应调用 mapper")
79 79
     void selectAllKeys_validTableName_callsMapper() {
80
-        service.selectAllKeys("realtime_001");
81
-        verify(sysRealtimeMapper).selectAllKeys("realtime_001");
80
+        service.selectAllKeys("realtime_001", "C1");
81
+        verify(sysRealtimeMapper).selectAllKeys("realtime_001", "C1");
82 82
     }
83 83
 }

+ 15
- 14
iot-platform/src/test/java/com/iot/platform/service/TDengineServiceTest.java 파일 보기

@@ -185,22 +185,23 @@ class TDengineServiceTest {
185 185
     @Test
186 186
     @DisplayName("getColumnTypeForDDL: BOOL/BIGINT/DOUBLE/TIMESTAMP 直接返回")
187 187
     void getColumnTypeForDDL_directTypes() throws Exception {
188
-        Method method = TdEngineService.class.getDeclaredMethod("getColumnTypeForDDL", String.class, String.class);
188
+        Method method = TdEngineService.class.getDeclaredMethod("getColumnTypeForDDL", String.class, Integer.class);
189 189
         method.setAccessible(true);
190 190
 
191
-        assertThat(method.invoke(tdengineService, "BOOL", "col")).isEqualTo("BOOL");
192
-        assertThat(method.invoke(tdengineService, "BIGINT", "col")).isEqualTo("BIGINT");
193
-        assertThat(method.invoke(tdengineService, "DOUBLE", "col")).isEqualTo("DOUBLE");
194
-        assertThat(method.invoke(tdengineService, "TIMESTAMP", "col")).isEqualTo("TIMESTAMP");
191
+        assertThat(method.invoke(tdengineService, "BOOL", null)).isEqualTo("BOOL");
192
+        assertThat(method.invoke(tdengineService, "BIGINT", null)).isEqualTo("BIGINT");
193
+        assertThat(method.invoke(tdengineService, "DOUBLE", null)).isEqualTo("DOUBLE");
194
+        assertThat(method.invoke(tdengineService, "TIMESTAMP", null)).isEqualTo("TIMESTAMP");
195 195
     }
196 196
 
197 197
     @Test
198
-    @DisplayName("getColumnTypeForDDL: VARCHAR 返回 VARCHAR(255)")
198
+    @DisplayName("getColumnTypeForDDL: VARCHAR 返回带长度")
199 199
     void getColumnTypeForDDL_varchar_returnsWithLength() throws Exception {
200
-        Method method = TdEngineService.class.getDeclaredMethod("getColumnTypeForDDL", String.class, String.class);
200
+        Method method = TdEngineService.class.getDeclaredMethod("getColumnTypeForDDL", String.class, Integer.class);
201 201
         method.setAccessible(true);
202 202
 
203
-        assertThat(method.invoke(tdengineService, "VARCHAR", "col")).isEqualTo("VARCHAR(255)");
203
+        assertThat(method.invoke(tdengineService, "VARCHAR", 250)).isEqualTo("VARCHAR(255)");
204
+        assertThat(method.invoke(tdengineService, "VARCHAR", null)).isEqualTo("VARCHAR(16)");
204 205
     }
205 206
 
206 207
     @Test
@@ -241,14 +242,14 @@ class TDengineServiceTest {
241 242
     }
242 243
 
243 244
     @Test
244
-    @DisplayName("formatValue: VARCHAR 类型超长时截断存储")
245
-    void formatValue_varchar_exceedsLength_truncates() throws Exception {
245
+    @DisplayName("formatValue: VARCHAR 类型不截断,完整返回")
246
+    void formatValue_varchar_noTruncation() throws Exception {
246 247
         Method method = TdEngineService.class.getDeclaredMethod("formatValue", Object.class, String.class, String.class);
247 248
         method.setAccessible(true);
248 249
 
249 250
         String longStr = "a".repeat(300);
250 251
         assertThat(method.invoke(tdengineService, longStr, "col", "VARCHAR"))
251
-                .isEqualTo("'" + "a".repeat(255) + "'");
252
+                .isEqualTo("'" + "a".repeat(300) + "'");
252 253
     }
253 254
 
254 255
     @Test
@@ -281,15 +282,15 @@ class TDengineServiceTest {
281 282
     }
282 283
 
283 284
     @Test
284
-    @DisplayName("isReservedColumn: ts 和 surfacename 返回 true")
285
+    @DisplayName("isReservedColumn: ts 和 controller_id 返回 true")
285 286
     void isReservedColumn_reservedNames() throws Exception {
286 287
         Method method = TdEngineService.class.getDeclaredMethod("isReservedColumn", String.class);
287 288
         method.setAccessible(true);
288 289
 
289 290
         assertThat(method.invoke(tdengineService, "ts")).isEqualTo(true);
290 291
         assertThat(method.invoke(tdengineService, "TS")).isEqualTo(true);
291
-        assertThat(method.invoke(tdengineService, "surfacename")).isEqualTo(true);
292
-        assertThat(method.invoke(tdengineService, "Surfacename")).isEqualTo(true);
292
+        assertThat(method.invoke(tdengineService, "controller_id")).isEqualTo(true);
293
+        assertThat(method.invoke(tdengineService, "CONTROLLER_ID")).isEqualTo(true);
293 294
     }
294 295
 
295 296
     @Test

Loading…
취소
저장