Files
knowledge-governance/internal/objectgateway/persistence_integration_test.go
姚章浩 5eef13b615 feat(object-gateway): 统一对象写网关与不可变治理日志
方案A:所有对象写入经 loopback 网关,持久计划/grant/intent/逐版本 receipt 与
attempt→grant delivery 落在治理 PG;scope 由 provider+endpoint+bucket 决定,
同一物理桶只允许一个写域。版本 append 不等于 CAS,未锚定计划在首笔业务写前拒绝。

本提交只含网关与其适配层接线、协议文档;生产独占、凭据切换与桶设置未改动。
2026-11-01 11:35:05 +08:00

45 lines
1.8 KiB
Go

package objectgateway_test
import (
"errors"
g "knowledge-governance/internal/objectgateway"
"testing"
)
func TestGatewayIntentCommitFailureNeverSends(t *testing.T) {
ctx, pool, real := fixture(t)
backend := &stoppedBeforeSend{Backend: real}
grant := g.Grant{Epoch: 1, Owner: g.Digest([]byte(t.Name())), Plan: g.Digest([]byte("plan"))}
gateway := &g.Gateway{Pool: pool, Scope: real.Bucket, Backend: backend, Isolation: verifiedFixture{}, MaxBytes: 1 << 20}
if e := gateway.InstallPlan(ctx, planFor(grant, request(t.Name(), grant))); e != nil {
t.Fatal(e)
}
if e := gateway.Advance(ctx, 0, grant); e != nil {
t.Fatal(e)
}
// Deferred failure fires on COMMIT, not on INSERT. This exercises the uncertain
// persistence boundary while confirming no provider request is sent.
_, e := pool.Exec(ctx, `CREATE FUNCTION kg_gateway_fixture_commit_failure() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'injected durable commit failure'; END $$;
CREATE CONSTRAINT TRIGGER kg_gateway_fixture_commit_failure AFTER INSERT ON kg_object_gateway_intents DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION kg_gateway_fixture_commit_failure()`)
if e != nil {
t.Fatal(e)
}
t.Cleanup(func() {
_, e := pool.Exec(ctx, `DROP TRIGGER kg_gateway_fixture_commit_failure ON kg_object_gateway_intents; DROP FUNCTION kg_gateway_fixture_commit_failure()`)
if e != nil {
t.Error(e)
}
})
req := request(t.Name(), grant)
if _, e = gateway.Execute(ctx, req, []byte("gateway fixture "+t.Name())); !errors.Is(e, g.ErrPersistence) {
t.Fatal("commit error not propagated", e)
}
if backend.calls != 0 {
t.Fatal("object request after failed journal commit")
}
var n int
if pool.QueryRow(ctx, "SELECT count(*) FROM kg_object_gateway_intents WHERE scope=$1", gateway.Scope).Scan(&n) != nil || n != 0 {
t.Fatal("failed transaction left intent")
}
}