feat: 完整游戏运维功能
This commit is contained in:
@@ -86,6 +86,18 @@ func (store *MemoryLogBodyStore) Query(streamID string, afterSeq uint64, limit i
|
||||
return selected, nextSeq, nil
|
||||
}
|
||||
|
||||
func (store *MemoryLogBodyStore) LatestSeq(streamID string) (uint64, error) {
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
var latest uint64
|
||||
for _, entry := range store.entries[streamID] {
|
||||
if entry.Seq > latest {
|
||||
latest = entry.Seq
|
||||
}
|
||||
}
|
||||
return latest, nil
|
||||
}
|
||||
|
||||
type FileLogBodyStore struct {
|
||||
mu sync.Mutex
|
||||
rootDir string
|
||||
@@ -101,7 +113,7 @@ func NewFileLogBodyStore(rootDir string) (*FileLogBodyStore, error) {
|
||||
rootDir: rootDir,
|
||||
memory: NewMemoryLogBodyStore(),
|
||||
}
|
||||
if err := os.MkdirAll(rootDir, 0o755); err != nil {
|
||||
if err := os.MkdirAll(rootDir, 0o700); err != nil {
|
||||
return nil, fmt.Errorf("create log directory: %w", err)
|
||||
}
|
||||
if err := store.load(); err != nil {
|
||||
@@ -124,7 +136,7 @@ func (store *FileLogBodyStore) AppendBatch(streamID string, record domain.LogBat
|
||||
return store.memory.AppendBatch(streamID, record)
|
||||
}
|
||||
streamDir := store.streamDir(streamID)
|
||||
if err := os.MkdirAll(streamDir, 0o755); err != nil {
|
||||
if err := os.MkdirAll(streamDir, 0o700); err != nil {
|
||||
return fmt.Errorf("create log stream directory: %w", err)
|
||||
}
|
||||
segmentPath := store.segmentPath(streamID, record.FirstSeq)
|
||||
@@ -133,23 +145,15 @@ func (store *FileLogBodyStore) AppendBatch(streamID string, record domain.LogBat
|
||||
} else if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("stat log segment: %w", err)
|
||||
}
|
||||
tmpPath := segmentPath + ".tmp"
|
||||
file, err := os.OpenFile(tmpPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open log segment: %w", err)
|
||||
}
|
||||
encoder := json.NewEncoder(file)
|
||||
var body strings.Builder
|
||||
encoder := json.NewEncoder(&body)
|
||||
for _, entry := range record.Entries {
|
||||
if err := encoder.Encode(domain.CopyLogEntry(entry)); err != nil {
|
||||
_ = file.Close()
|
||||
return fmt.Errorf("write log segment: %w", err)
|
||||
}
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return fmt.Errorf("close log segment: %w", err)
|
||||
}
|
||||
if err := os.Rename(tmpPath, segmentPath); err != nil {
|
||||
return fmt.Errorf("replace log segment: %w", err)
|
||||
if err := writeAtomicFile(segmentPath, []byte(body.String()), 0o600); err != nil {
|
||||
return fmt.Errorf("persist log segment: %w", err)
|
||||
}
|
||||
return store.memory.AppendBatch(streamID, record)
|
||||
}
|
||||
@@ -162,6 +166,10 @@ func (store *FileLogBodyStore) Query(streamID string, afterSeq uint64, limit int
|
||||
return store.memory.Query(streamID, afterSeq, limit)
|
||||
}
|
||||
|
||||
func (store *FileLogBodyStore) LatestSeq(streamID string) (uint64, error) {
|
||||
return store.memory.LatestSeq(streamID)
|
||||
}
|
||||
|
||||
func (store *FileLogBodyStore) load() error {
|
||||
entries, err := os.ReadDir(store.rootDir)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user