2024-07-30 14:28:39 +02:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-08-02 12:57:07 +02:00
|
|
|
"time"
|
2024-07-30 14:28:39 +02:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Registry struct {
|
2024-08-02 12:57:07 +02:00
|
|
|
protocols map[Identifier]ProtocolFactory
|
2024-07-30 14:28:39 +02:00
|
|
|
}
|
|
|
|
|
2024-08-02 12:57:07 +02:00
|
|
|
func (r *Registry) Register(identifier Identifier, factory ProtocolFactory) {
|
|
|
|
r.protocols[identifier] = factory
|
2024-07-30 14:28:39 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:21:53 +02:00
|
|
|
func (r *Registry) Get(identifier Identifier, funcs ...ProtocolOptionFunc) (Protocol, error) {
|
|
|
|
factory, exists := r.protocols[identifier]
|
|
|
|
if !exists {
|
|
|
|
return nil, errors.WithStack(ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
protocolOpts := NewProtocolOptions(funcs...)
|
|
|
|
|
|
|
|
proto, err := factory(protocolOpts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return proto, nil
|
|
|
|
}
|
|
|
|
|
2024-08-02 12:57:07 +02:00
|
|
|
func (r *Registry) Availables(ctx context.Context, addr string, timeout time.Duration, funcs ...ProtocolOptionFunc) ([]Protocol, error) {
|
2024-07-30 14:28:39 +02:00
|
|
|
availables := make([]Protocol, 0)
|
2024-08-02 12:57:07 +02:00
|
|
|
protocolOpts := NewProtocolOptions(funcs...)
|
2024-07-30 14:28:39 +02:00
|
|
|
|
2024-08-02 12:57:07 +02:00
|
|
|
for _, factory := range r.protocols {
|
|
|
|
proto, err := factory(protocolOpts)
|
2024-07-30 14:28:39 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
2024-08-02 12:57:07 +02:00
|
|
|
timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
|
|
|
|
|
|
|
|
available, err := proto.Available(timeoutCtx, addr)
|
|
|
|
if err != nil {
|
|
|
|
cancel()
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cancel()
|
|
|
|
|
2024-07-30 14:28:39 +02:00
|
|
|
if !available {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
availables = append(availables, proto)
|
|
|
|
}
|
|
|
|
|
|
|
|
return availables, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRegistry() *Registry {
|
|
|
|
return &Registry{
|
2024-08-02 12:57:07 +02:00
|
|
|
protocols: make(map[Identifier]ProtocolFactory),
|
2024-07-30 14:28:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var defaultRegistry = NewRegistry()
|
|
|
|
|
|
|
|
func DefaultRegistry() *Registry {
|
|
|
|
return defaultRegistry
|
|
|
|
}
|
|
|
|
|
2024-08-02 12:57:07 +02:00
|
|
|
func Register(identifier Identifier, factory ProtocolFactory) {
|
|
|
|
defaultRegistry.Register(identifier, factory)
|
2024-07-30 14:28:39 +02:00
|
|
|
}
|
|
|
|
|
2024-08-02 12:57:07 +02:00
|
|
|
func Availables(ctx context.Context, addr string, timeout time.Duration) ([]Protocol, error) {
|
|
|
|
return defaultRegistry.Availables(ctx, addr, timeout)
|
2024-07-30 14:28:39 +02:00
|
|
|
}
|