From cb3b507ed54895ef5fdbde0828a4e14bdd0938b5 Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 6 Aug 2026 01:31:19 +0400 Subject: [PATCH] ipc: one row mapper for the store adapter's list reads (V-575) Eleven methods repeated the same body: run mapErr over the store's error, allocate a slice of the wire type, convert row by row. mapRows holds it, and each method is now the read plus the conversion it uses. ListProposedRoutines had a conditional copy of ReminderID, which was a nil pointer assigned over a nil pointer whenever it did not fire. It is unconditional now and the result is the same. --- internal/ipc/storeapi.go | 139 ++++++++++----------------------------- 1 file changed, 34 insertions(+), 105 deletions(-) diff --git a/internal/ipc/storeapi.go b/internal/ipc/storeapi.go index 6158d36..21fd7da 100644 --- a/internal/ipc/storeapi.go +++ b/internal/ipc/storeapi.go @@ -77,18 +77,24 @@ func (a *storeAPI) MarkReminder(ctx context.Context, id int64, status string) er return mapErr(a.s.MarkReminder(ctx, id, status)) } -func (a *storeAPI) ListReminders(ctx context.Context, n int) ([]Reminder, error) { - rs, err := a.s.ListReminders(ctx, n) +// mapRows carries a store read's error through mapErr and converts the rows to +// their wire shape. Every list method here is that one shape. +func mapRows[S any, W any](rows []S, err error, conv func(S) W) ([]W, error) { if err != nil { return nil, mapErr(err) } - out := make([]Reminder, len(rs)) - for i, r := range rs { - out[i] = toReminder(r) + out := make([]W, len(rows)) + for i, r := range rows { + out[i] = conv(r) } return out, nil } +func (a *storeAPI) ListReminders(ctx context.Context, n int) ([]Reminder, error) { + rs, err := a.s.ListReminders(ctx, n) + return mapRows(rs, err, toReminder) +} + func (a *storeAPI) RescheduleReminder(ctx context.Context, id int64, now time.Time) error { return mapErr(a.s.RescheduleReminder(ctx, id, now)) } @@ -109,85 +115,48 @@ func (a *storeAPI) RecentOutcomes(ctx context.Context, rule string, n int) ([]st func (a *storeAPI) RecentFacts(ctx context.Context, n int) ([]Fact, error) { fs, err := a.s.RecentFacts(ctx, n) - if err != nil { - return nil, mapErr(err) - } - out := make([]Fact, len(fs)) - for i, f := range fs { - out[i] = toFact(f) - } - return out, nil + return mapRows(fs, err, toFact) } func (a *storeAPI) RecentActiveFactsByKind(ctx context.Context, kind string, n int) ([]Fact, error) { fs, err := a.s.RecentActiveFactsByKind(ctx, store.FactKind(kind), n) - if err != nil { - return nil, mapErr(err) - } - out := make([]Fact, len(fs)) - for i, f := range fs { - out[i] = toFact(f) - } - return out, nil + return mapRows(fs, err, toFact) } func (a *storeAPI) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) { fs, err := a.s.CalendarEvents(ctx, from, to) - if err != nil { - return nil, mapErr(err) - } - out := make([]Fact, len(fs)) - for i, f := range fs { - out[i] = toFact(f) - } - return out, nil + return mapRows(fs, err, toFact) } func (a *storeAPI) RecentEcosystemTraces(ctx context.Context, n int) ([]EcosystemTrace, error) { trs, err := a.s.RecentEcosystemTraces(ctx, n) - if err != nil { - return nil, mapErr(err) - } - out := make([]EcosystemTrace, len(trs)) - for i, tr := range trs { - out[i] = EcosystemTrace{ + return mapRows(trs, err, func(tr store.EcosystemTrace) EcosystemTrace { + return EcosystemTrace{ ID: tr.ID, Ts: tr.Ts, Service: tr.Service, Operation: tr.Operation, Status: tr.Status, DurationMs: tr.DurationMs, CorrelationID: tr.CorrelationID, CausationID: tr.CausationID, HTTPStatus: tr.HTTPStatus, Fields: tr.Fields, } - } - return out, nil + }) } func (a *storeAPI) RecentNudges(ctx context.Context, n int) ([]Nudge, error) { ns, err := a.s.RecentNudges(ctx, n) - if err != nil { - return nil, mapErr(err) - } - out := make([]Nudge, len(ns)) - for i, ng := range ns { - out[i] = toNudge(ng) - } - return out, nil + return mapRows(ns, err, toNudge) } func (a *storeAPI) DeliveryAttempts(ctx context.Context, status string, n int) ([]DeliveryAttempt, error) { as, err := a.s.ListDeliveryAttempts(ctx, status, n) - if err != nil { - return nil, mapErr(err) - } - out := make([]DeliveryAttempt, len(as)) - for i, at := range as { - out[i] = DeliveryAttempt{ + return mapRows(as, err, func(at store.DeliveryAttempt) DeliveryAttempt { + out := DeliveryAttempt{ ID: at.ID, Kind: at.Kind, Rule: at.Rule, ReminderID: at.ReminderID, Channel: at.Channel, Status: at.Status, Created: at.Created, } if at.HasComplete { t := at.Completed - out[i].Completed = &t + out.Completed = &t } - } - return out, nil + return out + }) } func (a *storeAPI) WriteNote(ctx context.Context, ts time.Time, text string, embedding []float32, source string) (int64, error) { @@ -197,38 +166,17 @@ func (a *storeAPI) WriteNote(ctx context.Context, ts time.Time, text string, emb func (a *storeAPI) QueryNotes(ctx context.Context, embedding []float32, k int) ([]Note, error) { ns, err := a.s.QueryNotes(ctx, embedding, k) - if err != nil { - return nil, mapErr(err) - } - out := make([]Note, len(ns)) - for i, n := range ns { - out[i] = toNote(n) - } - return out, nil + return mapRows(ns, err, toNote) } func (a *storeAPI) RecentNotesFromSource(ctx context.Context, prefix string, n int) ([]Note, error) { ns, err := a.s.RecentNotesFromSource(ctx, prefix, n) - if err != nil { - return nil, mapErr(err) - } - out := make([]Note, len(ns)) - for i, note := range ns { - out[i] = toNote(note) - } - return out, nil + return mapRows(ns, err, toNote) } func (a *storeAPI) RecentNotes(ctx context.Context, n int) ([]Note, error) { ns, err := a.s.RecentNotes(ctx, n) - if err != nil { - return nil, mapErr(err) - } - out := make([]Note, len(ns)) - for i, note := range ns { - out[i] = toNote(note) - } - return out, nil + return mapRows(ns, err, toNote) } func (a *storeAPI) ProposeTool(ctx context.Context, name, utterance, scope string, ts time.Time) (bool, error) { @@ -299,14 +247,7 @@ func (a *storeAPI) DayPlan(ctx context.Context) (DayPlan, error) { func (a *storeAPI) ListTools(ctx context.Context, status string) ([]Tool, error) { ts, err := a.s.ListTools(ctx, status) - if err != nil { - return nil, mapErr(err) - } - out := make([]Tool, len(ts)) - for i, t := range ts { - out[i] = toTool(t) - } - return out, nil + return mapRows(ts, err, toTool) } func (a *storeAPI) DeleteTool(ctx context.Context, name string) error { @@ -334,12 +275,8 @@ func (a *storeAPI) CaptureTask(ctx context.Context, req CaptureTaskReq) (Capture func (a *storeAPI) ListTasks(ctx context.Context, status string) ([]Task, error) { ts, err := a.s.ListTasks(ctx, status) - if err != nil { - return nil, mapErr(err) - } - out := make([]Task, len(ts)) - for i, t := range ts { - out[i] = Task{ + return mapRows(ts, err, func(t store.Task) Task { + return Task{ ID: t.ID, CreatedTs: t.CreatedTs, Text: t.Text, @@ -354,8 +291,7 @@ func (a *storeAPI) ListTasks(ctx context.Context, status string) ([]Task, error) DoneWhen: t.DoneWhen, BlockedOn: t.BlockedOn, } - } - return out, nil + }) } func (a *storeAPI) SetTaskStatus(ctx context.Context, id int64, status string, ts time.Time, by string) error { @@ -379,24 +315,17 @@ func (a *storeAPI) SetTaskFields(ctx context.Context, id int64, doneWhen, blocke func (a *storeAPI) ListProposedRoutines(ctx context.Context) ([]ProposedRoutine, error) { rs, err := a.s.ListProposedRoutines(ctx) - if err != nil { - return nil, mapErr(err) - } - out := make([]ProposedRoutine, len(rs)) - for i, r := range rs { - out[i] = ProposedRoutine{ + return mapRows(rs, err, func(r store.ProposedRoutine) ProposedRoutine { + return ProposedRoutine{ ID: r.ID, Action: r.Action, Object: r.Object, IntervalDays: r.IntervalDays, Status: string(r.Status), CreatedTs: r.CreatedTs.UnixMilli(), + ReminderID: r.ReminderID, } - if r.ReminderID != nil { - out[i].ReminderID = r.ReminderID - } - } - return out, nil + }) } func (a *storeAPI) DismissProposedRoutine(ctx context.Context, id int64) error {