Skip to content

Commit d374d93

Browse files
committed
robot: forget message api
For #90.
1 parent 265923b commit d374d93

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

api.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package main
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
7+
"io"
68
"log/slog"
79
"net"
810
"net/http"
@@ -12,6 +14,7 @@ import (
1214
"time"
1315

1416
"github.com/go-json-experiment/json"
17+
"github.com/go-json-experiment/json/jsontext"
1518
"github.com/google/uuid"
1619
"github.com/prometheus/client_golang/prometheus"
1720
"github.com/prometheus/client_golang/prometheus/collectors"
@@ -41,6 +44,7 @@ func (robo *Robot) api(ctx context.Context, listen string, mux *http.ServeMux, m
4144
mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol)
4245
mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)
4346
mux.HandleFunc("GET /api/message/{tag...}", robo.apiRecall)
47+
mux.HandleFunc("DELETE /api/message/{tag...}", robo.apiForget)
4448
l, err := net.Listen("tcp", listen)
4549
if err != nil {
4650
return fmt.Errorf("couldn't start API server: %w", err)
@@ -144,3 +148,42 @@ func (robo *Robot) apiRecall(w http.ResponseWriter, r *http.Request) {
144148
log.ErrorContext(ctx, "write response failed", slog.Any("err", err))
145149
}
146150
}
151+
152+
func (robo *Robot) apiForget(w http.ResponseWriter, r *http.Request) {
153+
ctx := r.Context()
154+
log := slog.With(slog.String("api", "recall"), slog.Any("trace", uuid.New()))
155+
log.InfoContext(ctx, "handle", slog.String("route", r.Pattern), slog.String("remote", r.RemoteAddr))
156+
defer log.InfoContext(ctx, "done")
157+
tag := r.PathValue("tag")
158+
d := jsontext.NewDecoder(r.Body)
159+
var all error
160+
for {
161+
tok, err := d.ReadToken()
162+
switch err {
163+
case nil: // do nothing
164+
case io.EOF:
165+
// Done; transmit any forget errors.
166+
if all != nil {
167+
jsonerror(w, http.StatusInternalServerError, all.Error())
168+
return
169+
}
170+
w.WriteHeader(http.StatusNoContent)
171+
return
172+
default:
173+
log.ErrorContext(ctx, "read token", slog.Any("err", err))
174+
jsonerror(w, http.StatusBadRequest, "token read failed")
175+
return
176+
}
177+
if tok.Kind() != '"' {
178+
log.WarnContext(ctx, "invalid token", slog.Any("kind", tok.Kind()))
179+
jsonerror(w, http.StatusBadRequest, "input not a JSON string")
180+
return
181+
}
182+
id := tok.String()
183+
if err := robo.brain.Forget(ctx, tag, id); err != nil {
184+
log.ErrorContext(ctx, "forget failed", slog.String("tag", tag), slog.String("id", id), slog.Any("err", err))
185+
all = errors.Join(all, err)
186+
// continue on
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)