All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 1m59s
Test / Hakurei (push) Successful in 3m20s
Test / Sandbox (race detector) (push) Successful in 4m26s
Test / Hpkg (push) Successful in 3m47s
Test / Hakurei (race detector) (push) Successful in 5m21s
Test / Flake checks (push) Successful in 1m35s
This helps indicate the exact origin and nature of the error. This eliminates generic WrapErr from container. Signed-off-by: Ophestra <cat@gensokyo.uk>
83 lines
1.6 KiB
Go
83 lines
1.6 KiB
Go
// Package app implements high-level hakurei container behaviour.
|
|
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
|
|
"hakurei.app/hst"
|
|
"hakurei.app/internal/app/state"
|
|
"hakurei.app/internal/sys"
|
|
)
|
|
|
|
func New(ctx context.Context, os sys.State) (*App, error) {
|
|
a := new(App)
|
|
a.sys = os
|
|
a.ctx = ctx
|
|
|
|
id := new(state.ID)
|
|
err := state.NewAppID(id)
|
|
a.id = newID(id)
|
|
|
|
return a, err
|
|
}
|
|
|
|
func MustNew(ctx context.Context, os sys.State) *App {
|
|
a, err := New(ctx, os)
|
|
if err != nil {
|
|
log.Fatalf("cannot create app: %v", err)
|
|
}
|
|
return a
|
|
}
|
|
|
|
type App struct {
|
|
outcome *Outcome
|
|
|
|
id *stringPair[state.ID]
|
|
sys sys.State
|
|
ctx context.Context
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// ID returns a copy of [state.ID] held by App.
|
|
func (a *App) ID() state.ID { a.mu.RLock(); defer a.mu.RUnlock(); return a.id.unwrap() }
|
|
|
|
func (a *App) String() string {
|
|
if a == nil {
|
|
return "(invalid app)"
|
|
}
|
|
|
|
a.mu.RLock()
|
|
defer a.mu.RUnlock()
|
|
|
|
if a.outcome != nil {
|
|
if a.outcome.user.uid == nil {
|
|
return fmt.Sprintf("(sealed app %s with invalid uid)", a.id)
|
|
}
|
|
return fmt.Sprintf("(sealed app %s as uid %s)", a.id, a.outcome.user.uid)
|
|
}
|
|
|
|
return fmt.Sprintf("(unsealed app %s)", a.id)
|
|
}
|
|
|
|
// Seal determines the [Outcome] of [hst.Config].
|
|
// Values stored in and referred to by [hst.Config] might be overwritten and must not be used again.
|
|
func (a *App) Seal(config *hst.Config) (*Outcome, error) {
|
|
a.mu.Lock()
|
|
defer a.mu.Unlock()
|
|
|
|
if a.outcome != nil {
|
|
panic("app sealed twice")
|
|
}
|
|
|
|
seal := new(Outcome)
|
|
seal.id = a.id
|
|
err := seal.finalise(a.ctx, a.sys, config)
|
|
if err == nil {
|
|
a.outcome = seal
|
|
}
|
|
return seal, err
|
|
}
|