add dispatcher

simplify transport implementation
support wildcard subscriptions
This commit is contained in:
Marcelo Pires
2018-09-24 16:13:57 +02:00
parent 8583e29645
commit 33a61d6d27
13 changed files with 786 additions and 410 deletions

View File

@ -1,73 +1,67 @@
package subscription
import (
"errors"
"github.com/thesyncim/faye/message"
"regexp"
)
var ErrInvalidChannelName = errors.New("invalid channel channel")
type Unsubscriber func(subscription *Subscription) error
type Publisher func(msg message.Data) (string, error)
type Subscription struct {
id string //request Subscription ID
channel string
ok chan error //used by
unsub Unsubscriber
pub Publisher
msgCh chan *message.Message
}
func NewSubscription(id string, chanel string, unsub Unsubscriber, pub Publisher, msgCh chan *message.Message, ok chan error) *Subscription {
//todo error
func NewSubscription(chanel string, unsub Unsubscriber, msgCh chan *message.Message) (*Subscription, error) {
if !IsValidSubscriptionName(chanel) {
return nil, ErrInvalidChannelName
}
return &Subscription{
pub: pub,
ok: ok,
id: id,
channel: chanel,
unsub: unsub,
msgCh: msgCh,
}
}, nil
}
func (s *Subscription) OnMessage(onMessage func(msg message.Data)) error {
func (s *Subscription) OnMessage(onMessage func(channel string, msg message.Data)) error {
var inMsg *message.Message
for inMsg = range s.msgCh {
if inMsg.GetError() != nil {
return inMsg.GetError()
}
onMessage(inMsg.Data)
onMessage(inMsg.Channel, inMsg.Data)
}
return nil
}
func (s *Subscription) ID() string {
return s.id
}
func (s *Subscription) MsgChannel() chan *message.Message {
return s.msgCh
}
func (s *Subscription) Channel() string {
func (s *Subscription) Name() string {
return s.channel
}
//todo remove
func (s *Subscription) SubscriptionResult() chan error {
return s.ok
}
//Unsubscribe ...
func (s *Subscription) Unsubscribe() error {
return s.unsub(s)
}
func (s *Subscription) Publish(msg message.Data) (string, error) {
return s.pub(msg)
}
//validChannelName channel specifies is the channel is in the format /foo/432/bar
var validChannelName = regexp.MustCompile(`^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$`)
var validChannelPattern = regexp.MustCompile(`^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$`)
func IsValidChannel(channel string) bool {
func IsValidSubscriptionName(channel string) bool {
return validChannelName.MatchString(channel) || validChannelPattern.MatchString(channel)
}
//isValidPublishName
func IsValidPublishName(channel string) bool {
return validChannelName.MatchString(channel)
}

View File

@ -1,20 +1,23 @@
package subscription
import "testing"
import (
"testing"
)
/*
assertEqual( ["/**", "/foo", "/*"],
Channel.expand("/foo") )
channel.expand("/foo") )
assertEqual( ["/**", "/foo/bar", "/foo/*", "/foo/**"],
Channel.expand("/foo/bar") )
channel.expand("/foo/bar") )
assertEqual( ["/**", "/foo/bar/qux", "/foo/bar/*", "/foo/**", "/foo/bar/**"],
*/
func TestIsValidChannel(t *testing.T) {
func TestIsValidSubscriptionName(t *testing.T) {
type args struct {
channel string
}
tests := []struct {
name string
args args
@ -62,11 +65,18 @@ func TestIsValidChannel(t *testing.T) {
},
want: false,
},
{
name: "asterisk before slash",
args: args{
channel: "/foo*",
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsValidChannel(tt.args.channel); got != tt.want {
t.Errorf("IsValidChannel() = %v, want %v", got, tt.want)
if got := IsValidSubscriptionName(tt.args.channel); got != tt.want {
t.Errorf("isValidChannelName() = %v, want %v", got, tt.want)
}
})
}