Files
ayatori/internal/database/domain/instance/readiness.go
T
panxiao81 23a2d81b50
Verify / test (pull_request) Successful in 11m8s
Verify / lint (pull_request) Successful in 19m34s
Verify / database-integration (pull_request) Successful in 21m51s
refactor: 移除 Database registry 与 Instance 初始化依赖
2026-09-24 16:32:30 +00:00

163 lines
4.5 KiB
Go

/*
Copyright 2026.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package instance
import "errors"
// Failure 只表示安全类别;驱动错误、凭据和 Condition 文案留在应用边界。
type Failure uint8
const (
NoFailure Failure = iota
ObservationIncomplete
DependencyUnavailable
AuthenticationFailed
InsufficientPrivileges
)
// CheckResult 的零值表示未观察,不能视为成功。
type CheckResult uint8
const (
CheckUnobserved CheckResult = iota
CheckPassed
CheckUnavailable
CheckAuthenticationFailed
CheckInsufficientPrivileges
)
// ManagementChecks 分别记录所需能力;SQL 探测和同轮次关联由 adapter/application 保证。
// Extensions 不代表任意扩展均可安装;具体请求仍需支持检查、执行及回读。
type ManagementChecks struct {
Connection CheckResult
Metadata CheckResult
Roles CheckResult
Databases CheckResult
Grants CheckResult
Extensions CheckResult
}
func (c ManagementChecks) failure() Failure {
for _, check := range []CheckResult{c.Connection, c.Metadata, c.Roles, c.Databases, c.Grants, c.Extensions} {
switch check {
case CheckPassed:
case CheckUnavailable:
return DependencyUnavailable
case CheckAuthenticationFailed:
return AuthenticationFailed
case CheckInsufficientPrivileges:
return InsufficientPrivileges
default:
return ObservationIncomplete
}
}
return NoFailure
}
// CapabilityObservation 是值对象,不包含连接、凭据或可变集合。
type CapabilityObservation struct {
target ObservationTarget
version string
checks ManagementChecks
}
func NewCapabilityObservation(
target ObservationTarget,
version string,
checks ManagementChecks,
) (CapabilityObservation, error) {
if err := target.Validate(); err != nil {
return CapabilityObservation{}, err
}
return CapabilityObservation{target: target, version: version, checks: checks}, nil
}
func (o CapabilityObservation) managementFailure() Failure {
if failure := o.checks.failure(); failure != NoFailure {
return failure
}
if o.version == "" {
return ObservationIncomplete
}
return NoFailure
}
func (i *Instance) acceptObservation(o CapabilityObservation, phase Phase) error {
if !i.target.Matches(o.target) {
return errors.New("capability observation target does not match instance")
}
if i.deleting || i.snapshot.Phase != phase {
return errors.New("capability observation is not allowed in current lifecycle")
}
return nil
}
func (i *Instance) fail(failure Failure) {
i.evidence = nil
i.extensions = ExtensionSupport{}
i.snapshot.Readiness = NotReady
i.snapshot.Failure = failure
i.snapshot.ObservedRevision = i.target.Revision().Value()
}
// AssessManagement 根据本轮完整能力观察完成验证,不执行外部写入。
func (i *Instance) AssessManagement(o CapabilityObservation) error {
if err := i.acceptObservation(o, PhaseValidating); err != nil {
return err
}
i.assessComplete(o)
return nil
}
func (i *Instance) assessComplete(o CapabilityObservation) {
if failure := o.managementFailure(); failure != NoFailure {
i.fail(failure)
return
}
i.snapshot = Snapshot{
Phase: PhaseReady,
ObservedRevision: i.target.Revision().Value(),
Readiness: Ready,
ReportedVersion: o.version,
}
i.evidence = &o
}
// AssessReadiness 每轮接收完整事实,失败立即撤销本轮供应能力。
func (i *Instance) AssessReadiness(o CapabilityObservation) error {
if err := i.acceptObservation(o, PhaseReady); err != nil {
return err
}
if i.snapshot.ObservedRevision != i.target.Revision().Value() {
return i.BeginValidation()
}
if o.managementFailure() != NoFailure {
i.snapshot.Phase = PhaseValidating
}
i.assessComplete(o)
return nil
}
// RequireProvisioningReady 仅检查 Instance 前置条件,不授予 Tenant 所有权或外部写入许可。
func (i *Instance) RequireProvisioningReady() error {
if i.deleting || i.evidence == nil || i.snapshot.Phase != PhaseReady || i.snapshot.Readiness != Ready ||
i.snapshot.ObservedRevision != i.target.Revision().Value() {
return errors.New("instance is not ready for provisioning")
}
return nil
}