Reduce log ingest and SCUM page refresh pressure

This commit is contained in:
npc0-hue
2026-09-09 16:21:12 +08:00
parent e6e38b275a
commit 8c924b5928
7 changed files with 43 additions and 11 deletions
+4 -1
View File
@@ -41,6 +41,7 @@ type StoreSnapshot struct {
type runtimeSnapshot struct {
RunControlSessions []domain.RunControlSession `json:"runControlSessions"`
RunEndpoints []domain.RunEndpoint `json:"runEndpoints"`
LogStreams []domain.LogStream `json:"logStreams"`
}
type FileStore struct {
@@ -131,7 +132,7 @@ func (store *FileStore) RunUpdateJobs() RunUpdateJobRepository {
}
func (store *FileStore) LogStreams() LogStreamRepository {
return &persistentRepository[domain.LogStream, domain.LogStreamFilter]{repository: store.MemoryStore.logStreams, persist: store.persist}
return &persistentRepository[domain.LogStream, domain.LogStreamFilter]{repository: store.MemoryStore.logStreams, persist: store.persistRuntime}
}
func (store *FileStore) MetricSamples() MetricSampleRepository {
@@ -318,6 +319,7 @@ func (store *FileStore) runtimeSnapshot() runtimeSnapshot {
return runtimeSnapshot{
RunControlSessions: snapshotRepository(store.MemoryStore.runSessions),
RunEndpoints: snapshotRepository(store.MemoryStore.runEndpoints),
LogStreams: snapshotRepository(store.MemoryStore.logStreams),
}
}
@@ -350,6 +352,7 @@ func (store *FileStore) loadSnapshot(snapshot StoreSnapshot) {
func (store *FileStore) loadRuntimeSnapshot(snapshot runtimeSnapshot) {
loadRepository(store.MemoryStore.runSessions, snapshot.RunControlSessions)
loadRepository(store.MemoryStore.runEndpoints, snapshot.RunEndpoints)
loadRepository(store.MemoryStore.logStreams, snapshot.LogStreams)
}
type mutableRepository[T any, F any] interface {
+3 -1
View File
@@ -114,7 +114,7 @@ func (store *MySQLStore) RunUpdateJobs() RunUpdateJobRepository {
}
func (store *MySQLStore) LogStreams() LogStreamRepository {
return &persistentRepository[domain.LogStream, domain.LogStreamFilter]{repository: store.MemoryStore.logStreams, persist: store.persist}
return &persistentRepository[domain.LogStream, domain.LogStreamFilter]{repository: store.MemoryStore.logStreams, persist: store.persistRuntime}
}
func (store *MySQLStore) MetricSamples() MetricSampleRepository {
@@ -280,6 +280,7 @@ func (store *MySQLStore) runtimeSnapshot() runtimeSnapshot {
return runtimeSnapshot{
RunControlSessions: snapshotRepository(store.MemoryStore.runSessions),
RunEndpoints: snapshotRepository(store.MemoryStore.runEndpoints),
LogStreams: snapshotRepository(store.MemoryStore.logStreams),
}
}
@@ -312,4 +313,5 @@ func (store *MySQLStore) loadSnapshot(snapshot StoreSnapshot) {
func (store *MySQLStore) loadRuntimeSnapshot(snapshot runtimeSnapshot) {
loadRepository(store.MemoryStore.runSessions, snapshot.RunControlSessions)
loadRepository(store.MemoryStore.runEndpoints, snapshot.RunEndpoints)
loadRepository(store.MemoryStore.logStreams, snapshot.LogStreams)
}
+8 -1
View File
@@ -330,6 +330,10 @@ func TestFileStorePersistsRunRuntimeStateSeparately(t *testing.T) {
if err := store.RunControlSessions().Create(session); err != nil {
t.Fatalf("create runtime session: %v", err)
}
stream := domain.LogStream{ID: "run.run-runtime.server-1.scum.console.stdout", ServerInstanceID: "server-1", Source: domain.LogStreamSourceProcess, StreamKey: "scum.console.stdout", LatestSeq: 42, StorageBackend: domain.LogStorageBackendLocalSegments, RetentionPolicy: "default", CreatedAt: stamp, UpdatedAt: stamp}
if err := store.LogStreams().Create(stream); err != nil {
t.Fatalf("create runtime log stream: %v", err)
}
mainAfter, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read main snapshot after runtime update: %v", err)
@@ -341,7 +345,7 @@ func TestFileStorePersistsRunRuntimeStateSeparately(t *testing.T) {
if err != nil {
t.Fatalf("read runtime snapshot: %v", err)
}
if !strings.Contains(string(runtimePayload), endpoint.ID) || strings.Contains(string(runtimePayload), session.SessionToken) {
if !strings.Contains(string(runtimePayload), endpoint.ID) || !strings.Contains(string(runtimePayload), stream.ID) || strings.Contains(string(runtimePayload), session.SessionToken) {
t.Fatalf("unexpected runtime snapshot payload: %s", runtimePayload)
}
@@ -355,6 +359,9 @@ func TestFileStorePersistsRunRuntimeStateSeparately(t *testing.T) {
if got, err := reloaded.RunControlSessions().Get(endpoint.ID); err != nil || got.SessionTokenHash != session.SessionTokenHash || got.UsedNonces[0] != "nonce-1" {
t.Fatalf("runtime session did not reload: %+v err=%v", got, err)
}
if got, err := reloaded.LogStreams().Get(stream.ID); err != nil || got.LatestSeq != stream.LatestSeq {
t.Fatalf("runtime log stream did not reload: %+v err=%v", got, err)
}
}
func TestFileStorePersistsPluginOperationsStateAcrossRestart(t *testing.T) {
+14 -4
View File
@@ -1619,12 +1619,22 @@ func (svc *CoreService) GetRunEndpoint(id string) (domain.RunEndpoint, error) {
}
func (svc *CoreService) ListRunEndpoints(filter domain.RunEndpointFilter) ([]domain.RunEndpoint, error) {
svc.controlMu.Lock()
defer svc.controlMu.Unlock()
if err := svc.sweepExpiredRunRegistrationsLocked(svc.now()); err != nil {
endpoints, err := svc.store.RunEndpoints().List(domain.RunEndpointFilter{})
if err != nil {
return nil, err
}
return svc.store.RunEndpoints().List(filter)
stamp := svc.now()
items := make([]domain.RunEndpoint, 0, len(endpoints))
for _, endpoint := range endpoints {
if !runEndpointRegistrationCurrentAt(endpoint, stamp) && (endpoint.Status == domain.RunEndpointStatusOnline || endpoint.Status == domain.RunEndpointStatusDegraded) {
endpoint.Status = domain.RunEndpointStatusOffline
}
if filter.Status != "" && endpoint.Status != filter.Status {
continue
}
items = append(items, domain.CopyRunEndpoint(endpoint))
}
return items, nil
}
func (svc *CoreService) CreateServerInstance(instance domain.ServerInstance) (domain.ServerInstance, error) {