func (s *Service) errorf(format string, v ...interface{}) {
	if s.logger == nil {
		return
	}
	s.logger.Errorf(format, v...)
	if s.onError != nil {
		s.onError(s, fmt.Sprintf(format, v...))
	}
}
errorf logs a formatted error entry.
package res
import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/jirenius/go-res/logger"
	"github.com/jirenius/timerqueue"
	nats "github.com/nats-io/nats.go"
)
const protocolVersion = "1.2.2"
const inChannelSize = 256
const workerCount = 32
const defaultQueryEventDuration = time.Second * 3
var (
	errNotStopped = errors.New("res: service is not stopped")
	errNotStarted = errors.New("res: service is not started")
)
type Option interface{ SetOption(*Handler) }
type OptionFunc func(*Handler)
func (f OptionFunc) SetOption(hs *Handler) { f(hs) }
type AccessHandler func(AccessRequest)
type GetHandler func(GetRequest)
type ModelHandler func(ModelRequest)
type CollectionHandler func(CollectionRequest)
type CallHandler func(CallRequest)
type NewHandler func(NewRequest)
type AuthHandler func(AuthRequest)
type ApplyChangeHandler func(r Resource, changes map[string]interface{}) (map[string]interface{}, error)
type ApplyAddHandler func(r Resource, value interface{}, idx int) error
type ApplyRemoveHandler func(r Resource, idx int) (interface{}, error)
type ApplyCreateHandler func(r Resource, data interface{}) error
type ApplyDeleteHandler func(r Resource) (interface{}, error)
type Handler struct {
	Type ResourceType
	Access AccessHandler
	Get GetHandler
	Call map[string]CallHandler
	New NewHandler
	Auth map[string]AuthHandler
	ApplyChange ApplyChangeHandler
	ApplyAdd ApplyAddHandler
	ApplyRemove ApplyRemoveHandler
	ApplyCreate ApplyCreateHandler
	ApplyDelete ApplyDeleteHandler
	Group string
	OnRegister func(service *Service, pattern Pattern, rh Handler)
	Listeners map[string]func(*Event)
}
const (
	stateStopped = iota
	stateStarting
	stateStarted
	stateStopping
)
var (
	Model = OptionFunc(func(hs *Handler) {
		if hs.Type != TypeUnset {
			panic("res: resource type set multiple times")
		}
		hs.Type = TypeModel
	})
	Collection = OptionFunc(func(hs *Handler) {
		if hs.Type != TypeUnset {
			panic("res: resource type set multiple times")
		}
		hs.Type = TypeCollection
	})
)
func (h *Handler) Option(hf ...Option) {
	for _, f := range hf {
		f.SetOption(h)
	}
}
type Service struct {
	*Mux
	state          int32
	nc             Conn                    
	inCh           chan *nats.Msg          
	rwork          map[string]*work        
	workCh         chan *work              
	wg             sync.WaitGroup          
	mu             sync.Mutex              
	logger         logger.Logger           
	queueGroup     string                  
	resetResources []string                
	resetAccess    []string                
	queryTQ        *timerqueue.Queue       
	queryDuration  time.Duration           
	onServe        func(*Service)          
	onDisconnect   func(*Service)          
	onReconnect    func(*Service)          
	onError        func(*Service, string)  
}
func NewService(name string) *Service {
	s := &Service{
		Mux:           NewMux(name),
		queueGroup:    name,
		logger:        logger.NewStdLogger(),
		queryDuration: defaultQueryEventDuration,
	}
	s.Mux.Register(s)
	return s
}
func (s *Service) SetLogger(l logger.Logger) *Service {
	if s.nc != nil {
		panic("res: service already started")
	}
	s.logger = l
	return s
}
func (s *Service) SetQueryEventDuration(d time.Duration) *Service {
	if s.nc != nil {
		panic("res: service already started")
	}
	s.queryDuration = d
	return s
}
func (s *Service) SetQueueGroup(queue string) *Service {
	s.queueGroup = queue
	return s
}
func (s *Service) SetOnServe(f func(*Service)) {
	s.onServe = f
}
func (s *Service) SetOnDisconnect(f func(*Service)) {
	s.onDisconnect = f
}
func (s *Service) SetOnReconnect(f func(*Service)) {
	s.onReconnect = f
}
func (s *Service) SetOnError(f func(*Service, string)) {
	s.onError = f
}
func (s *Service) Logger() logger.Logger {
	return s.logger
}
func (s *Service) ProtocolVersion() string {
	return protocolVersion
}
func (s *Service) Conn() Conn {
	return s.nc
}
func (s *Service) infof(format string, v ...interface{}) {
	if s.logger == nil {
		return
	}
	s.logger.Infof(format, v...)
}