A page's time budget is sent to the runtime, and a verb the runtime lacks is told by its code (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
+3
-7
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/busretry"
|
||||
@@ -115,15 +114,12 @@ type StatePage struct {
|
||||
Next string `json:"next,omitempty"`
|
||||
}
|
||||
|
||||
// Page is the current values in key order after the key `after`, as many as fit maxBytes (keys and values), at least
|
||||
// Page is the current values in key order after the key `after`, as many as fit maxBytes (keys and values) or the time budget allows, at least
|
||||
// one: one request for many values, where Get is one request each. A runtime that does not answer it gives an error
|
||||
// satisfying errors.Is(err, errors.ErrUnsupported), and the reader asks Get per key instead.
|
||||
func (s KeptState) Page(after string, maxBytes int) (StatePage, error) {
|
||||
raw, err := s.ask("page", map[string]any{"after": after, "max_bytes": maxBytes})
|
||||
func (s KeptState) Page(after string, maxBytes int, budget time.Duration) (StatePage, error) {
|
||||
raw, err := s.ask("page", map[string]any{"after": after, "max_bytes": maxBytes, "budget_ms": budget.Milliseconds()})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "answers no mesh/state.page") {
|
||||
return StatePage{}, fmt.Errorf("%w: %v", errors.ErrUnsupported, err)
|
||||
}
|
||||
return StatePage{}, err
|
||||
}
|
||||
var p StatePage
|
||||
|
||||
+6
-1
@@ -150,7 +150,12 @@ type refused struct {
|
||||
func (r *refused) Error() string { return r.message }
|
||||
|
||||
// Is makes a compare-and-set the runtime refused because another writer was first ErrChanged.
|
||||
func (r *refused) Is(target error) bool { return target == ErrChanged && r.code == CodeChanged }
|
||||
func (r *refused) Is(target error) bool {
|
||||
return target == ErrChanged && r.code == CodeChanged || target == errors.ErrUnsupported && r.code == CodeNoMethod
|
||||
}
|
||||
|
||||
// CodeNoMethod is the error code the runtime answers a verb it does not have with (JSON-RPC's method not found).
|
||||
const CodeNoMethod = -32601
|
||||
|
||||
// ErrChanged is a compare-and-set that lost: the key was made or changed by another writer first (novox/hq
|
||||
// ADR 0259). Told apart by the runtime's error code, never by its words.
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ func (k KeptSource) Get(key string) (*Entry, bool, error) {
|
||||
}
|
||||
|
||||
// Page is the values after a key in one request (stdio.KeptState.Page), as FirstView prefers them to Get per key.
|
||||
func (k KeptSource) Page(after string, maxBytes int) ([]KeyedEntry, string, error) {
|
||||
p, err := k.State.Page(after, maxBytes)
|
||||
func (k KeptSource) Page(after string, maxBytes int, budget time.Duration) ([]KeyedEntry, string, error) {
|
||||
p, err := k.State.Page(after, maxBytes, budget)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
+3
-3
@@ -201,10 +201,10 @@ type KeyedEntry struct {
|
||||
}
|
||||
|
||||
// Pager is a Source that answers many values in one request: the values in key order after a key, as many as fit
|
||||
// maxBytes and at least one, and the key to ask after for the rest. FirstView uses it when its source has it, unless
|
||||
// maxBytes or the time budget and at least one, and the key to ask after for the rest. FirstView uses it when its source has it, unless
|
||||
// it answers errors.Is(err, errors.ErrUnsupported), when it reads per key.
|
||||
type Pager interface {
|
||||
Page(after string, maxBytes int) ([]KeyedEntry, string, error)
|
||||
Page(after string, maxBytes int, budget time.Duration) ([]KeyedEntry, string, error)
|
||||
}
|
||||
|
||||
// FirstView answers one page of state from its owner's source: the mark first, so no change after the revision it
|
||||
@@ -226,7 +226,7 @@ func FirstView(owner, state string, values, marks Source, after string, now time
|
||||
}
|
||||
}
|
||||
if p, ok := values.(Pager); ok {
|
||||
got, next, err := p.Page(after, PageBytes)
|
||||
got, next, err := p.Page(after, PageBytes, PageBudget)
|
||||
if err == nil {
|
||||
for _, e := range got {
|
||||
a.put(e.Key, e.Entry)
|
||||
|
||||
@@ -676,7 +676,7 @@ func (s *pagedSource) Get(k string) (*Entry, bool, error) {
|
||||
return s.mapSource.Get(k)
|
||||
}
|
||||
|
||||
func (s *pagedSource) Page(after string, _ int) ([]KeyedEntry, string, error) {
|
||||
func (s *pagedSource) Page(after string, _ int, _ time.Duration) ([]KeyedEntry, string, error) {
|
||||
if s.unsupported {
|
||||
return nil, "", errors.ErrUnsupported
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user