From d3711c1f40615086efc8dffc1f3659301336c151 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:00:37 +0100 Subject: [PATCH 1/7] fix(cmd): stop trapping os.Kill, which cannot be caught SIGKILL cannot be handled, so listing it in signal.Notify had no effect. Behavior is unchanged. --- cmd/parsec/cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/parsec/cmd.go b/cmd/parsec/cmd.go index 3920729..b03bcad 100644 --- a/cmd/parsec/cmd.go +++ b/cmd/parsec/cmd.go @@ -203,7 +203,7 @@ func main() { sigs := make(chan os.Signal, 1) ctx, cancel := context.WithCancel(context.Background()) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) go func() { sig := <-sigs log.Printf("Received %s signal - Stopping...\n", sig.String()) From 630e73370ac3ba50cdcced47b9a7c0d60485db85 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:00:37 +0100 Subject: [PATCH 2/7] refactor(db): ignore the unused error argument in migration walk The callback overwrote err before reading it. Behavior is unchanged. --- pkg/db/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/db/client.go b/pkg/db/client.go index d7ecb31..0d6745a 100644 --- a/pkg/db/client.go +++ b/pkg/db/client.go @@ -116,7 +116,7 @@ func (c *PGClient) applyMigrations() error { }() log.WithField("dir", tmpDir).Debugln("Created temporary directory") - err = fs.WalkDir(migrations, ".", func(path string, d fs.DirEntry, err error) error { + err = fs.WalkDir(migrations, ".", func(path string, d fs.DirEntry, _ error) error { join := filepath.Join(tmpDir, path) if d.IsDir() { return os.MkdirAll(join, 0o755) From 3c1e6f35c7415d0492965e96bc43923525b75bfa Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:00:38 +0100 Subject: [PATCH 3/7] refactor(server): remove unused conf field and fmtMultihash --- pkg/server/host.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkg/server/host.go b/pkg/server/host.go index 0edc4f7..99f9a3e 100644 --- a/pkg/server/host.go +++ b/pkg/server/host.go @@ -44,7 +44,6 @@ type HostConfig struct { type Host struct { host.Host - conf *HostConfig fhClient firehose.Submitter idService identify.IDService @@ -361,14 +360,6 @@ func fmtContextID(contextID []byte) string { return str } -func fmtMultihash(m mh.Multihash) string { - str := m.B58String() - if len(str) >= 16 { - return str[:16] - } - return str -} - func (h *Host) getPublicIP(ctx context.Context) error { log.Infoln("Fetching public IP from AWS checkip service...") req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://checkip.amazonaws.com", nil) From acc60ee1c43679beafccb24ec206c74bd7f39e10 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:00:38 +0100 Subject: [PATCH 4/7] refactor(server): use a typed context key for the scheduler ID A plain string key can collide with keys from other packages. The header name and the stored value are unchanged. --- pkg/server/server.go | 6 ++++++ pkg/server/server_dht.go | 4 ++-- pkg/server/server_handlers.go | 4 ++-- pkg/server/server_ipni.go | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg/server/server.go b/pkg/server/server.go index 846c5d4..918b257 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -26,6 +26,12 @@ type IServer interface { const headerSchedulerID = "x-scheduler-id" +// ctxKey is the type of context keys set by this package. +type ctxKey string + +// schedulerIDKey holds the scheduler ID in a request context. +const schedulerIDKey ctxKey = headerSchedulerID + type Config struct { Host string Port int diff --git a/pkg/server/server_dht.go b/pkg/server/server_dht.go index 49d6684..d9596b3 100644 --- a/pkg/server/server_dht.go +++ b/pkg/server/server_dht.go @@ -134,7 +134,7 @@ func (d *DHTServer) Provide(ctx context.Context, cid cid.Cid) (*ProvideResponse, err := d.DHT.Provide(timeoutCtx, cid, true) duration := time.Since(start) - latencies.WithLabelValues("provide_duration", strconv.FormatBool(err == nil), ctx.Value(headerSchedulerID).(string)).Observe(duration.Seconds()) + latencies.WithLabelValues("provide_duration", strconv.FormatBool(err == nil), ctx.Value(schedulerIDKey).(string)).Observe(duration.Seconds()) logEntry := log.WithField("dur", duration.Seconds()).WithField("cid", cid.String()) if err != nil { logEntry = logEntry.WithError(err) @@ -183,7 +183,7 @@ func (d *DHTServer) Retrieve(ctx context.Context, cid cid.Cid) (*RetrievalRespon RoutingTableSize: RoutingTableSize(d.DHT), } - latencies.WithLabelValues("retrieval_ttfpr", strconv.FormatBool(err == nil), ctx.Value(headerSchedulerID).(string)).Observe(duration.Seconds()) + latencies.WithLabelValues("retrieval_ttfpr", strconv.FormatBool(err == nil), ctx.Value(schedulerIDKey).(string)).Observe(duration.Seconds()) return resp, nil } diff --git a/pkg/server/server_handlers.go b/pkg/server/server_handlers.go index de99075..437b0bd 100644 --- a/pkg/server/server_handlers.go +++ b/pkg/server/server_handlers.go @@ -42,7 +42,7 @@ func (s *Server) provide(rw http.ResponseWriter, req *http.Request) { log.WithField("cid", content.CID.String()).Infoln("Start providing content...") - ctx := context.WithValue(req.Context(), headerSchedulerID, req.Header.Get(headerSchedulerID)) + ctx := context.WithValue(req.Context(), schedulerIDKey, req.Header.Get(headerSchedulerID)) resp, err := s.serverImpl.Provide(ctx, content.CID) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) @@ -66,7 +66,7 @@ func (s *Server) provide(rw http.ResponseWriter, req *http.Request) { type RetrieveRequest struct{} func (s *Server) retrieve(rw http.ResponseWriter, req *http.Request) { - ctx := context.WithValue(req.Context(), headerSchedulerID, req.Header.Get(headerSchedulerID)) + ctx := context.WithValue(req.Context(), schedulerIDKey, req.Header.Get(headerSchedulerID)) var rr RetrieveRequest data, err := io.ReadAll(req.Body) if err != nil { diff --git a/pkg/server/server_ipni.go b/pkg/server/server_ipni.go index 9db96c3..854f263 100644 --- a/pkg/server/server_ipni.go +++ b/pkg/server/server_ipni.go @@ -187,7 +187,7 @@ func (i *IPNIServer) Provide(ctx context.Context, c cid.Cid) (pr *ProvideRespons return } - latencies.WithLabelValues("provide_duration", strconv.FormatBool(m.Error == ""), ctx.Value(headerSchedulerID).(string)).Observe(m.Duration.Seconds()) + latencies.WithLabelValues("provide_duration", strconv.FormatBool(m.Error == ""), ctx.Value(schedulerIDKey).(string)).Observe(m.Duration.Seconds()) }() // Generating multihash for probing after we have pushed out the advertisement. @@ -425,7 +425,7 @@ func (i *IPNIServer) Retrieve(ctx context.Context, cid cid.Cid) (*RetrievalRespo RoutingTableSize: 0, } - latencies.WithLabelValues("retrieval_ttfpr", strconv.FormatBool(err == nil), ctx.Value(headerSchedulerID).(string)).Observe(duration.Seconds()) + latencies.WithLabelValues("retrieval_ttfpr", strconv.FormatBool(err == nil), ctx.Value(schedulerIDKey).(string)).Observe(duration.Seconds()) return retResp, nil } From 8c244edf1f8f271214ae920fa9fccd312a583624 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:00:59 +0100 Subject: [PATCH 5/7] refactor: apply go fix modernizations Replaces interface{} with any, a counting loop with range over int, and fmt.Sprintf into []byte with fmt.Appendf. Produced by just format. --- pkg/server/host.go | 4 ++-- pkg/server/server_ipni.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/server/host.go b/pkg/server/host.go index 99f9a3e..5a2df72 100644 --- a/pkg/server/host.go +++ b/pkg/server/host.go @@ -273,7 +273,7 @@ var codecs = []multicodec.Code{ } func (h *Host) subscribeForEvents() error { - sub, err := h.EventBus().Subscribe([]interface{}{new(event.EvtLocalAddressesUpdated), new(event.EvtLocalReachabilityChanged)}) + sub, err := h.EventBus().Subscribe([]any{new(event.EvtLocalAddressesUpdated), new(event.EvtLocalReachabilityChanged)}) if err != nil { return fmt.Errorf("event bus subscription: %w", err) } @@ -340,7 +340,7 @@ func RoutingTableSize(dht routing.Routing) int { func genProbes(start mh.Multihash, count int) ([]mh.Multihash, error) { probes := make([]mh.Multihash, count) hash := start - for i := 0; i < count; i++ { + for i := range count { probe, err := mh.Sum(hash, mh.SHA2_256, -1) if err != nil { return nil, fmt.Errorf("gen probe digest: %w", err) diff --git a/pkg/server/server_ipni.go b/pkg/server/server_ipni.go index 854f263..af17749 100644 --- a/pkg/server/server_ipni.go +++ b/pkg/server/server_ipni.go @@ -206,7 +206,7 @@ func (i *IPNIServer) Provide(ctx context.Context, c cid.Cid) (pr *ProvideRespons logEntry.Infoln(" Probes:", probeCount) // The contextID just needs to be unique per multihash - contextID := []byte(fmt.Sprintf("parsec-%d", rand.Uint64())) + contextID := fmt.Appendf(nil, "parsec-%d", rand.Uint64()) logEntry.Infoln(" CtxID:", base64.StdEncoding.EncodeToString(contextID)) logEntry = logEntry.WithField("ctxID", fmtContextID(contextID)) From 162ff8a3009019e9ca96f701747de48bc95d8155 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:01:35 +0100 Subject: [PATCH 6/7] build: fail just lint when go fix has pending changes go fix -diff exits 0 even when it prints a diff, so lint never failed on it. --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index 553a9ff..f04c26f 100644 --- a/justfile +++ b/justfile @@ -29,7 +29,7 @@ build: # Check formatting, go fix, vet, and staticcheck without changing files lint: @test -z "$(gofumpt -l .)" || { echo "not formatted, run just format:"; gofumpt -l .; exit 1; } - go fix -diff ./... + @test -z "$(go fix -diff ./... 2>/dev/null)" || { go fix -diff ./... 2>/dev/null; echo "go fix changes pending, run just format"; exit 1; } go vet ./... staticcheck ./... From 781ed8e46ea94c0eabd043e3d5f06505e446bfd3 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 6 Nov 2026 11:01:35 +0100 Subject: [PATCH 7/7] chore: keep only SA1019 ignored in staticcheck.conf The other ignored checks are fixed in code. SA1019 stays because the aws-sdk-go v1 migration is a larger change. --- staticcheck.conf | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/staticcheck.conf b/staticcheck.conf index 2a9f2a3..9c3af29 100644 --- a/staticcheck.conf +++ b/staticcheck.conf @@ -1,7 +1,4 @@ -# Existing findings, left for follow-up changes so that `just lint` passes: -# SA1016 os.Kill in signal.Notify (cmd/parsec/cmd.go) -# SA1019 deprecated aws-sdk-go v1 and go-ipfs-util -# SA1029 string context keys (pkg/server/server_handlers.go) -# SA4009 overwritten err argument (pkg/db/client.go) -# U1000 unused field conf and func fmtMultihash (pkg/server/host.go) -checks = ["inherit", "-SA1016", "-SA1019", "-SA1029", "-SA4009", "-U1000"] +# SA1019 stays ignored: aws-sdk-go v1 (pkg/firehose) and go-ipfs-util +# (pkg/util) are deprecated. Moving to aws-sdk-go v2 is a larger change, +# so it is tracked separately. Remove this file once it is done. +checks = ["inherit", "-SA1019"]