Skip to content

Commit 2acee54

Browse files
committed
fix(graphstore): give users actionable paths when the ladybug provider is a stub
Before this, cloning the repo and running `go run ./cmd/umodel-server` without `-tags ladybug` gave: local.ladybug provider is disabled in this build with no hint about what to do next. The stub's Health, OpenWorkspace, EnsureSchema, and every other operation now all report: build with -tags ladybug to enable local.ladybug, or run with --graphstore file.memory for local development Two clear paths, one line — no need to dig through source or ask around. DefaultProviderType stays local.ladybug. file.memory is not the new default. The real ladybug provider (built with -tags ladybug) is completely unaffected. Zero changes to REST, CLI, MCP schema, SDK, Query, Web UI, or runtime storage.
1 parent 06f21b8 commit 2acee54

7 files changed

Lines changed: 43 additions & 2 deletions

File tree

cmd/README.en.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Entry Layer: process entry points.
1414

1515
`umodel-server` and `umodel-mcp` both support `--graphstore`:
1616

17+
When `--graphstore` is omitted, Go entrypoints use `local.ladybug`. Builds without `-tags ladybug` report clear startup guidance: build with the Ladybug tag, or pass `--graphstore file.memory` for local development.
18+
1719
| Provider | Description |
1820
|---|---|
1921
| `memory` | In-memory provider for fast local verification; data is lost on process exit. |

cmd/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Entry Layer — 二进制入口点。
1212

1313
`umodel-server``umodel-mcp` 都支持 `--graphstore`
1414

15+
未显式传入 `--graphstore` 时,Go 入口默认使用 `local.ladybug`。如果构建时没有 `-tags ladybug`,启动错误会提示两条路径:使用 Ladybug tag 构建,或在本地开发时传入 `--graphstore file.memory`
16+
1517
| Provider | 说明 |
1618
|---|---|
1719
| `memory` | 纯内存,适合本地快速验证,进程退出后数据丢失;通过纯 Go 引擎支持 Ladybug 兼容只读 Cypher。 |

cmd/umodel-mcp/main_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ func TestRunQuickStartPreloadsMCPWorkspace(t *testing.T) {
3030
}
3131
}
3232

