From 933c947b3e8ced97bef4847966376180b39c115c Mon Sep 17 00:00:00 2001 From: luorijun Date: Tue, 27 May 2025 15:08:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=90=86=E5=92=8C?= =?UTF-8?q?=E8=BE=B9=E7=BC=98=E8=8A=82=E7=82=B9=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B7=E6=B1=82=E5=92=8C=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=85=A8=E9=87=8F?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E4=BF=A1=E6=81=AF=E8=BF=94=E5=9B=9E=EF=BC=8C?= =?UTF-8?q?=E5=BC=95=E5=85=A5=E5=85=A8=E5=B1=80=E9=94=81=E4=BB=A5=E9=98=B2?= =?UTF-8?q?=E6=AD=A2=E5=B9=B6=E5=8F=91=E6=B3=A8=E5=86=8C=EF=BC=9B=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E6=9C=8D=E5=8A=A1=E4=B8=8B=E7=BA=BF=E5=90=8E=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E8=8A=82=E7=82=B9=E4=B9=9F=E6=A0=87=E8=AE=B0=E4=B8=8B?= =?UTF-8?q?=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +- docs/服务网络建立流程图.excalidraw | 1381 +++++++++++++++++----------- go.mod | 11 +- go.sum | 65 +- web/domains/edge/types.go | 2 +- web/globals/redis.go | 11 +- web/handlers/edge.go | 124 +-- web/handlers/proxy.go | 239 ++++- web/router.go | 9 +- 9 files changed, 1222 insertions(+), 649 deletions(-) diff --git a/README.md b/README.md index 7e59b10..15ff1c4 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,33 @@ ## TODO -修改边缘节点上线分配策略,已分配的边缘节点优先使用旧的配置,新的边缘节点使用负载均衡算法分配新的网关 +模型字段修改,特定枚举字段使用自定义类型代替通用 int32 -## 枚举字典 +## 业务逻辑 -### 产品 +### 代理服务与节点的增量更新 + +代理服务定时提交增量更新数据包,格式为: + +| version(1) | proxy_id(4) | count(2) | edge_id(4) | mask(1) | info(...) | +|------------|-------------|----------|------------|---------|-----------| +| 数据包版本 | 代理服务 id | 更新的节点数量 | 节点 id | 节点更新项 | 节点更新内容 | + +其中 mask 部分,每个位代表一个节点更新项,具体如下: + +| 位数(从前到后) | 节点更新项 | +|----------|----------| +| 0 | 保留位,预留扩展 | +| 1 | 空,固定为 0 | +| 2 | 空,固定为 0 | +| 3 | 端口 | +| 4 | 省份 | +| 5 | 城市 | +| 6 | 运营商 | +| 7 | 状态 | + +节点更新的具体内容大小视数据结构而定 + +### 产品字典表 | 代码 | 产品 | |-------|------| diff --git a/docs/服务网络建立流程图.excalidraw b/docs/服务网络建立流程图.excalidraw index 201ca8f..59b97eb 100644 --- a/docs/服务网络建立流程图.excalidraw +++ b/docs/服务网络建立流程图.excalidraw @@ -4,47 +4,12 @@ "source": "https://excalidraw.com", "elements": [ { - "id": "zsbeHr3kNPUaSvPMU-OMT", + "id": "OUaO-jfdbgndfc2j1l-Mb", "type": "rectangle", - "x": 583, - "y": 200, - "width": 116.99999999999997, - "height": 400, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a0", - "roundness": { - "type": 3 - }, - "seed": 277020470, - "version": 77, - "versionNonce": 280720234, - "isDeleted": false, - "boundElements": [ - { - "type": "text", - "id": "WZRxUygjSWpwJ9jCQGz64" - } - ], - "updated": 1747132847296, - "link": null, - "locked": false - }, - { - "id": "WZRxUygjSWpwJ9jCQGz64", - "type": "text", - "x": 600.8700256347656, - "y": 387.5, - "width": 81.25994873046875, - "height": 25, + "x": 533.0555158332934, + "y": 690.630805408583, + "width": 142.1021021021021, + "height": 70.2052052052052, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -56,32 +21,83 @@ "groupIds": [], "frameId": null, "index": "a1", + "roundness": { + "type": 3 + }, + "seed": 1394589719, + "version": 433, + "versionNonce": 231478445, + "isDeleted": false, + "boundElements": [ + { + "id": "asUoS6hhE2KkASqJIm-aO", + "type": "arrow" + }, + { + "type": "text", + "id": "BtuUuyKeAn2Y60JGy82z0" + }, + { + "id": "h_7Wmsp6oW_oD-iMW9dR3", + "type": "arrow" + }, + { + "id": "CupIZ0BOLpYq5Qag3s3xy", + "type": "arrow" + }, + { + "id": "kUZ5P6wYswD10UwwZi8Ws", + "type": "arrow" + } + ], + "updated": 1748256973263, + "link": null, + "locked": false + }, + { + "id": "BtuUuyKeAn2Y60JGy82z0", + "type": "text", + "x": 584.1065668843444, + "y": 713.2334080111856, + "width": 40, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a1V", "roundness": null, - "seed": 687766762, - "version": 67, - "versionNonce": 1888319018, + "seed": 1084566201, + "version": 494, + "versionNonce": 1144134253, "isDeleted": false, "boundElements": [], - "updated": 1747132847296, + "updated": 1748257134960, "link": null, "locked": false, - "text": "platform", + "text": "网关", "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", - "containerId": "zsbeHr3kNPUaSvPMU-OMT", - "originalText": "platform", + "containerId": "OUaO-jfdbgndfc2j1l-Mb", + "originalText": "网关", "autoResize": true, "lineHeight": 1.25 }, { - "id": "h_Vq2Fw7X05jQmOjpvwdp", + "id": "SRSpll66B6dG_KPSLQSYc", "type": "rectangle", - "x": 1200, - "y": 200, - "width": 200.00000000000003, - "height": 100, + "x": 1298.8549263549264, + "y": 680.4764049764049, + "width": 142.94794794794797, + "height": 76.12612612612612, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -96,26 +112,38 @@ "roundness": { "type": 3 }, - "seed": 535145962, - "version": 47, - "versionNonce": 1571657718, + "seed": 431275257, + "version": 331, + "versionNonce": 1414622723, "isDeleted": false, "boundElements": [ + { + "id": "asUoS6hhE2KkASqJIm-aO", + "type": "arrow" + }, { "type": "text", - "id": "PCRc2tKqmXazgf7vBXpBy" + "id": "ZWM1X_tAtVgUqy65iyY1w" + }, + { + "id": "Xqhf-ZeRlWBPt94fYkq6M", + "type": "arrow" + }, + { + "id": "CupIZ0BOLpYq5Qag3s3xy", + "type": "arrow" } ], - "updated": 1747132544466, + "updated": 1748256965995, "link": null, "locked": false }, { - "id": "PCRc2tKqmXazgf7vBXpBy", + "id": "ZWM1X_tAtVgUqy65iyY1w", "type": "text", - "x": 1273.8300247192383, - "y": 237.5, - "width": 52.33995056152344, + "x": 1350.3289003289003, + "y": 706.0394680394679, + "width": 40, "height": 25, "angle": 0, "strokeColor": "#1e1e1e", @@ -127,67 +155,87 @@ "opacity": 100, "groupIds": [], "frameId": null, + "index": "a2V", + "roundness": null, + "seed": 546659319, + "version": 387, + "versionNonce": 542046851, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134960, + "link": null, + "locked": false, + "text": "节点", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "SRSpll66B6dG_KPSLQSYc", + "originalText": "节点", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "KpCCLFeGnq8oXwDKR8jVY", + "type": "rectangle", + "x": 920.6156156156156, + "y": 233, + "width": 134.4894894894895, + "height": 73.58858858858859, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, "index": "a3", - "roundness": null, - "seed": 1744934570, - "version": 32, - "versionNonce": 1978592246, - "isDeleted": false, - "boundElements": [], - "updated": 1747132358707, - "link": null, - "locked": false, - "text": "fwd...", - "fontSize": 20, - "fontFamily": 5, - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "h_Vq2Fw7X05jQmOjpvwdp", - "originalText": "fwd...", - "autoResize": true, - "lineHeight": 1.25 - }, - { - "id": "zNdFfRSAyIRsYWkHi09yH", - "type": "rectangle", - "x": 1201.152228201041, - "y": 500, - "width": 200, - "height": 100, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a4", "roundness": { "type": 3 }, - "seed": 1960286698, - "version": 110, - "versionNonce": 236636202, + "seed": 2131329209, + "version": 265, + "versionNonce": 1997039491, "isDeleted": false, "boundElements": [ { "type": "text", - "id": "3DEBFPuFoQqTfJaMlPRtU" + "id": "CFEJZLzCo0xvfODxWVYcu" + }, + { + "id": "Xqhf-ZeRlWBPt94fYkq6M", + "type": "arrow" + }, + { + "id": "kUZ5P6wYswD10UwwZi8Ws", + "type": "arrow" + }, + { + "id": "h_7Wmsp6oW_oD-iMW9dR3", + "type": "arrow" + }, + { + "id": "wwDi2BzkrDMkNZKEMii6T", + "type": "arrow" + }, + { + "id": "H-kVvnOyhW7UQ4sy1mUBg", + "type": "arrow" } ], - "updated": 1747132546398, + "updated": 1748257022221, "link": null, "locked": false }, { - "id": "3DEBFPuFoQqTfJaMlPRtU", + "id": "CFEJZLzCo0xvfODxWVYcu", "type": "text", - "x": 1270.5922535306308, - "y": 537.5, - "width": 61.11994934082031, + "x": 967.8603603603603, + "y": 257.2942942942943, + "width": 40, "height": 25, "angle": 0, "strokeColor": "#1e1e1e", @@ -199,209 +247,33 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "a5", + "index": "a3V", "roundness": null, - "seed": 1536135146, - "version": 109, - "versionNonce": 58765174, + "seed": 1302672761, + "version": 314, + "versionNonce": 1965241741, "isDeleted": false, "boundElements": [], - "updated": 1747132520694, + "updated": 1748257134960, "link": null, "locked": false, - "text": "edge...", + "text": "平台", "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", - "containerId": "zNdFfRSAyIRsYWkHi09yH", - "originalText": "edge...", + "containerId": "KpCCLFeGnq8oXwDKR8jVY", + "originalText": "平台", "autoResize": true, "lineHeight": 1.25 }, { - "id": "FaY6s3IeRlUKxMRwPzXX4", + "id": "asUoS6hhE2KkASqJIm-aO", "type": "arrow", - "x": 1161.5263313428777, - "y": 201.7402520552557, - "width": 420, - "height": 0, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a6", - "roundness": { - "type": 2 - }, - "seed": 1025214378, - "version": 267, - "versionNonce": 650402614, - "isDeleted": false, - "boundElements": [ - { - "type": "text", - "id": "iCHZyeKUHerPacOJtYeYI" - } - ], - "updated": 1747132627325, - "link": null, - "locked": false, - "points": [ - [ - 0, - 0 - ], - [ - -420, - 0 - ] - ], - "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "elbowed": false - }, - { - "id": "iCHZyeKUHerPacOJtYeYI", - "type": "text", - "x": 894.7183479444402, - "y": 191.7402520552557, - "width": 113.615966796875, - "height": 20, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a6V", - "roundness": null, - "seed": 118902262, - "version": 27, - "versionNonce": 781320938, - "isDeleted": false, - "boundElements": null, - "updated": 1747132957440, - "link": null, - "locked": false, - "text": "1. 注册转发服务", - "fontSize": 16, - "fontFamily": 5, - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "FaY6s3IeRlUKxMRwPzXX4", - "originalText": "1. 注册转发服务", - "autoResize": true, - "lineHeight": 1.25 - }, - { - "id": "po3Veg6YDVvp2KXkFaFuS", - "type": "arrow", - "x": 1161.152228201041, - "y": 520.5986727826297, - "width": 420, - "height": 0, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a7", - "roundness": { - "type": 2 - }, - "seed": 910967926, - "version": 493, - "versionNonce": 1269815542, - "isDeleted": false, - "boundElements": [ - { - "type": "text", - "id": "6vSZb4yswl2PqEOZHsbfY" - } - ], - "updated": 1747132667478, - "link": null, - "locked": false, - "points": [ - [ - 0, - 0 - ], - [ - -420, - 0 - ] - ], - "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "elbowed": false - }, - { - "id": "6vSZb4yswl2PqEOZHsbfY", - "type": "text", - "x": 892.896239126334, - "y": 510.5986727826297, - "width": 116.51197814941406, - "height": 20, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a7V", - "roundness": null, - "seed": 781601642, - "version": 36, - "versionNonce": 1701769718, - "isDeleted": false, - "boundElements": null, - "updated": 1747132957441, - "link": null, - "locked": false, - "text": "3. 注册边缘节点", - "fontSize": 16, - "fontFamily": 5, - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "po3Veg6YDVvp2KXkFaFuS", - "originalText": "3. 注册边缘节点", - "autoResize": true, - "lineHeight": 1.25 - }, - { - "id": "BNs2GbrhDdzbMBJzAWdwv", - "type": "arrow", - "x": 1300, - "y": 460, - "width": 0, - "height": 120, + "x": 1288.597567914963, + "y": 693.474947309669, + "width": 606.5219187772383, + "height": 7.554940480555047, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -416,17 +288,17 @@ "roundness": { "type": 2 }, - "seed": 799286378, - "version": 309, - "versionNonce": 925925802, + "seed": 19080439, + "version": 984, + "versionNonce": 2057735533, "isDeleted": false, "boundElements": [ { "type": "text", - "id": "Kx-Zgee6eTpVb7Mgq6W9S" + "id": "cyfcTwCPgyHygQ8PTHRM1" } ], - "updated": 1747132974134, + "updated": 1748256973263, "link": null, "locked": false, "points": [ @@ -435,95 +307,31 @@ 0 ], [ - 0, - -120 + -606.5219187772383, + 7.554940480555047 ] ], "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, + "startBinding": { + "elementId": "SRSpll66B6dG_KPSLQSYc", + "focus": 0.6678799246937968, + "gap": 11.959664224263923 + }, + "endBinding": { + "elementId": "OUaO-jfdbgndfc2j1l-Mb", + "focus": -0.6594508828129372, + "gap": 8.074620247669158 + }, "startArrowhead": null, "endArrowhead": "arrow", "elbowed": false }, { - "id": "Kx-Zgee6eTpVb7Mgq6W9S", + "id": "cyfcTwCPgyHygQ8PTHRM1", "type": "text", - "x": 1217.6640167236328, - "y": 380, - "width": 164.67196655273438, - "height": 40, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a8V", - "roundness": null, - "seed": 1451839658, - "version": 66, - "versionNonce": 1319645994, - "isDeleted": false, - "boundElements": null, - "updated": 1747132957442, - "link": null, - "locked": false, - "text": "5. 边缘节点连接到转发\n服务", - "fontSize": 16, - "fontFamily": 5, - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "BNs2GbrhDdzbMBJzAWdwv", - "originalText": "5. 边缘节点连接到转发服务", - "autoResize": true, - "lineHeight": 1.25 - }, - { - "id": "mFDQoiG3vbpyFwQBC7jyG", - "type": "rectangle", - "x": 198, - "y": 351, - "width": 200, - "height": 100, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "a9", - "roundness": { - "type": 3 - }, - "seed": 1351484214, - "version": 37, - "versionNonce": 1265028342, - "isDeleted": false, - "boundElements": [ - { - "type": "text", - "id": "5y_lj25Q01lH09VvtpEee" - } - ], - "updated": 1747132838847, - "link": null, - "locked": false - }, - { - "id": "5y_lj25Q01lH09VvtpEee", - "type": "text", - "x": 277.6000213623047, - "y": 388.5, - "width": 40.799957275390625, + "x": 945.336608526344, + "y": 684.7524175499466, + "width": 80, "height": 25, "angle": 0, "strokeColor": "#1e1e1e", @@ -535,33 +343,33 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "a9V", + "index": "a8G", "roundness": null, - "seed": 1682566506, - "version": 28, - "versionNonce": 1110294070, + "seed": 1890633741, + "version": 148, + "versionNonce": 382780771, "isDeleted": false, "boundElements": [], - "updated": 1747132838847, + "updated": 1748257134960, "link": null, "locked": false, - "text": "user", + "text": "节点连入", "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", - "containerId": "mFDQoiG3vbpyFwQBC7jyG", - "originalText": "user", + "containerId": "asUoS6hhE2KkASqJIm-aO", + "originalText": "节点连入", "autoResize": true, "lineHeight": 1.25 }, { - "id": "gcvXDtgBKjckbIcfsDhkr", + "id": "Xqhf-ZeRlWBPt94fYkq6M", "type": "arrow", - "x": 423, - "y": 399, - "width": 129, - "height": 0, + "x": 1378.523253295927, + "y": 673.6733206457401, + "width": 317.55388587134894, + "height": 359.879900812749, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -576,12 +384,17 @@ "roundness": { "type": 2 }, - "seed": 1116663094, - "version": 209, - "versionNonce": 1517628458, + "seed": 405136099, + "version": 539, + "versionNonce": 581822691, "isDeleted": false, - "boundElements": [], - "updated": 1747132848563, + "boundElements": [ + { + "type": "text", + "id": "66bKE1klc1nkNVd6_2HDD" + } + ], + "updated": 1748256965995, "link": null, "locked": false, "points": [ @@ -590,24 +403,32 @@ 0 ], [ - 129, - 0 + -317.55388587134894, + -359.879900812749 ] ], "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, + "startBinding": { + "elementId": "SRSpll66B6dG_KPSLQSYc", + "focus": 0.45495464204504327, + "gap": 13.140347981828086 + }, + "endBinding": { + "elementId": "KpCCLFeGnq8oXwDKR8jVY", + "focus": -0.34595637630746967, + "gap": 16.95863159263879 + }, "startArrowhead": null, "endArrowhead": "arrow", "elbowed": false }, { - "id": "i_8u5473xh1b8I_yoY07j", - "type": "arrow", - "x": 1160.743274975568, - "y": 241.59697448672608, - "width": 420, - "height": 0, + "id": "66bKE1klc1nkNVd6_2HDD", + "type": "text", + "x": 1179.7463103602524, + "y": 481.2333702393656, + "width": 80, + "height": 25, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -618,21 +439,58 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "aB", + "index": "aAV", + "roundness": null, + "seed": 967981869, + "version": 147, + "versionNonce": 1500511299, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134961, + "link": null, + "locked": false, + "text": "请求分配", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Xqhf-ZeRlWBPt94fYkq6M", + "originalText": "请求分配", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "h_7Wmsp6oW_oD-iMW9dR3", + "type": "arrow", + "x": 561.8870469489292, + "y": 675.1614307522879, + "width": 344.16716607753233, + "height": 418.9642966904891, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aC", "roundness": { "type": 2 }, - "seed": 1331335734, - "version": 72, - "versionNonce": 624254710, + "seed": 1841562893, + "version": 1191, + "versionNonce": 1545796141, "isDeleted": false, "boundElements": [ { "type": "text", - "id": "hfpuERsbfPQwM7YecmMfg" + "id": "FeiHqg_trZcU3DnCEHovE" } ], - "updated": 1747132629207, + "updated": 1748256982389, "link": null, "locked": false, "points": [ @@ -641,24 +499,32 @@ 0 ], [ - -420, - 0 + 344.16716607753233, + -418.9642966904891 ] ], "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": "arrow", - "endArrowhead": null, + "startBinding": { + "elementId": "OUaO-jfdbgndfc2j1l-Mb", + "focus": -0.8385784942740364, + "gap": 15.469374656295145 + }, + "endBinding": { + "elementId": "KpCCLFeGnq8oXwDKR8jVY", + "focus": 0.9480006783469175, + "gap": 14.561402589154113 + }, + "startArrowhead": null, + "endArrowhead": "arrow", "elbowed": false }, { - "id": "hfpuERsbfPQwM7YecmMfg", + "id": "FeiHqg_trZcU3DnCEHovE", "type": "text", - "x": 888.3272974975407, - "y": 231.59697448672608, - "width": 124.83195495605469, - "height": 20, + "x": 683.9706299876954, + "y": 440.6792824070433, + "width": 100, + "height": 50, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -669,33 +535,33 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "aBV", + "index": "aCV", "roundness": null, - "seed": 127815402, - "version": 26, - "versionNonce": 772697526, + "seed": 869398819, + "version": 195, + "versionNonce": 1195567053, "isDeleted": false, - "boundElements": null, - "updated": 1747132957442, + "boundElements": [], + "updated": 1748257134961, "link": null, "locked": false, - "text": "2. 平台返回 200", - "fontSize": 16, + "text": "报告上下线\n报告更新", + "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", - "containerId": "i_8u5473xh1b8I_yoY07j", - "originalText": "2. 平台返回 200", + "containerId": "h_7Wmsp6oW_oD-iMW9dR3", + "originalText": "报告上下线\n报告更新", "autoResize": true, "lineHeight": 1.25 }, { - "id": "PjDN6opphck2HkSYTe1Ln", + "id": "CupIZ0BOLpYq5Qag3s3xy", "type": "arrow", - "x": 1159.5713063315768, - "y": 581.2037355477607, - "width": 420, - "height": 0, + "x": 1287.1161658678975, + "y": 741.9191208015678, + "width": 605.5912941945408, + "height": 5.122675813953833, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -706,21 +572,21 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "aE", + "index": "aG", "roundness": { "type": 2 }, - "seed": 1407186474, - "version": 38, - "versionNonce": 580002102, + "seed": 1552118659, + "version": 857, + "versionNonce": 1883887149, "isDeleted": false, "boundElements": [ { "type": "text", - "id": "2qs1YbvHnFM3og-O2ZoRa" + "id": "7JWwgWAIY9694s2uFMll0" } ], - "updated": 1747132598748, + "updated": 1748256973263, "link": null, "locked": false, "points": [ @@ -729,61 +595,32 @@ 0 ], [ - -420, - 0 + -605.5912941945408, + 5.122675813953833 ] ], "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": "arrow", - "endArrowhead": null, + "startBinding": { + "elementId": "SRSpll66B6dG_KPSLQSYc", + "focus": -0.5936890046850755, + "gap": 13.73761156822924 + }, + "endBinding": { + "elementId": "OUaO-jfdbgndfc2j1l-Mb", + "focus": 0.6151607366935045, + "gap": 7.240428690095611 + }, + "startArrowhead": null, + "endArrowhead": "arrow", "elbowed": false }, { - "id": "2qs1YbvHnFM3og-O2ZoRa", + "id": "7JWwgWAIY9694s2uFMll0", "type": "text", - "x": 875.4993229941745, - "y": 571.2037355477607, - "width": 148.1439666748047, - "height": 20, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "index": "aF", - "roundness": null, - "seed": 983535734, - "version": 71, - "versionNonce": 1835696502, - "isDeleted": false, - "boundElements": null, - "updated": 1747132957442, - "link": null, - "locked": false, - "text": "4. 平台分配转发服务", - "fontSize": 16, - "fontFamily": 5, - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "PjDN6opphck2HkSYTe1Ln", - "originalText": "4. 平台分配转发服务", - "autoResize": true, - "lineHeight": 1.25 - }, - { - "id": "8AtKcV9AvqUvk2Mr9flrI", - "type": "arrow", - "x": 740, - "y": 280, - "width": 420, - "height": 0, + "x": 944.3205187706271, + "y": 731.9804587085448, + "width": 80, + "height": 25, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -795,46 +632,32 @@ "groupIds": [], "frameId": null, "index": "aH", - "roundness": { - "type": 2 - }, - "seed": 1080875126, - "version": 25, - "versionNonce": 1872649834, + "roundness": null, + "seed": 1975288621, + "version": 138, + "versionNonce": 261365539, "isDeleted": false, - "boundElements": [ - { - "type": "text", - "id": "sZja5umzjfTmtuZDk_hsS" - } - ], - "updated": 1747132657373, + "boundElements": [], + "updated": 1748257134962, "link": null, "locked": false, - "points": [ - [ - 0, - 0 - ], - [ - 420, - 0 - ] - ], - "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": "arrow", - "endArrowhead": null, - "elbowed": false + "text": "节点心跳", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "CupIZ0BOLpYq5Qag3s3xy", + "originalText": "节点心跳", + "autoResize": true, + "lineHeight": 1.25 }, { - "id": "sZja5umzjfTmtuZDk_hsS", + "id": "3oFDCs_rog-98qjPppui2", "type": "text", - "x": 859.4880142211914, - "y": 270, - "width": 181.0239715576172, - "height": 20, + "x": 505.1587301587302, + "y": 784.6366366366367, + "width": 426.0948448448449, + "height": 275, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", @@ -845,23 +668,500 @@ "opacity": 100, "groupIds": [], "frameId": null, - "index": "aI", + "index": "aL", "roundness": null, - "seed": 705278454, - "version": 41, - "versionNonce": 1536576426, + "seed": 391221187, + "version": 1530, + "versionNonce": 639794925, "isDeleted": false, - "boundElements": null, - "updated": 1747132957443, + "boundElements": [], + "updated": 1748257134965, "link": null, "locked": false, - "text": "6. 转发服务更新端口信息", - "fontSize": 16, + "text": "网关启动后首先自检,如果是新网关则生成 lock\n文件。\n\n网关上下线时向平台报告,上线时平台需要返回\n记录的授权信息\n\n节点向网关发送心跳,如果 ip 有变化则携带新\n的 geo 信息\n\n网关定时与现有的节点数据做 diff,增量更新有\n变化的节点信息", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "网关启动后首先自检,如果是新网关则生成 lock 文件。\n\n网关上下线时向平台报告,上线时平台需要返回记录的授权信息\n\n节点向网关发送心跳,如果 ip 有变化则携带新的 geo 信息\n\n网关定时与现有的节点数据做 diff,增量更新有变化的节点信息", + "autoResize": false, + "lineHeight": 1.25 + }, + { + "id": "bpoLs6riklIvEjBwYEU7O", + "type": "text", + "x": 1313.1402831402831, + "y": 767.6732446732445, + "width": 260, + "height": 50, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aN", + "roundness": null, + "seed": 594609741, + "version": 272, + "versionNonce": 1303770531, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134965, + "link": null, + "locked": false, + "text": "节点上线向平台请求分配网关\n", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "节点上线向平台请求分配网关\n", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "kUZ5P6wYswD10UwwZi8Ws", + "type": "arrow", + "x": 915.8624173524173, + "y": 315.48557639512313, + "width": 257.3941387386344, + "height": 361.2589733743561, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aR", + "roundness": { + "type": 2 + }, + "seed": 1891882637, + "version": 578, + "versionNonce": 1360243203, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "q9sHgO92OgClhLRxR2kgQ" + } + ], + "updated": 1748257067091, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -257.3941387386344, + 361.2589733743561 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "KpCCLFeGnq8oXwDKR8jVY", + "focus": 0.42203194719778103, + "gap": 16.303174613894328 + }, + "endBinding": { + "elementId": "OUaO-jfdbgndfc2j1l-Mb", + "focus": 0.18988087005886545, + "gap": 13.89394543716626 + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "q9sHgO92OgClhLRxR2kgQ", + "type": "text", + "x": 747.1653479831001, + "y": 483.61506308230116, + "width": 80, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aS", + "roundness": null, + "seed": 648945709, + "version": 153, + "versionNonce": 1106845805, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134966, + "link": null, + "locked": false, + "text": "访问配置", + "fontSize": 20, "fontFamily": 5, "textAlign": "center", "verticalAlign": "middle", - "containerId": "8AtKcV9AvqUvk2Mr9flrI", - "originalText": "6. 转发服务更新端口信息", + "containerId": "kUZ5P6wYswD10UwwZi8Ws", + "originalText": "访问配置", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "KL1nGwvLBz0STGTr5rFKy", + "type": "ellipse", + "x": 942.7889993167772, + "y": 503.8968492301824, + "width": 95.78801023245468, + "height": 103.37672020287398, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aU", + "roundness": { + "type": 2 + }, + "seed": 1822296579, + "version": 310, + "versionNonce": 463747971, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "5bviELHwK3ca9uMtkV5Ej" + }, + { + "id": "wwDi2BzkrDMkNZKEMii6T", + "type": "arrow" + } + ], + "updated": 1748257173634, + "link": null, + "locked": false + }, + { + "id": "5bviELHwK3ca9uMtkV5Ej", + "type": "text", + "x": 970.816828637137, + "y": 530.5360193954812, + "width": 40, + "height": 50, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aUV", + "roundness": null, + "seed": 428950435, + "version": 279, + "versionNonce": 1127732003, + "isDeleted": false, + "boundElements": [], + "updated": 1748257173634, + "link": null, + "locked": false, + "text": "数据\n库", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "KL1nGwvLBz0STGTr5rFKy", + "originalText": "数据库", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "wwDi2BzkrDMkNZKEMii6T", + "type": "arrow", + "x": 985.120288062112, + "y": 321.18816729591845, + "width": 5.018370792285509, + "height": 166.22123167951702, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aX", + "roundness": { + "type": 2 + }, + "seed": 1227590915, + "version": 242, + "versionNonce": 610015043, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "gUL_tUvCRbSFZHcPIE-fl" + } + ], + "updated": 1748257177643, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 5.018370792285509, + 166.22123167951702 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "KpCCLFeGnq8oXwDKR8jVY", + "focus": 0.06278491274007861, + "gap": 14.59957870732984 + }, + "endBinding": { + "elementId": "KL1nGwvLBz0STGTr5rFKy", + "focus": 0.03085133555331287, + "gap": 16.4898870472052 + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "gUL_tUvCRbSFZHcPIE-fl", + "type": "text", + "x": 937.0921018183194, + "y": 375.2708758913577, + "width": 100, + "height": 50, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aY", + "roundness": null, + "seed": 563295053, + "version": 72, + "versionNonce": 1874852749, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134966, + "link": null, + "locked": false, + "text": "网关和节点\n授权信息", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "wwDi2BzkrDMkNZKEMii6T", + "originalText": "网关和节点\n授权信息", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "ixi6dOW1R4dxoWpk6P5Ox", + "type": "rectangle", + "x": 909.1825396825402, + "y": 5.650793650793673, + "width": 147.1428571428571, + "height": 74.28571428571428, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aj", + "roundness": { + "type": 3 + }, + "seed": 1191278477, + "version": 81, + "versionNonce": 1419277101, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "tq0aJoT_MxhxcuLfUv0T8" + }, + { + "id": "H-kVvnOyhW7UQ4sy1mUBg", + "type": "arrow" + } + ], + "updated": 1748256943813, + "link": null, + "locked": false + }, + { + "id": "tq0aJoT_MxhxcuLfUv0T8", + "type": "text", + "x": 962.7539682539688, + "y": 30.293650793650812, + "width": 40, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "ak", + "roundness": null, + "seed": 738194403, + "version": 51, + "versionNonce": 1869094755, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134966, + "link": null, + "locked": false, + "text": "用户", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ixi6dOW1R4dxoWpk6P5Ox", + "originalText": "用户", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "H-kVvnOyhW7UQ4sy1mUBg", + "type": "arrow", + "x": 982.3005025682027, + "y": 84.84971980582708, + "width": 2.078181266293882, + "height": 145.90957904337336, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "al", + "roundness": { + "type": 2 + }, + "seed": 1596364643, + "version": 107, + "versionNonce": 1540180973, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "oZ3apDpQg31Q-_hiS5NF3" + } + ], + "updated": 1748256943813, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -2.078181266293882, + 145.90957904337336 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ixi6dOW1R4dxoWpk6P5Ox", + "focus": -0.0019765143587950236, + "gap": 10.000000000000057 + }, + "endBinding": { + "elementId": "KpCCLFeGnq8oXwDKR8jVY", + "focus": -0.12085434196128003, + "gap": 4.492063492063437 + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "oZ3apDpQg31Q-_hiS5NF3", + "type": "text", + "x": 961.2614119350558, + "y": 145.30450932751376, + "width": 40, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "am", + "roundness": null, + "seed": 440751501, + "version": 9, + "versionNonce": 1310927533, + "isDeleted": false, + "boundElements": [], + "updated": 1748257134966, + "link": null, + "locked": false, + "text": "提取", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "H-kVvnOyhW7UQ4sy1mUBg", + "originalText": "提取", "autoResize": true, "lineHeight": 1.25 } @@ -870,7 +1170,8 @@ "gridSize": 20, "gridStep": 5, "gridModeEnabled": false, - "viewBackgroundColor": "#ffffff" + "viewBackgroundColor": "#ffffff", + "lockedMultiSelections": {} }, "files": {} } \ No newline at end of file diff --git a/go.mod b/go.mod index 4e1814b..4198e63 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,8 @@ require ( github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.26.0 + github.com/go-redsync/redsync v1.4.2 + github.com/go-redsync/redsync/v4 v4.13.0 github.com/gofiber/fiber/v2 v2.52.6 github.com/google/uuid v1.6.0 github.com/hibiken/asynq v0.25.1 @@ -41,8 +43,13 @@ require ( github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/go-redis/redis v6.15.9+incompatible // indirect github.com/go-sql-driver/mysql v1.9.1 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect + github.com/gomodule/redigo v2.0.0+incompatible // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.4 // indirect @@ -58,6 +65,8 @@ require ( github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect + github.com/onsi/gomega v1.37.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/smartwalle/ncrypto v1.0.4 // indirect @@ -73,7 +82,7 @@ require ( golang.org/x/text v0.23.0 // indirect golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.31.0 // indirect - google.golang.org/protobuf v1.35.2 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gorm.io/datatypes v1.2.5 // indirect gorm.io/driver/mysql v1.5.7 // indirect diff --git a/go.sum b/go.sum index 8ad6c9b..f08d8c0 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,9 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -87,9 +90,20 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI= +github.com/go-redis/redis/v7 v7.4.1/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-redsync/redsync v1.4.2 h1:KADEZ2rlaHMZWnlkthQCxfGP+8ZWwJLiSjOYN3mntKA= +github.com/go-redsync/redsync v1.4.2/go.mod h1:my8/M5YL986u2jBMtZTLkBIgBsKNNSixJWzWwISH6Uw= +github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkvQ1EkZKA= +github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI= github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI= github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= @@ -109,19 +123,29 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hibiken/asynq v0.25.1 h1:phj028N0nm15n8O2ims+IvJ2gz4k2auvermngh9JhTw= github.com/hibiken/asynq v0.25.1/go.mod h1:pazWNOLBu0FEynQRBvHA26qdIKRSmfdIfUm4HdsLmXg= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= @@ -176,10 +200,24 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo= +github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -214,6 +252,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= @@ -227,6 +267,7 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -251,6 +292,7 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -260,13 +302,16 @@ golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -287,6 +332,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -295,12 +341,17 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -350,6 +401,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= @@ -359,6 +411,7 @@ golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -373,15 +426,20 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -397,6 +455,7 @@ gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDa gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g= gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g= gorm.io/gen v0.3.27 h1:ziocAFLpE7e0g4Rum69pGfB9S6DweTxK8gAun7cU8as= +gorm.io/gen v0.3.27/go.mod h1:9zquz2xD1f3Eb/eHq4oLn2z6vDVvQlCY5S3uMBLv4EA= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/web/domains/edge/types.go b/web/domains/edge/types.go index 929fa70..0d630e9 100644 --- a/web/domains/edge/types.go +++ b/web/domains/edge/types.go @@ -23,7 +23,7 @@ func ISPFromStr(str string) ISP { return IspUnknown } -func ISPToStr(isp ISP) string { +func (isp ISP) String() string { switch isp { case IspChinaTelecom: return "电信" diff --git a/web/globals/redis.go b/web/globals/redis.go index 01a0bda..308516f 100644 --- a/web/globals/redis.go +++ b/web/globals/redis.go @@ -1,20 +1,29 @@ package globals import ( + "github.com/go-redsync/redsync/v4/redis/goredis/v9" "net" "platform/pkg/env" + "github.com/go-redsync/redsync/v4" "github.com/redis/go-redis/v9" ) var Redis *redis.Client +var Redsync *redsync.Redsync func initRedis() { - Redis = redis.NewClient(&redis.Options{ + client := redis.NewClient(&redis.Options{ Addr: net.JoinHostPort(env.RedisHost, env.RedisPort), DB: env.RedisDb, Password: env.RedisPass, }) + + pool := goredis.NewPool(client) + sync := redsync.New(pool) + + Redis = client + Redsync = sync } func ExitRedis() error { diff --git a/web/handlers/edge.go b/web/handlers/edge.go index a9fe26c..10a0c15 100644 --- a/web/handlers/edge.go +++ b/web/handlers/edge.go @@ -1,6 +1,10 @@ package handlers import ( + "errors" + "gorm.io/gen/field" + "gorm.io/gorm" + "log/slog" "platform/pkg/u" "platform/web/auth" edge2 "platform/web/domains/edge" @@ -11,16 +15,11 @@ import ( s "platform/web/services" "github.com/gofiber/fiber/v2" - "gorm.io/gen/field" - "gorm.io/gorm/clause" ) type RegisterEdgeReq struct { - Name string `json:"name" validate:"required"` - Version int `json:"version" validate:"required"` - ISP edge2.ISP `json:"isp"` - Prov string `json:"prov"` - City string `json:"city"` + Name string `json:"name" validate:"required"` + Version int `json:"version" validate:"required"` } type RegisterEdgeResp struct { @@ -28,7 +27,7 @@ type RegisterEdgeResp struct { Host string `json:"host"` } -func OnlineEdge(c *fiber.Ctx) (err error) { +func AssignEdge(c *fiber.Ctx) (err error) { // 验证请求参数 var req = new(RegisterEdgeReq) @@ -37,36 +36,64 @@ func OnlineEdge(c *fiber.Ctx) (err error) { return err } - // 挑选合适的转发服务 - var fwd *m.Proxy - fwd, err = q.Proxy. - LeftJoin(q.Edge, q.Edge.ProxyID.EqCol(q.Proxy.ID), q.Edge.Status.Eq(1)). - Select(q.Proxy.ALL, q.Edge.ALL.Count().As("count")). - Where(q.Proxy.Type.Eq(int32(proxy2.TypeSelfHosted))). - Group(q.Proxy.ID). - Order(field.NewField("", "count").Desc()). - First() - if err != nil { - return err + // 全局锁,防止并发注册 + var mutex = g.Redsync.NewMutex("edge:discovery") + if err := mutex.Lock(); err != nil { + return errors.New("服务繁忙,请稍后重试") } + defer func() { + if ok, err := mutex.Unlock(); err != nil { + slog.Error("解锁失败", slog.Bool("ok", ok), slog.Any("err", err)) + } + }() - // 保存节点信息 - var edge = &m.Edge{ - Name: req.Name, - Version: int32(req.Version), - Host: c.Context().RemoteIP().String(), - Isp: int32(req.ISP), - Prov: req.Prov, - City: req.City, - ProxyID: &fwd.ID, - Type: int32(edge2.TypeSelfHosted), - Status: 1, - } - err = q.Edge.Clauses(clause.OnConflict{ - UpdateAll: true, - Columns: []clause.Column{{Name: "name"}}, - }).Create(edge) - if err != nil { + // 检查节点 + var fwd *m.Proxy + var edge *m.Edge + edge, err = q.Edge. + Where(q.Edge.Name.Eq(req.Name)). + Take() + if errors.Is(err, gorm.ErrRecordNotFound) { + // 挑选合适的转发服务 + fwd, err = q.Proxy. + LeftJoin(q.Edge, q.Edge.ProxyID.EqCol(q.Proxy.ID), q.Edge.Status.Eq(1)). + Select(q.Proxy.ALL, q.Edge.ALL.Count().As("count")). + Where(q.Proxy.Type.Eq(int32(proxy2.TypeSelfHosted))). + Group(q.Proxy.ID). + Order(field.NewField("", "count").Desc()). + First() + if err != nil { + return err + } + // 保存节点信息 + edge = &m.Edge{ + Name: req.Name, + Version: int32(req.Version), + Type: int32(edge2.TypeSelfHosted), + ProxyID: &fwd.ID, + } + err = q.Edge.Create(edge) + if err != nil { + return err + } + } else if err == nil { + // 获取已配置的转发服务 + fwd, err = q.Proxy. + Where(q.Proxy.ID.Eq(*edge.ProxyID)). + Take() + if err != nil { + return err + } + // 节点已存在,更新版本号 + if edge.Version < int32(req.Version) { + _, err = q.Edge. + Where(q.Edge.ID.Eq(edge.ID)). + UpdateSimple(q.Edge.Version.Value(int32(req.Version))) + if err != nil { + return err + } + } + } else { return err } @@ -77,29 +104,6 @@ func OnlineEdge(c *fiber.Ctx) (err error) { }) } -type OfflineEdgeReq struct { - Name string `json:"name" validate:"required"` -} - -func OfflineEdge(c *fiber.Ctx) (err error) { - // 验证请求参数 - var req = new(OfflineEdgeReq) - err = g.Validator.Validate(c, req) - if err != nil { - return err - } - - // 下线转发服务 - _, err = q.Edge. - Where(q.Edge.Name.Eq(req.Name)). - UpdateSimple(q.Edge.Status.Value(0)) - if err != nil { - return err - } - - return c.SendStatus(fiber.StatusOK) -} - type AllEdgesAvailableReq struct { s.EdgeFilter Count int `json:"count"` @@ -140,7 +144,7 @@ func AllEdgesAvailable(c *fiber.Ctx) (err error) { edges[i] = AllEdgesAvailableRespItem{ Ip: info.Host, Port: u.Z(info.ProxyPort), - Isp: edge2.ISPToStr(edge2.ISP(info.Isp)), + Isp: edge2.ISP(info.Isp).String(), Prov: info.Prov, City: info.City, Status: info.Status, diff --git a/web/handlers/proxy.go b/web/handlers/proxy.go index 844ad48..deded4f 100644 --- a/web/handlers/proxy.go +++ b/web/handlers/proxy.go @@ -3,11 +3,12 @@ package handlers import ( "crypto/rand" "encoding/base32" - "github.com/gofiber/fiber/v2" + "fmt" "log/slog" "platform/pkg/u" auth2 "platform/web/auth" "platform/web/core" + edge2 "platform/web/domains/edge" proxy2 "platform/web/domains/proxy" g "platform/web/globals" "platform/web/globals/orm" @@ -16,23 +17,27 @@ import ( "strings" "time" + "github.com/gofiber/fiber/v2" + + "gorm.io/gen/field" "gorm.io/gorm/clause" ) -// region OnlineProxy +// region 报告上线 -type OnlineProxyReq struct { +type ProxyReportOnlineReq struct { Name string `json:"name" validate:"required"` Version int `json:"version" validate:"required"` } -type OnlineProxyResp struct { - Id int32 `json:"id"` - Secret string `json:"secret"` - Permits []ProxyPermit `json:"permits"` +type ProxyReportOnlineResp struct { + Id int32 `json:"id"` + Secret string `json:"secret"` + Permits []*ProxyPermit `json:"permits"` + Edges []*ProxyEdge `json:"edges"` } -func OnlineProxy(c *fiber.Ctx) (err error) { +func ProxyReportOnline(c *fiber.Ctx) (err error) { // 检查接口权限 _, err = auth2.NewProtect(c).Payload( @@ -43,7 +48,7 @@ func OnlineProxy(c *fiber.Ctx) (err error) { } // 验证请求参数 - var req = new(OnlineProxyReq) + var req = new(ProxyReportOnlineReq) err = g.Validator.Validate(c, req) if err != nil { return err @@ -81,6 +86,28 @@ func OnlineProxy(c *fiber.Ctx) (err error) { return err } + // 获取边缘节点信息 + data, err := q.Edge.Where( + q.Edge.ProxyID.Eq(proxy.ID), + ).Find() + if err != nil { + return err + } + edges := make([]*ProxyEdge, len(data)) + for i, edge := range data { + edges[i] = &ProxyEdge{ + Id: edge.ID, + Port: edge.ProxyPort, + Prov: &edge.Prov, + City: &edge.City, + Isp: u.P(edge2.ISP(edge.Isp).String()), + Status: &edge.Status, + Loss: edge.Loss, + Rtt: edge.Rtt, + } + } + + // 获取许可配置 channels, err := q.Channel.Where( q.Channel.ProxyID.Eq(proxy.ID), q.Channel.Expiration.Gt(orm.LocalDateTime(time.Now())), @@ -89,38 +116,38 @@ func OnlineProxy(c *fiber.Ctx) (err error) { return err } - var permits []ProxyPermit - for _, channel := range channels { + var permits = make([]*ProxyPermit, len(channels)) + for i, channel := range channels { if channel.EdgeID == nil { - return core.NewBizErr("通道未分配边缘节点") + return core.NewBizErr(fmt.Sprintf("权限解析异常,通道缺少边缘节点ID %d", channel.ID)) } - permit := ProxyPermit{ + permits[i] = &ProxyPermit{ Id: *channel.EdgeID, Expire: time.Time(channel.Expiration), Whitelists: u.P(strings.Split(u.Z(channel.Whitelists), ",")), Username: channel.Username, Password: channel.Password, } - permits = append(permits, permit) } slog.Debug("注册转发服务", "ip", ip, "id", proxy.ID) - return c.JSON(&OnlineProxyResp{ + return c.JSON(&ProxyReportOnlineResp{ Id: proxy.ID, Secret: secret, + Edges: edges, Permits: permits, }) } // endregion -// region OfflineProxy +// region 报告下线 -type OfflineProxyReq struct { - Name string `json:"name" validate:"required"` +type ProxyReportOfflineReq struct { + Id int32 `json:"id" validate:"required"` } -func OfflineProxy(c *fiber.Ctx) (err error) { +func ProxyReportOffline(c *fiber.Ctx) (err error) { // 检查接口权限 _, err = auth2.NewProtect(c).Payload( auth2.PayloadInternalServer, @@ -130,7 +157,7 @@ func OfflineProxy(c *fiber.Ctx) (err error) { } // 验证请求参数 - var req = new(OfflineProxyReq) + var req = new(ProxyReportOfflineReq) err = g.Validator.Validate(c, req) if err != nil { return err @@ -138,26 +165,33 @@ func OfflineProxy(c *fiber.Ctx) (err error) { // 下线转发服务 _, err = q.Proxy. - Where(q.Proxy.Name.Eq(req.Name)). + Where(q.Proxy.ID.Eq(req.Id)). UpdateSimple(q.Proxy.Status.Value(0)) if err != nil { return err } + // 下线所有相关的边缘节点 + _, err = q.Edge. + Where(q.Edge.ProxyID.Eq(req.Id)). + UpdateSimple(q.Edge.Status.Value(0)) + if err != nil { + return err + } + return nil } // endregion -// region AssignProxyFwdPort +// region 报告更新 -type AssignProxyFwdPortReq struct { - Proxy int32 `json:"proxy" validate:"required"` - Edge int32 `json:"edge" validate:"required"` - Port uint16 `json:"port" validate:"required"` +type ProxyReportUpdateReq struct { + Id int32 `json:"id" validate:"required"` + Edges []*ProxyEdge `json:"edges" validate:"required"` } -func AssignProxyFwdPort(c *fiber.Ctx) (err error) { +func ProxyReportUpdate(c *fiber.Ctx) (err error) { // 检查接口权限 _, err = auth2.NewProtect(c).Payload( auth2.PayloadInternalServer, @@ -167,19 +201,142 @@ func AssignProxyFwdPort(c *fiber.Ctx) (err error) { } // 验证请求参数 - var req = new(AssignProxyFwdPortReq) + var req = new(ProxyReportUpdateReq) err = g.Validator.Validate(c, req) if err != nil { return err } - // 更新边缘节点端口分配状态 - _, err = q.Edge. - Where(q.Edge.ID.Eq(req.Edge)). - UpdateSimple( - q.Edge.ProxyID.Value(req.Proxy), - q.Edge.ProxyPort.Value(int32(req.Port)), - ) + // 更新节点信息 + var idsActive = make([]int32, 0, len(req.Edges)) + var idsInactive = make([]int32, 0, len(req.Edges)) + var idsIspUnknown = make([]int32, 0, len(req.Edges)) + var idsIspTelecom = make([]int32, 0, len(req.Edges)) + var idsIspUnicom = make([]int32, 0, len(req.Edges)) + var idsIspMobile = make([]int32, 0, len(req.Edges)) + var otherEdges = make([]*ProxyEdge, 0, len(req.Edges)) + for _, edge := range req.Edges { + + // 跳过不方便批量操作的边缘节点 + if edge.Port != nil || edge.Prov != nil || edge.City != nil { + otherEdges = append(otherEdges, edge) + continue + } + + // 检查更新ISP + if edge.Isp != nil { + switch edge2.ISPFromStr(*edge.Isp) { + case edge2.IspUnknown: + idsIspUnknown = append(idsIspUnknown, edge.Id) + case edge2.IspChinaTelecom: + idsIspTelecom = append(idsIspTelecom, edge.Id) + case edge2.IspChinaUnicom: + idsIspUnicom = append(idsIspUnicom, edge.Id) + case edge2.IspChinaMobile: + idsIspMobile = append(idsIspMobile, edge.Id) + } + } + + // 检查更新状态 + if edge.Status != nil { + if *edge.Status == 1 { + idsActive = append(idsActive, edge.Id) + } else { + idsInactive = append(idsInactive, edge.Id) + } + } + } + + slog.Debug("更新边缘节点信息", + "active", len(idsActive), + "inactive", len(idsInactive), + "isp_unknown", len(idsIspUnknown), + "isp_china_telecom", len(idsIspTelecom), + "isp_china_unicom", len(idsIspUnicom), + "isp_china_mobile", len(idsIspMobile), + "other_edges", len(otherEdges), + ) + + err = q.Q.Transaction(func(q *q.Query) error { + // 更新边缘节点状态 + if len(idsActive) > 0 { + _, err = q.Edge.Debug(). + Where(q.Edge.ID.In(idsActive...)). + UpdateSimple(q.Edge.Status.Value(1)) + if err != nil { + return err + } + } + + if len(idsInactive) > 0 { + _, err = q.Edge.Debug(). + Where(q.Edge.ID.In(idsInactive...)). + UpdateSimple(q.Edge.Status.Value(0)) + if err != nil { + return err + } + } + + // 更新边缘节点ISP + if len(idsIspUnknown) > 0 { + _, err = q.Edge.Debug(). + Where(q.Edge.ID.In(idsIspUnknown...)). + UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspUnknown))) + if err != nil { + return err + } + } + + if len(idsIspTelecom) > 0 { + _, err = q.Edge.Debug(). + Where(q.Edge.ID.In(idsIspTelecom...)). + UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaTelecom))) + if err != nil { + return err + } + } + + if len(idsIspUnicom) > 0 { + _, err = q.Edge.Debug(). + Where(q.Edge.ID.In(idsIspUnicom...)). + UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaUnicom))) + if err != nil { + return err + } + } + + if len(idsIspMobile) > 0 { + _, err = q.Edge.Debug(). + Where(q.Edge.ID.In(idsIspMobile...)). + UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaMobile))) + if err != nil { + return err + } + } + + // 更新其他边缘节点信息 + for _, edge := range otherEdges { + do := q.Edge.Debug().Where(q.Edge.ID.Eq(edge.Id)) + + var assigns = make([]field.AssignExpr, 0, 5) + if edge.Port != nil { + assigns = append(assigns, q.Edge.ProxyPort.Value(*edge.Port)) + } + if edge.Prov != nil { + assigns = append(assigns, q.Edge.Prov.Value(*edge.Prov)) + } + if edge.City != nil { + assigns = append(assigns, q.Edge.City.Value(*edge.City)) + } + + // 更新边缘节点 + _, err := do.UpdateSimple(assigns...) + if err != nil { + return fmt.Errorf("更新边缘节点 %d 失败: %w", edge.Id, err) + } + } + return nil + }) if err != nil { return err } @@ -196,3 +353,15 @@ type ProxyPermit struct { Username *string `json:"username"` Password *string `json:"password"` } + +type ProxyEdge struct { + Id int32 `json:"id"` + Host *string `json:"host,omitempty"` // 边缘节点地址 + Port *int32 `json:"port,omitempty"` // 边缘节点代理端口 + Prov *string `json:"prov,omitempty"` + City *string `json:"city,omitempty"` + Isp *string `json:"isp,omitempty"` + Status *int32 `json:"status,omitempty"` + Loss *int32 `json:"loss,omitempty"` // 丢包率 + Rtt *int32 `json:"latency,omitempty"` // 延迟 +} diff --git a/web/router.go b/web/router.go index 0cd8295..ec4bd0a 100644 --- a/web/router.go +++ b/web/router.go @@ -67,14 +67,13 @@ func ApplyRouters(app *fiber.App) { // 网关 proxy := api.Group("/proxy") - proxy.Post("/online", handlers.OnlineProxy) - proxy.Post("/offline", handlers.OfflineProxy) - proxy.Post("/assign", handlers.AssignProxyFwdPort) + proxy.Post("/online", handlers.ProxyReportOnline) + proxy.Post("/offline", handlers.ProxyReportOffline) + proxy.Post("/update", handlers.ProxyReportUpdate) // 节点 edge := api.Group("/edge") - edge.Post("/online", handlers.OnlineEdge) - edge.Post("/offline", handlers.OfflineEdge) + edge.Post("/assign", handlers.AssignEdge) edge.Post("/all", handlers.AllEdgesAvailable) // 临时