Files
mesh-catalog/modules/gitea/cmd/package-registry/incoming.go
T
jschoubben dc0349a220 G-catalog-B 5: distribution and gitea look at every open transfer at the idle watch's start
A transfer whose idle key ended while the bundle was down was never dropped. Both hand mesh-sdk's
FollowIdle their open transfers, which it gives Expired once the watch is taken.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 18:09:42 +01:00

78 lines
3.0 KiB
Go

package main
// The package seats' incoming, read and steered (design 51 *Publishing*; tools review F4): npm_incoming and
// go_incoming list a seat's open transfers, incoming's fill and the cap its binding carries, and drop one by hand.
// The holder counts against that cap, never a number of its own, and drops a transfer left with no chunk for 24 hours
// when its idle key ends (the bus's marker), never on a timer.
import (
"errors"
"fmt"
"os"
"strings"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/parts"
"gitea/internal/packageseats"
)
// incomingTool is a seat's <type>_incoming.
func incomingTool(typ, seat string, holder func() (*packageseats.Holder, error)) stdio.Tool {
str := func(args map[string]any, k string) string { s, _ := args[k].(string); return strings.TrimSpace(s) }
return stdio.Tool{
Name: typ + "_incoming",
Description: "The " + seat + " seat's open transfers in the forge module's object store incoming (each with its " +
"opener, its parts and when it last took a chunk), incoming's fill and the cap its binding carries; a " +
"transfer with no chunk for 24 hours is dropped on its own. With drop, drops one by hand, its chunks with " +
"it (a hand act, why required). (a)",
Input: map[string]any{"type": "object", "properties": map[string]any{
"drop": map[string]any{"type": "string", "description": "a transfer id (the caller's own name) to drop"},
"why": map[string]any{"type": "string", "description": "why it is dropped"},
}},
Run: func(args map[string]any) (any, error) {
h, err := holder()
if err != nil {
return nil, err
}
if id := str(args, "drop"); id != "" {
if str(args, "why") == "" {
return nil, errors.New("a drop is a hand act: say why")
}
t, err := h.Drop(seat, id)
if err != nil {
return nil, err
}
fmt.Fprintf(os.Stderr, "transfer %s of %s dropped by hand by %s: %s\n", id, seat, stdio.CallerOf(args), str(args, "why"))
return map[string]any{"dropped": t.ID}, nil
}
return h.IncomingOf(seat)
},
}
}
// followIdle drops a transfer when its idle key ends (packageseats.Holder.Expired): the bus's marker is the event; at the
// watch's start every open transfer is looked at too, so one that ended while the bundle was down is dropped.
func followIdle(holder func() (*packageseats.Holder, error)) {
open := func() ([]string, error) {
h, err := holder()
if err != nil {
return nil, fmt.Errorf("the holder cannot be made: %w", err)
}
return parts.IDs(h.Transfers)()
}
parts.FollowIdle(packageseats.IdleState, open, func(id string) (bool, error) {
h, err := holder()
if err != nil {
return false, fmt.Errorf("transfer %s's idle bound ended, but the holder cannot be made: %w", id, err)
}
return h.Expired(id)
}, func(id string, dropped bool, err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Fprintf(os.Stderr, "transfer %s had no chunk for %s: dropped with its chunks\n", id, packageseats.TransferIdle)
})
}