Restore durable log ingest and typed plugin projections

This commit is contained in:
npc0-hue
2026-09-02 10:20:30 +08:00
parent 40ac46ba17
commit 6018d8f0fc
61 changed files with 809 additions and 3157 deletions
+28 -75
View File
@@ -92,45 +92,6 @@ func TestCoreServicePublishesLogEventsForAcceptedBatch(t *testing.T) {
}
}
func TestCoreServiceRelaysLiveBatchWithoutPersistingBody(t *testing.T) {
svc, sessionToken := newRegisteredLogIngestService(t)
createLogStreamFixture(t, svc)
subscription, err := svc.SubscribeLogEvents("server-1")
if err != nil {
t.Fatalf("subscribe log events: %v", err)
}
defer subscription.Close()
batch := validLogBatch(t, sessionToken, 1, 1)
batch.Entries[0].Timestamp = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
batch.Checksum, err = validator.LogEntriesChecksum(batch.Entries)
if err != nil {
t.Fatalf("checksum live batch: %v", err)
}
ack, err := svc.RelayLiveLogBatch(batch)
if err != nil || !ack.Accepted || ack.LatestSeq != 1 {
t.Fatalf("relay live batch: ack=%+v err=%v", ack, err)
}
query, err := svc.QueryLogStream(domain.LogStreamCursorQuery{LogStreamID: batch.LogStreamID, AfterSeq: 0, Limit: 10})
if err != nil {
t.Fatalf("query relayed log stream: %v", err)
}
if len(query.Entries) != 0 || query.LatestSeq != 1 {
t.Fatalf("live relay wrote a platform log body: %+v", query)
}
select {
case event := <-subscription.Events:
if !event.Live {
t.Fatalf("expected live relay event marker: %+v", event)
}
if event.LogEvent.Entry.Timestamp.Before(fixedTime) {
t.Fatalf("live relay kept stale source timestamp: %+v", event.LogEvent.Entry)
}
case <-time.After(time.Second):
t.Fatal("expected relayed live log event")
}
}
func TestCoreServicePersistsAndEnforcesImmutableProcessLogSessionMetadata(t *testing.T) {
svc, sessionToken := newRegisteredLogIngestService(t)
startedAt := time.Date(2026, 7, 3, 12, 30, 0, 0, time.UTC)
@@ -480,47 +441,14 @@ func TestCoreServiceAcceptsLegacyAutonomousJobLogStreamWithoutPlatformJob(t *tes
}
}
func TestCoreServiceAcceptsSessionMetadataOnLegacyAutonomousStreamID(t *testing.T) {
func TestCoreServiceRejectsSessionMetadataOnLegacyAutonomousStreamID(t *testing.T) {
svc, sessionToken := newRegisteredLogIngestService(t)
batch := validLogBatch(t, sessionToken, 1, 1)
batch.LogStreamID = jobLogStreamID("autonomous-bootstrap-start", "stdout")
batch.LogSessionID = "session-a"
batch.SessionStartedAt = time.Date(2026, 7, 3, 12, 30, 0, 0, time.UTC)
ack, err := svc.IngestLogBatch(batch)
if err != nil {
t.Fatalf("ingest session-scoped legacy autonomous stream: %v", err)
}
if !ack.Accepted || ack.LogStreamID != batch.LogStreamID || ack.LatestSeq != batch.LastSeq {
t.Fatalf("unexpected legacy autonomous session ack: %+v", ack)
}
stream, err := svc.GetLogStream(batch.LogStreamID)
if err != nil {
t.Fatalf("get session-scoped legacy autonomous stream: %v", err)
}
if stream.LogSessionID != batch.LogSessionID || !stream.SessionStartedAt.Equal(batch.SessionStartedAt) {
t.Fatalf("session metadata was not persisted: %+v", stream)
}
}
func TestCoreServiceAcceptsSessionMetadataOnLegacyRunStreamID(t *testing.T) {
svc, sessionToken := newRegisteredLogIngestService(t)
batch := validLogBatch(t, sessionToken, 1, 1)
batch.LogStreamID = runLogStreamID("run-local", "server-1", "stdout")
batch.LogSessionID = "session-a"
batch.SessionStartedAt = time.Date(2026, 7, 3, 12, 30, 0, 0, time.UTC)
ack, err := svc.IngestLogBatch(batch)
if err != nil {
t.Fatalf("ingest session-scoped legacy run stream: %v", err)
}
if !ack.Accepted || ack.LogStreamID != batch.LogStreamID || ack.LatestSeq != batch.LastSeq {
t.Fatalf("unexpected legacy run session ack: %+v", ack)
}
stream, err := svc.GetLogStream(batch.LogStreamID)
if err != nil {
t.Fatalf("get session-scoped legacy run stream: %v", err)
}
if stream.LogSessionID != batch.LogSessionID || !stream.SessionStartedAt.Equal(batch.SessionStartedAt) {
t.Fatalf("session metadata was not persisted: %+v", stream)
if _, err := svc.IngestLogBatch(batch); err == nil {
t.Fatal("expected session-scoped batch with legacy autonomous stream ID to be rejected")
}
}
@@ -601,6 +529,31 @@ func TestFileLogBodyStoreReloadsBatchesAndCursorEntries(t *testing.T) {
}
}
func TestFileLogBodyStoreReloadsVerbatimLongLogLine(t *testing.T) {
rootDir := filepath.Join(t.TempDir(), "logs")
store, err := NewFileLogBodyStore(rootDir)
if err != nil {
t.Fatalf("create file log store: %v", err)
}
line := strings.Repeat("log-output-", 16*1024)
entries := []domain.LogEntry{{Seq: 1, Timestamp: time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC), Line: line}}
checksum, err := validator.LogEntriesChecksum(entries)
if err != nil {
t.Fatalf("checksum: %v", err)
}
if err := store.AppendBatch("log-long", domain.LogBatchRecord{Checksum: checksum, FirstSeq: 1, LastSeq: 1, Entries: entries}); err != nil {
t.Fatalf("append long log batch: %v", err)
}
reloaded, err := NewFileLogBodyStore(rootDir)
if err != nil {
t.Fatalf("reload long log store: %v", err)
}
batch, exists, err := reloaded.GetBatch("log-long", 1)
if err != nil || !exists || len(batch.Entries) != 1 || batch.Entries[0].Line != line {
t.Fatalf("long log line changed after reload: batch=%+v exists=%t err=%v", batch, exists, err)
}
}
func newRegisteredLogIngestService(t *testing.T) (*CoreService, string) {
t.Helper()
svc := newTestCoreService()