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
78 lines
3.0 KiB
Go
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)
|
|
})
|
|
}
|