Files
decent-webui/internal/filesvc/store.go
jbergner baedff9e9d
All checks were successful
release-tag / release-image (push) Successful in 1m32s
Umstellung auf uuid
2025-09-27 21:42:32 +02:00

91 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package filesvc
import (
"context"
"crypto/rand"
"errors"
"fmt"
"time"
)
/*** Domain ***/
type ID = string
type File struct {
ID ID `json:"id"`
Name string `json:"name"`
// weitere Metadaten optional: Size, Hash, Owner, Tags, ...
UpdatedAt int64 `json:"updatedAt"` // UnixNano für LWW
Deleted bool `json:"deleted"` // Tombstone für Mesh-Delete
}
/*** Fehler ***/
var (
ErrNotFound = errors.New("file not found")
ErrBadInput = errors.New("bad input")
ErrConflict = errors.New("conflict")
ErrForbidden = errors.New("forbidden")
ErrTransient = errors.New("transient")
)
/*** Basis-API (lokal nutzbar) ***/
type Store interface {
// Lesen & Auflisten
Get(ctx context.Context, id ID) (File, error)
List(ctx context.Context, next ID, limit int) (items []File, nextOut ID, err error)
// Mutationen mit LWW-Semantik (UpdatedAt wird intern gesetzt, außer bei ApplyRemote)
Create(ctx context.Context, name string) (File, error)
Rename(ctx context.Context, id ID, newName string) (File, error)
Delete(ctx context.Context, id ID) (File, error)
}
/*** Mesh-Replikation ***/
type Snapshot struct {
Items []File `json:"items"`
}
type Replicable interface {
// Snapshot liefert den vollständigen aktuellen Stand (inkl. Tombstones).
Snapshot(ctx context.Context) (Snapshot, error)
// ApplyRemote wendet LWW an. next-ID wird dabei korrekt fortgeschrieben.
ApplyRemote(ctx context.Context, s Snapshot) error
}
/*** Events (optional) ***/
// ChangeEvent kann genutzt werden, um proaktive Mesh-Pushes zu triggern.
// Bei deiner Pull-basierten Anti-Entropy ist es optional.
type ChangeEvent struct {
At time.Time
Item File
}
// Watch gibt Änderungen aus; close(stop) beendet den Stream.
// Eine Noop-Implementierung ist erlaubt, wenn Pull-Sync genügt.
type Watchable interface {
Watch(stop <-chan struct{}) <-chan ChangeEvent
}
/*** Kombiniertes Interface ***/
type MeshStore interface {
Store
Replicable
Watchable // optional kann Noop sein
}
func NewUUIDv4() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", err
}
b[6] = (b[6] & 0x0f) | 0x40 // Version 4
b[8] = (b[8] & 0x3f) | 0x80 // Variant RFC4122
return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:16]), nil
}