Files
go-omni/ws/rpc/config.go

68 lines
2.4 KiB
Go

// Package rpc implements an optional, versioned JSON protocol over ws sessions.
// Both endpoints may issue calls and events. It does not provide durable delivery.
package rpc
import (
"context"
"errors"
"time"
)
const Subprotocol = "go-omni.rpc.v1"
var (
ErrClosed = errors.New("rpc: closed")
ErrNotConnected = errors.New("rpc: not connected")
ErrBusy = errors.New("rpc: capacity reached")
ErrProtocol = errors.New("rpc: invalid protocol message")
)
// Config bounds allocations, concurrency, and the lifetime of incoming work.
// Zero fields select defaults. A canceled handler must return before Wait succeeds.
type Config struct {
MaxMessageBytes int `json:"maxMessageBytes"`
MaxPending int `json:"maxPending"`
MaxConcurrent int `json:"maxConcurrent"`
CallTimeout time.Duration `json:"callTimeout"`
WriteTimeout time.Duration `json:"writeTimeout"`
// OnEventError observes local notification failures; they have no reply on
// the wire. This callback runs within the handler completion barrier.
OnEventError func(context.Context, error) `json:"-"`
}
func DefaultConfig() Config {
return Config{MaxMessageBytes: 1 << 20, MaxPending: 128, MaxConcurrent: 32, CallTimeout: 30 * time.Second, WriteTimeout: 5 * time.Second}
}
func (c Config) Validate() error { _, err := normalize(c); return err }
func normalize(c Config) (Config, error) {
if c.MaxMessageBytes < 0 || c.MaxMessageBytes > 16<<20 || c.MaxPending < 0 || c.MaxPending > 65536 || c.MaxConcurrent < 0 || c.MaxConcurrent > 4096 || c.CallTimeout < 0 || c.CallTimeout > 24*time.Hour || c.WriteTimeout < 0 || c.WriteTimeout > time.Minute {
return c, errors.New("rpc: configuration exceeds supported bounds")
}
d := DefaultConfig()
if c.MaxMessageBytes == 0 {
c.MaxMessageBytes = d.MaxMessageBytes
}
if c.MaxPending == 0 {
c.MaxPending = d.MaxPending
}
if c.MaxConcurrent == 0 {
c.MaxConcurrent = d.MaxConcurrent
}
if c.CallTimeout == 0 {
c.CallTimeout = d.CallTimeout
}
if c.WriteTimeout == 0 {
c.WriteTimeout = d.WriteTimeout
}
return c, nil
}
// Error is an explicitly public error. Only this type's code/message may be
// sent to the other endpoint; all other handler errors become INTERNAL.
type Error struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (e *Error) Error() string { return "rpc: " + e.Code }