diff options
author | Valery Piashchynski <[email protected]> | 2021-06-14 16:39:02 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2021-06-14 16:39:02 +0300 |
commit | 75ab1e16c64cfd0a6424fe4c546fdbc5e1b992dd (patch) | |
tree | 1e9a910071d20021ad0f7ef4fe6099bac6a341ef /plugins/memory | |
parent | dc8ed203c247afd684f198ebbac103a10bfad72a (diff) |
- Rework redis with ws plugins
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'plugins/memory')
-rw-r--r-- | plugins/memory/plugin.go | 25 | ||||
-rw-r--r-- | plugins/memory/pubsub.go | 95 |
2 files changed, 120 insertions, 0 deletions
diff --git a/plugins/memory/plugin.go b/plugins/memory/plugin.go new file mode 100644 index 00000000..650f0b4b --- /dev/null +++ b/plugins/memory/plugin.go @@ -0,0 +1,25 @@ +package memory + +import ( + "github.com/spiral/roadrunner/v2/pkg/pubsub" + "github.com/spiral/roadrunner/v2/plugins/logger" +) + +const PluginName string = "memory" + +type Plugin struct { + log logger.Logger +} + +func (p *Plugin) Init(log logger.Logger) error { + p.log = log + return nil +} + +func (p *Plugin) PSProvide(key string) (pubsub.PubSub, error) { + return NewPubSubDriver(p.log, key) +} + +func (p *Plugin) Name() string { + return PluginName +} diff --git a/plugins/memory/pubsub.go b/plugins/memory/pubsub.go new file mode 100644 index 00000000..75cd9d24 --- /dev/null +++ b/plugins/memory/pubsub.go @@ -0,0 +1,95 @@ +package memory + +import ( + "sync" + + "github.com/spiral/roadrunner/v2/pkg/bst" + websocketsv1 "github.com/spiral/roadrunner/v2/pkg/proto/websockets/v1beta" + "github.com/spiral/roadrunner/v2/pkg/pubsub" + "github.com/spiral/roadrunner/v2/plugins/logger" + "google.golang.org/protobuf/proto" +) + +type PubSubDriver struct { + sync.RWMutex + // channel with the messages from the RPC + pushCh chan []byte + // user-subscribed topics + storage bst.Storage + log logger.Logger +} + +func NewPubSubDriver(log logger.Logger, _ string) (pubsub.PubSub, error) { + ps := &PubSubDriver{ + pushCh: make(chan []byte, 10), + storage: bst.NewBST(), + log: log, + } + return ps, nil +} + +func (p *PubSubDriver) Publish(message []byte) error { + p.pushCh <- message + return nil +} + +func (p *PubSubDriver) PublishAsync(message []byte) { + go func() { + p.pushCh <- message + }() +} + +func (p *PubSubDriver) Subscribe(connectionID string, topics ...string) error { + p.Lock() + defer p.Unlock() + for i := 0; i < len(topics); i++ { + p.storage.Insert(connectionID, topics[i]) + } + return nil +} + +func (p *PubSubDriver) Unsubscribe(connectionID string, topics ...string) error { + p.Lock() + defer p.Unlock() + for i := 0; i < len(topics); i++ { + p.storage.Remove(connectionID, topics[i]) + } + return nil +} + +func (p *PubSubDriver) Connections(topic string, res map[string]struct{}) { + p.RLock() + defer p.RUnlock() + + ret := p.storage.Get(topic) + for rr := range ret { + res[rr] = struct{}{} + } +} + +func (p *PubSubDriver) Next() (*websocketsv1.Message, error) { + msg := <-p.pushCh + if msg == nil { + return nil, nil + } + + p.RLock() + defer p.RUnlock() + + m := &websocketsv1.Message{} + err := proto.Unmarshal(msg, m) + if err != nil { + return nil, err + } + + // push only messages, which are subscribed + // TODO better??? + for i := 0; i < len(m.GetTopics()); i++ { + // if we have active subscribers - send a message to a topic + // or send nil instead + if ok := p.storage.Contains(m.GetTopics()[i]); ok { + return m, nil + } + } + return nil, nil +} |