The running checker asks the checking program twice on the build seat's job run: first the heads' seat list, which the manifest validator's requests (change and trunk) and the node-engine composer's carry; then the verdict of the facts it gathered. The program is built at the group's mesh-delivery head, else at mesh-delivery's trunk, and its input is kept in the checker's new state inputs as the exact bytes of its digest, read with checker_inputs. A run ask no build node begins within 5 minutes is put once more, then fails the check naming the job; a program that does not build or answer fails the check naming it, and the verdict records who judged it (JudgedBy). A second step-seen hook on a context is added to the first, so a try still sees its steps. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package check
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
// memKV is a bucket in memory with the revisions a real one gives.
|
|
type memKV struct {
|
|
mu sync.Mutex
|
|
vals map[string][]byte
|
|
revs map[string]uint64
|
|
next uint64
|
|
// creates counts the creates that succeeded, by key.
|
|
creates map[string]int
|
|
}
|
|
|
|
func newMemKV() *memKV {
|
|
return &memKV{vals: map[string][]byte{}, revs: map[string]uint64{}, creates: map[string]int{}}
|
|
}
|
|
|
|
func (m *memKV) Get(_ context.Context, key string) ([]byte, uint64, bool, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
v, ok := m.vals[key]
|
|
return v, m.revs[key], ok, nil
|
|
}
|
|
|
|
func (m *memKV) Create(_ context.Context, key string, value []byte) (uint64, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if _, ok := m.vals[key]; ok {
|
|
return 0, ErrConflict
|
|
}
|
|
m.next++
|
|
m.vals[key], m.revs[key] = append([]byte(nil), value...), m.next
|
|
m.creates[key]++
|
|
return m.next, nil
|
|
}
|
|
|
|
func (m *memKV) Update(_ context.Context, key string, value []byte, revision uint64) (uint64, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if _, ok := m.vals[key]; !ok || m.revs[key] != revision {
|
|
return 0, ErrConflict
|
|
}
|
|
m.next++
|
|
m.vals[key], m.revs[key] = append([]byte(nil), value...), m.next
|
|
return m.next, nil
|
|
}
|
|
|
|
func (m *memKV) Keys(context.Context) ([]string, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
keys := make([]string, 0, len(m.vals))
|
|
for k := range m.vals {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
return keys, nil
|
|
}
|
|
|
|
func (m *memKV) Delete(_ context.Context, key string) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
delete(m.vals, key)
|
|
delete(m.revs, key)
|
|
return nil
|
|
}
|
|
|
|
// memInputs keeps run inputs in a memKV, under their digest.
|
|
type memInputs struct{ kv *memKV }
|
|
|
|
func (m memInputs) Keep(ctx context.Context, digest string, body []byte) error {
|
|
if _, _, found, _ := m.kv.Get(ctx, digest); found {
|
|
return nil
|
|
}
|
|
_, err := m.kv.Create(ctx, digest, body)
|
|
return err
|
|
}
|