Skip to content

Commit 7baae29

Browse files
authored
feat: enhance plugin host service capabilities (#68)
1 parent d6fe97d commit 7baae29

360 files changed

Lines changed: 12771 additions & 7359 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/rules/dev-tooling.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323

2424
- `hack/tools/linactl/`下承载具体`make``linactl`命令实现的源码文件,必须按对应命令名称命名为`command_<command>.go`
2525
- `<command>`保持命令的点分段语义。例如`make dev`对应`command_dev.go``make build`对应`command_build.go``make env.setup`对应`command_env.setup.go`
26-
- 同一文件只应承载该命令的主实现及其紧密私有辅助逻辑。
27-
- 跨命令复用能力应提取到职责明确的非命令文件或内部组件。
28-
- 禁止继续把多个无直接归属的命令混放到`command_ops.go`这类兜底文件中。
2926
- 若命令名与 Go 工具链文件后缀规则冲突,必须使用明确的命令专属后缀并记录原因,例如`test`命令使用`command_testcmd.go``wasm`命令使用`command_wasmcmd.go`
3027

3128
## linactl 子组件组织要求

.agents/rules/plugin.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ apps/lina-plugins/<plugin-id>/
1616
├── Makefile # 插件make指令入口
1717
├── backend/
1818
│ ├── api/ # API DTO与路由契约
19-
│ ├── hack/
20-
│ │ └── config.yaml # make dao等插件开发配置
2119
│ ├── internal/
2220
│ │ ├── controller/ # HTTP控制器
2321
│ │ ├── service/ # 业务服务层
@@ -28,6 +26,7 @@ apps/lina-plugins/<plugin-id>/
2826
│ ├── pages/ # 插件页面
2927
│ └── slots/ # 插槽页面,可选
3028
├── hack/ # 插件自身脚本和工具
29+
│ ├── config.yaml # 插件开发期工具配置入口,包含代码生成、自定义构建等配置
3130
│ └── tests/ # 插件测试内容
3231
│ └── e2e/ # 插件 e2e 测试内容
3332
├── manifest/
@@ -57,6 +56,8 @@ apps/lina-plugins/<plugin-id>/
5756
- 插件多语言资源放在`manifest/i18n/<locale>/`,API 文档翻译资源放在`manifest/i18n/<locale>/apidoc/`
5857
- 插件 SQL 必须遵守`.agents/rules/database.md`
5958
- 插件 i18n 资源必须遵守`.agents/rules/i18n.md`
59+
- 插件开发期工具配置统一维护在插件根`hack/config.yaml`,包括代码生成、自定义构建等插件本地工具配置。
60+
- 插件自定义构建指令统一放在插件根`hack/config.yaml``build.commands`下,由仓库根`make build``linactl build`读取执行。
6061

6162
## 插件后端同构开发结构要求
6263

@@ -69,7 +70,7 @@ apps/lina-plugins/<plugin-id>/
6970

7071
## 插件数据库访问要求
7172

72-
- 插件的后端代码生成工具配置维护在`backend/hack/config.yaml`
73+
- 涉及数据库访问的插件应在插件根`hack/config.yaml`中维护`gfcli.gen.dao`等代码生成工具配置,GoFrame 生成工作目录仍为插件`backend/`
7374
- 禁止插件重新依赖宿主的`dao/do/entity`生成工件。
7475
- 动态插件涉及宿主数据访问时,必须通过`plugin.yaml``hostServices`资源边界和宿主授权的 host service 协议。
7576

.agents/skills/lina-perf-audit/scripts/setup-audit-env.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ BACKUP_FILE="$RUN_DIR/logger-backup.json"
307307
TOKEN_FILE="$RUN_DIR/token.txt"
308308
TRACE_CHECK_FILE="$RUN_DIR/trace-id-check.txt"
309309
BACKEND_BINARY="temp/bin/lina-perf-audit-backend"
310-
BACKEND_PID_FILE="temp/pids/backend.pid"
310+
BACKEND_PID_FILE="temp/pids/lina-core.pid"
311311
LOGGER_PATH="${RUN_DIR}/"
312312
LOGGER_FILE="server.log"
313313
HEALTH_URL="http://127.0.0.1:9120/api/v1/health"

.github/workflows/reusable-make-command-smoke.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,11 @@ jobs:
146146
147147
make -C "$smoke_root" dev plugins=0 BACKEND_PORT="$backend_port" FRONTEND_PORT="$frontend_port"
148148
make -C "$smoke_root" status BACKEND_PORT="$backend_port" FRONTEND_PORT="$frontend_port" | tee "$RUNNER_TEMP/dev-status.txt"
149-
grep -q "Backend" "$RUNNER_TEMP/dev-status.txt"
150-
grep -q "Frontend" "$RUNNER_TEMP/dev-status.txt"
149+
grep -q "Lina Core" "$RUNNER_TEMP/dev-status.txt"
150+
grep -q "Lina Vben" "$RUNNER_TEMP/dev-status.txt"
151151
make -C "$smoke_root" stop BACKEND_PORT="$backend_port" FRONTEND_PORT="$frontend_port"
152-
test ! -f "$smoke_root/temp/pids/backend.pid"
153-
test ! -f "$smoke_root/temp/pids/frontend.pid"
152+
test ! -f "$smoke_root/temp/pids/lina-core.pid"
153+
test ! -f "$smoke_root/temp/pids/lina-vben.pid"
154154
155155
# Verify wasm through a real isolated dynamic plugin build and artifact assertion.
156156
# 通过真实隔离动态插件构建和产物断言验证 wasm 指令。

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ BACKEND_DIR := apps/lina-core
55
FRONTEND_DIR := apps/lina-vben
66
TEMP_DIR := temp
77
PID_DIR := $(TEMP_DIR)/pids
8-
BACKEND_PID := $(PID_DIR)/backend.pid
9-
FRONTEND_PID := $(PID_DIR)/frontend.pid
8+
BACKEND_PID := $(PID_DIR)/lina-core.pid
9+
FRONTEND_PID := $(PID_DIR)/lina-vben.pid
1010
BACKEND_PORT := 9120
1111
FRONTEND_PORT := 5666
1212
BACKEND_LOG := $(TEMP_DIR)/lina-core.log

apps/lina-core/api/usermsg/v1/usermsg_get.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type GetRes struct {
2020
TypeLabel string `json:"typeLabel" dc:"Localized category label resolved by the host according to the request locale" eg:"Notice"`
2121
TypeColor string `json:"typeColor" dc:"Localized category tag color resolved by the host so the inbox preview can render badges without hardcoding category-specific colors" eg:"blue"`
2222
SourceType SourceType `json:"sourceType" dc:"Source type: notice=notification announcement plugin=dynamic plugin system=system" eg:"notice"`
23-
SourceId int64 `json:"sourceId" dc:"Source ID" eg:"1001"`
23+
SourceId string `json:"sourceId" dc:"Original sender-declared source record ID" eg:"notice-1001"`
2424
Content string `json:"content" dc:"Can be used directly to preview rendered message content" eg:"<p>The system will be undergoing maintenance tonight</p>"`
2525
CreatedByName string `json:"createdByName" dc:"Sender username" eg:"admin"`
2626
CreatedAt *int64 `json:"createdAt" dc:"Message creation time as Unix timestamp in milliseconds" eg:"1776752400000"`

apps/lina-core/api/usermsg/v1/usermsg_list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type MessageItem struct {
4444
TypeLabel string `json:"typeLabel" dc:"Localized category label resolved by the host according to the request locale" eg:"Notice"`
4545
TypeColor string `json:"typeColor" dc:"Localized category tag color resolved by the host so the inbox UI can render badges without hardcoding category-specific colors" eg:"blue"`
4646
SourceType SourceType `json:"sourceType" dc:"Source type: notice=notification announcement plugin=dynamic plugin system=system" eg:"notice"`
47-
SourceId int64 `json:"sourceId" dc:"Source ID, this field is used for the current notification announcement preview" eg:"1001"`
47+
SourceId string `json:"sourceId" dc:"Original sender-declared source record ID" eg:"notice-1001"`
4848
IsRead statusflag.ReadState `json:"isRead" dc:"Whether it has been read: 0=unread 1=read" eg:"0"`
4949
ReadAt *int64 `json:"readAt" dc:"Read time as Unix timestamp in milliseconds, empty when unread" eg:"1776240000000"`
5050
CreatedAt *int64 `json:"createdAt" dc:"Message creation time as Unix timestamp in milliseconds" eg:"1776238200000"`

apps/lina-core/internal/cmd/internal/httpstartup/http.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ func Run(ctx context.Context) error {
5151
dispatchSystemStartedHook(ctx, runtime.pluginSvc)
5252

5353
server.Run()
54-
return shutdownHTTPRuntime(ctx, runtime, configSvc)
54+
return shutdownHTTPRuntime(ctx, runtime, server)
5555
}

apps/lina-core/internal/cmd/internal/httpstartup/http_runtime.go

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,6 @@ func configureHTTPServer(
145145
return err
146146
}
147147

148-
shutdownCfg := configSvc.GetShutdown(ctx)
149-
if shutdownCfg != nil && shutdownCfg.Timeout > 0 {
150-
timeoutSeconds := durationSeconds(shutdownCfg.Timeout)
151-
server.SetGracefulTimeout(timeoutSeconds)
152-
server.SetGracefulShutdownTimeout(timeoutSeconds)
153-
}
154-
155148
// Request-size limits are enforced by host middleware so multipart uploads
156149
// can follow the runtime-effective sys.upload.maxSize value per request
157150
// instead of being clipped by GoFrame's static 8MB default at server entry.
@@ -262,13 +255,8 @@ func newHTTPRuntime(ctx context.Context, configSvc config.Service) (*httpRuntime
262255
closeHTTPCoordinationAfterInitError(ctx, coordinationSvc)
263256
return nil, err
264257
}
265-
pluginStorageCfg := configSvc.GetPluginStorage(ctx)
266-
storageRuntime := pluginsvc.NewStorageProviderRuntime(configSvc, pluginRuntime)
267-
localStorageProvider := pluginsvc.NewLocalStorageProvider(
268-
configSvc.GetPluginDynamicStoragePath(ctx),
269-
clusterSvc != nil && clusterSvc.IsEnabled(),
270-
pluginStorageCfg.AllowLocalProviderInCluster,
271-
)
258+
storageRuntime := pluginsvc.NewStorageProviderRuntime(pluginRuntime)
259+
localStorageProvider := pluginsvc.NewLocalStorageProvider(configSvc.GetPluginDynamicStoragePath(ctx))
272260
capabilities, err := pluginsvc.NewHostServices(
273261
apiDocSvc,
274262
authSvc,
@@ -590,9 +578,9 @@ func logHTTPStartupSummary(ctx context.Context, collector *startupstats.Collecto
590578

591579
// shutdownHTTPRuntime stops non-HTTP runtime components after GoFrame Server.Run
592580
// has handled signal listening and HTTP graceful shutdown.
593-
func shutdownHTTPRuntime(ctx context.Context, runtime *httpRuntime, configSvc config.Service) error {
581+
func shutdownHTTPRuntime(ctx context.Context, runtime *httpRuntime, server *ghttp.Server) error {
594582
shutdownBaseCtx := context.WithoutCancel(ctx)
595-
shutdownTimeout := resolveShutdownTimeout(shutdownBaseCtx, configSvc)
583+
shutdownTimeout := resolveRuntimeShutdownTimeout(server)
596584
logger.Infof(shutdownBaseCtx, "runtime shutdown requested, timeout=%s", shutdownTimeout)
597585

598586
shutdownCtx, cancel := context.WithTimeout(shutdownBaseCtx, shutdownTimeout)
@@ -661,24 +649,11 @@ func shutdownStep(ctx context.Context, name string, fn func(context.Context) err
661649
}
662650
}
663651

664-
// resolveShutdownTimeout returns the configured full runtime-shutdown budget.
665-
func resolveShutdownTimeout(ctx context.Context, configSvc config.Service) time.Duration {
666-
if configSvc == nil {
667-
return 30 * time.Second
668-
}
669-
cfg := configSvc.GetShutdown(ctx)
670-
if cfg == nil || cfg.Timeout <= 0 {
671-
return 30 * time.Second
672-
}
673-
return cfg.Timeout
674-
}
675-
676-
// durationSeconds converts a validated duration into whole seconds for
677-
// GoFrame server configuration.
678-
func durationSeconds(value time.Duration) int {
679-
seconds := int(value / time.Second)
680-
if seconds < 1 {
681-
return 1
652+
// resolveRuntimeShutdownTimeout returns the host-owned cleanup budget from the
653+
// GoFrame HTTP server graceful shutdown configuration already active at startup.
654+
func resolveRuntimeShutdownTimeout(server *ghttp.Server) time.Duration {
655+
if server == nil {
656+
return time.Duration(ghttp.NewConfig().GracefulShutdownTimeout) * time.Second
682657
}
683-
return seconds
658+
return time.Duration(server.GetGracefulShutdownTimeout()) * time.Second
684659
}

apps/lina-core/internal/cmd/internal/httpstartup/http_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,8 +1038,8 @@ func newRouteBindingTestRuntime(ctx context.Context) *httpRuntime {
10381038
notifySvc,
10391039
kvCacheSvc,
10401040
hostLockSvc,
1041-
pluginsvc.NewStorageProviderRuntime(configSvc, pluginRuntime),
1042-
pluginsvc.NewLocalStorageProvider(configSvc.GetPluginDynamicStoragePath(ctx), false, false),
1041+
pluginsvc.NewStorageProviderRuntime(pluginRuntime),
1042+
pluginsvc.NewLocalStorageProvider(configSvc.GetPluginDynamicStoragePath(ctx)),
10431043
)
10441044
if err != nil {
10451045
panic(err)

0 commit comments

Comments
 (0)