feat: add durable client command spool

This commit is contained in:
2026-09-06 06:28:42 +00:00
parent 3e675aaabf
commit c348d6bb16
8 changed files with 986 additions and 1 deletions
+75
View File
@@ -0,0 +1,75 @@
package spool
import (
"errors"
"fmt"
"os"
"path/filepath"
"github.com/rvbox/rvbox/internal/domain"
)
func loadOrCreateIdentity(path string, generate func() (domain.UUID, error)) (domain.UUID, error) {
data, err := os.ReadFile(path)
if err == nil {
return parseIdentity(data)
}
if !errors.Is(err, os.ErrNotExist) {
return domain.UUID{}, fmt.Errorf("read client instance identity: %w", err)
}
identity, err := generate()
if err != nil {
return domain.UUID{}, fmt.Errorf("generate client instance identity: %w", err)
}
if err := writeIdentityAtomically(path, []byte(identity.String()+"\n")); err != nil {
return domain.UUID{}, err
}
return identity, nil
}
func parseIdentity(data []byte) (domain.UUID, error) {
if len(data) != 37 || data[36] != '\n' {
return domain.UUID{}, ErrIdentityCorrupt
}
identity, err := domain.ParseUUIDv7(string(data[:36]))
if err != nil {
return domain.UUID{}, fmt.Errorf("%w: %v", ErrIdentityCorrupt, err)
}
return identity, nil
}
func writeIdentityAtomically(path string, data []byte) (result error) {
directory := filepath.Dir(path)
temporary, err := os.CreateTemp(directory, ".client-instance-id-*")
if err != nil {
return fmt.Errorf("create client identity temporary file: %w", err)
}
temporaryPath := temporary.Name()
defer func() {
if result != nil {
_ = os.Remove(temporaryPath)
}
}()
if err := temporary.Chmod(0o600); err != nil {
_ = temporary.Close()
return fmt.Errorf("secure client identity temporary file: %w", err)
}
if _, err := temporary.Write(data); err != nil {
_ = temporary.Close()
return fmt.Errorf("write client identity: %w", err)
}
if err := temporary.Sync(); err != nil {
_ = temporary.Close()
return fmt.Errorf("sync client identity: %w", err)
}
if err := temporary.Close(); err != nil {
return fmt.Errorf("close client identity: %w", err)
}
if err := replaceIdentityFile(temporaryPath, path); err != nil {
return fmt.Errorf("install client identity: %w", err)
}
if err := syncDirectory(directory); err != nil {
return fmt.Errorf("sync client identity directory: %w", err)
}
return nil
}