diff --git a/changes/unreleased/Fixed-20251219-104159.yaml b/changes/unreleased/Fixed-20251219-104159.yaml new file mode 100644 index 00000000..8f4be86d --- /dev/null +++ b/changes/unreleased/Fixed-20251219-104159.yaml @@ -0,0 +1,3 @@ +kind: Fixed +body: Fixed task logs API to return a `last_entry_id` even if `after_entry_id` is the last entry. +time: 2025-12-19T10:41:59.153319-05:00 diff --git a/server/internal/task/service.go b/server/internal/task/service.go index da67bdaa..fe41d107 100644 --- a/server/internal/task/service.go +++ b/server/internal/task/service.go @@ -140,9 +140,17 @@ func (s *Service) GetTaskLog(ctx context.Context, databaseID string, taskID uuid log := &TaskLog{ DatabaseID: databaseID, TaskID: taskID, + Entries: make([]LogEntry, 0, len(stored)), } for i := len(stored) - 1; i >= 0; i-- { s := stored[i] + if s.EntryID == options.AfterEntryID { + // This range should be behave as if its exclusive, however we need + // to perform an inclusive get so that we're still able to return + // the last entry ID when there are no entries after AfterEntryID. + // Skipping this entry produces the expected behavior. + continue + } log.Entries = append(log.Entries, LogEntry{ Timestamp: s.Timestamp, Message: s.Message, diff --git a/server/internal/task/task_log_store.go b/server/internal/task/task_log_store.go index 1268aceb..bf0c423e 100644 --- a/server/internal/task/task_log_store.go +++ b/server/internal/task/task_log_store.go @@ -61,7 +61,10 @@ func (s *TaskLogEntryStore) GetAllByTaskID(databaseID string, taskID uuid.UUID, opOptions = append(opOptions, clientv3.WithLimit(int64(options.Limit))) } if options.AfterEntryID != uuid.Nil { - rangeStart = s.Key(databaseID, taskID, options.AfterEntryID) + "0" + // We intentionally treat this as inclusive so that we still return an + // entry when AfterEntryID is the last entry. Callers must ignore the + // entry with EntryID == AfterEntryID. + rangeStart = s.Key(databaseID, taskID, options.AfterEntryID) } opOptions = append( opOptions,