Files
mesh-sdk/go/stateobjects/process.go
T

127 lines
3.2 KiB
Go

package stateobjects
import (
"context"
"errors"
"time"
"github.com/nats-io/nats.go/jetstream"
"git.novox.be/novox/mesh-sdk/go/kvlimit"
)
// callTimeout bounds each call a process makes of its bus.
const callTimeout = 30 * time.Second
// OverBus is a state a process reaches through its own JetStream, with the object store beside it: a foundation part's
// bucket and its old `objects` section, or a bundle-less part's `<state>-objects`. store names the object store as a
// reader asks for it, written into every reference. The bucket's own limit for one value is the limit of the values.
func OverBus(kv jetstream.KeyValue, objects jetstream.ObjectStore, store string) Values {
limit, cancel := context.WithTimeout(context.Background(), callTimeout)
defer cancel()
return Values{KV: BusKV{KV: kv}, Objects: BusObjects{Store: objects}, Store: store, Limit: int(kvlimit.LimitOf(limit, kv))}
}
// BusKV is a bucket as a process reaches it.
type BusKV struct{ KV jetstream.KeyValue }
func ctx() (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), callTimeout)
}
func (b BusKV) Get(key string) (*Entry, error) {
c, cancel := ctx()
defer cancel()
e, err := b.KV.Get(c, key)
if errors.Is(err, jetstream.ErrKeyNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
if e.Operation() != jetstream.KeyValuePut {
return nil, nil
}
return &Entry{Value: e.Value(), Revision: e.Revision()}, nil
}
func (b BusKV) Create(key string, value []byte) error {
c, cancel := ctx()
defer cancel()
_, err := kvlimit.Create(c, b.KV, key, value)
if errors.Is(err, jetstream.ErrKeyExists) {
return ErrChanged
}
return err
}
func (b BusKV) Update(key string, value []byte, revision uint64) error {
c, cancel := ctx()
defer cancel()
_, err := kvlimit.Update(c, b.KV, key, value, revision)
if errors.Is(err, jetstream.ErrKeyRevisionMismatch) {
return ErrChanged
}
return err
}
func (b BusKV) Delete(key string) error {
c, cancel := ctx()
defer cancel()
return b.KV.Delete(c, key)
}
func (b BusKV) Keys() ([]string, error) {
c, cancel := ctx()
defer cancel()
keys, err := b.KV.Keys(c)
if errors.Is(err, jetstream.ErrNoKeysFound) {
return nil, nil
}
return keys, err
}
// BusObjects is an object store as a process reaches it; it takes any size in one put.
type BusObjects struct{ Store jetstream.ObjectStore }
func (BusObjects) MostBytes() int { return 0 }
func (b BusObjects) Put(name string, data []byte) error {
c, cancel := ctx()
defer cancel()
_, err := b.Store.PutBytes(c, name, data)
return err
}
func (b BusObjects) Get(name string) ([]byte, error) {
c, cancel := ctx()
defer cancel()
return b.Store.GetBytes(c, name)
}
func (b BusObjects) Delete(name string) error {
c, cancel := ctx()
defer cancel()
err := b.Store.Delete(c, name)
if errors.Is(err, jetstream.ErrObjectNotFound) {
return nil
}
return err
}
func (b BusObjects) List() ([]Object, error) {
c, cancel := ctx()
defer cancel()
l, err := b.Store.List(c)
if errors.Is(err, jetstream.ErrNoObjectsFound) {
return nil, nil
}
out := make([]Object, 0, len(l))
for _, o := range l {
if !o.Deleted {
out = append(out, Object{Name: o.Name, Size: int64(o.Size), Modified: o.ModTime})
}
}
return out, err
}