5eef13b615
方案A:所有对象写入经 loopback 网关,持久计划/grant/intent/逐版本 receipt 与 attempt→grant delivery 落在治理 PG;scope 由 provider+endpoint+bucket 决定, 同一物理桶只允许一个写域。版本 append 不等于 CAS,未锚定计划在首笔业务写前拒绝。 本提交只含网关与其适配层接线、协议文档;生产独占、凭据切换与桶设置未改动。
45 lines
1.8 KiB
Go
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")
|
|
}
|
|
}
|