func (p RpcMessageReceiver) handleRpc(args []interface{}, kwargs map[string]interface{}) *gowamp.CallResult { defer utils.Recover() var msg messaging.Message if msgStr, ok := args[0].(string); ok { err := msg.FromString(msgStr) if err != nil { return p.makeErrorResult(err) } } else { err := models.Convert(args[0], &msg) if err != nil { return p.makeErrorResult(err) } } log.Info("RPC message received:", msg) res, err := p.MessageProcessor.Process(msg) if err != nil { return p.makeErrorResult(err) } return p.makeResult(res) }
func (p WsMessageReceiver) handleSubscribe(im interceptorMessage, msg *gowamp.Subscribe) { opts := models.SubscribeOptions{} err := models.Convert(msg.Options, &opts) if err != nil { log.Error(err) return } topic := fmt.Sprintf("%v", msg.Topic) topicArguments := strings.Split(topic, ".") opts.Topic = topic if opts.IsSpecial() { baseTopic := messaging.BuildTopicArbitrary(topicArguments[:len(topicArguments)-1]...) opts.BaseTopic = baseTopic } else { opts.BaseTopic = topic } log.Info("Listening for changefeed:", opts) d := db.NewDbService() newValuesChan := make(chan map[string]interface{}) //for create and delete we want to listen for changes for the whole collection, for update only for the specific item if opts.Operation == messaging.OP_CREATE || opts.Operation == messaging.OP_DELETE { err = d.Changes(opts.AppId, opts.Type, opts.Filter, newValuesChan) } else if opts.Operation == messaging.OP_UPDATE { opts.ItemId = topicArguments[len(topicArguments)-1] err = d.ChangesId(opts.ItemId, newValuesChan) } if err != nil { log.Error(err) return } messageBuilder := messaging.GetMessageBuilder() go func() { leaveChan := make(chan interface{}) p.broadcaster.Subscribe(leaveChan) for { select { case val := <-newValuesChan: p.processDatabaseUpdate(val, &messageBuilder, opts) case leaveVal := <-leaveChan: sessionId := leaveVal.(gowamp.ID) if im.sess.Id == sessionId { //TODO: newValuesChan seems to be automatically closed by the rethinkdb driver //investigate whether we need to do something else _, leaveChanOpened := <-leaveChan if leaveChanOpened { close(leaveChan) } p.broadcaster.Remove(leaveChan) return } } } }() }