aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/app/app.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-28 01:07:51 +0900
committerOphestra <cat@gensokyo.uk>2025-08-28 01:07:51 +0900
commitb14690aa77b3d5f86c4d1b1965675d6d82789e32 (patch)
tree5765f705fd69dae7a65a0666451ac71a729a6aa8 /internal/app/app.go
parentd0b6852cd7db2bb1214c3267719d3ac108c0a53e (diff)
internal/app: remove seal interface
This further cleans up the package for the restructure. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/app/app.go')
-rw-r--r--internal/app/app.go92
1 files changed, 69 insertions, 23 deletions
diff --git a/internal/app/app.go b/internal/app/app.go
index d59b145d..17b4103d 100644
--- a/internal/app/app.go
+++ b/internal/app/app.go
@@ -2,35 +2,81 @@
package app
import (
- "syscall"
- "time"
+ "context"
+ "fmt"
+ "log"
+ "sync"
+
+ "hakurei.app/hst"
+ "hakurei.app/internal/app/state"
+ "hakurei.app/internal/sys"
)
-type SealedApp interface {
- // Run commits sealed system setup and starts the app process.
- Run(rs *RunState) error
+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
}
-// RunState stores the outcome of a call to [SealedApp.Run].
-type RunState struct {
- // Time is the exact point in time where the process was created.
- // Location must be set to UTC.
- //
- // Time is nil if no process was ever created.
- Time *time.Time
- // RevertErr is stored by the deferred revert call.
- RevertErr error
- // WaitErr is the generic error value created by the standard library.
- WaitErr error
+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
+}
- syscall.WaitStatus
+type App struct {
+ outcome *Outcome
+
+ id *stringPair[state.ID]
+ sys sys.State
+ ctx context.Context
+ mu sync.RWMutex
}
-// SetStart stores the current time in [RunState] once.
-func (rs *RunState) SetStart() {
- if rs.Time != nil {
- panic("attempted to store time twice")
+// 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] as a [SealedApp].
+// 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
}
- now := time.Now().UTC()
- rs.Time = &now
+ return seal, err
}