33+
func TestRunDefaultLadybugUnavailableGuidesLocalDevelopment(t *testing.T) {
34+
var out bytes.Buffer
35+
var errOut bytes.Buffer
36+
37+
err := run([]string{"--manifest", "--data", t.TempDir()}, strings.NewReader(""), &out, &errOut)
38+
if err == nil {
39+
t.Fatal("expected default local.ladybug stub to be unavailable in no-ladybug build")
40+
}
41+
for _, want := range []string{"local.ladybug", "-tags ladybug", "--graphstore file.memory"} {
42+
if !strings.Contains(err.Error(), want) {
43+
t.Fatalf("expected %q in error %q", want, err.Error())
44+
}
45+
}
46+
}
47+
3348
func TestEncodeTOONCoversObjectsAndTables(t *testing.T) {
3449
got := encodeTOON(map[string]any{
3550
"workspace": "demo",

docs/en/graphstore-providers.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
UModel stores UModel elements, CMS 2.0 entities, and topology relations behind the `GraphStore` interface. Go entry binaries default to `local.ladybug` when `--graphstore` is omitted; select another provider with `--graphstore` on `umodel-server` or `umodel-mcp`.
66

7+
If a build omits the `ladybug` tag, the default `local.ladybug` provider reports an unavailable health status. Build with `-tags ladybug` to enable the real `local.ladybug` provider, or pass `--graphstore file.memory` for local development without Ladybug.
8+
79
```bash
810
go run ./cmd/umodel-server --addr :8080 --data data --graphstore file.memory
911
```

docs/zh/graphstore-providers.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ English: [GraphStore Providers](../en/graphstore-providers.md)
55
UModel 通过 `GraphStore` 接口保存和查询 UModel elements、CMS 2.0 实体以及拓扑关系。运行时通过 `--graphstore` 选择 provider。
66

77

8+
未显式传入 `--graphstore` 时,Go 入口默认使用 `local.ladybug`。如果构建时没有 `-tags ladybug`,该 provider 会报告不可用状态。使用 `-tags ladybug` 构建即可启用真实的 `local.ladybug` provider;本地开发且不使用 Ladybug 时请显式传入 `--graphstore file.memory`
9+
810
## Providers
911

1012
| Provider | 持久化 | 典型用途 |

internal/graphstore/provider/ladybug/provider_stub.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313

1414
type Provider struct{}
1515

16+
const noLadybugBuildGuidance = "build with -tags ladybug to enable local.ladybug, or run with --graphstore file.memory for local development"
17+
1618
func NewProvider(config graphstore.ProviderConfig) (*Provider, error) {
1719
return &Provider{}, nil
1820
}
@@ -64,11 +66,11 @@ func (p *Provider) Capabilities(ctx context.Context) (model.GraphStoreCapabiliti
6466
}
6567

6668
func (p *Provider) Health(ctx context.Context) (model.GraphStoreHealth, error) {
67-
return model.GraphStoreHealth{Provider: graphstore.ProviderTypeLadybug, Status: "unavailable", Message: "build with -tags ladybug to enable local.ladybug"}, nil
69+
return model.GraphStoreHealth{Provider: graphstore.ProviderTypeLadybug, Status: "unavailable", Message: noLadybugBuildGuidance}, nil
6870
}
6971

7072
func unavailable() error {
71-
return apperrors.New(apperrors.CodeProviderUnavailable, "local.ladybug provider is disabled in this build")
73+
return apperrors.New(apperrors.CodeProviderUnavailable, "local.ladybug provider is disabled in this build; "+noLadybugBuildGuidance)
7274
}
7375

7476
func ladybugCapabilities() model.GraphStoreCapabilities {

internal/graphstore/provider/ladybug/provider_stub_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package ladybug
44

55
import (
66
"context"
7+
"strings"
78
"testing"
89

910
"github.com/alibaba/UnifiedModel/internal/graphstore"
@@ -20,9 +21,13 @@ func TestStubProviderReportsUnavailable(t *testing.T) {
2021
ctx := context.Background()
2122
if health, err := provider.Health(ctx); err != nil || health.Status != "unavailable" || health.Provider != graphstore.ProviderTypeLadybug {
2223
t.Fatalf("health: %+v err=%v", health, err)
24+
} else {
25+
requireLadybugGuidance(t, health.Message)
2326
}
2427
if err := provider.OpenWorkspace(ctx, model.WorkspaceMetadata{ID: "demo"}); !apperrors.IsCode(err, apperrors.CodeProviderUnavailable) {
2528
t.Fatalf("expected provider unavailable, got %v", err)
29+
} else {
30+
requireLadybugGuidance(t, err.Error())
2631
}
2732
if capabilities, err := provider.Capabilities(ctx); err != nil || !capabilities.ControlledCypher || capabilities.MaxLimit == 0 {
2833
t.Fatalf("stub should expose intended local.ladybug capabilities for planning, got %+v err=%v", capabilities, err)
@@ -36,5 +41,16 @@ func TestStubProviderIsRegisteredButUnavailable(t *testing.T) {
3641
}
3742
if err := provider.EnsureSchema(context.Background(), "demo"); !apperrors.IsCode(err, apperrors.CodeProviderUnavailable) {
3843
t.Fatalf("expected registered stub provider to be unavailable, got %v", err)
44+
} else {
45+
requireLadybugGuidance(t, err.Error())
46+
}
47+
}
48+
49+
func requireLadybugGuidance(t *testing.T, message string) {
50+
t.Helper()
51+
for _, want := range []string{"-tags ladybug", "--graphstore file.memory"} {
52+
if !strings.Contains(message, want) {
53+
t.Fatalf("expected %q guidance in %q", want, message)
54+
}
3955
}
4056
}

0 commit comments

Comments
 (0)