// Subscribe prepares the peer to consume messages. func (c *Peer) Subscribe() error { // Subscription names must start with a lowercase letter, end with a // lowercase letter or number, and contain only lowercase letters, numbers, // dashes, underscores or periods. c.subscription = strings.ToLower(fmt.Sprintf("x%sx", broker.GenerateName())) exists, err := pubsub.SubExists(c.context, c.subscription) if err != nil { return err } if exists { return fmt.Errorf("Subscription %s already exists", c.subscription) } if err := pubsub.CreateSub(c.context, c.subscription, topic, 0, ""); err != nil { return err } go c.ack() go func() { // TODO: Can we avoid using atomic flag? for atomic.LoadInt32(&c.stopped) != stopped { messages, err := pubsub.PullWait(c.context, c.subscription, bufferSize) if err != nil { // Timed out. continue } ids := make([]string, len(messages)) for i, message := range messages { ids[i] = message.AckID c.messages <- message.Data } c.acks <- ids } }() return nil }
func consumePubSubMsgs(projectId string, topicName string) <-chan []byte { msgC := make(chan []byte, 100) subName := topicName + "-2loggly" ackDeadline := time.Second * 20 client, err := google.DefaultClient(context.Background(), pubsub.ScopePubSub) if err != nil { logFatal(LogData{ "event": "pubsub.error.auth", "error": err.Error(), }) } ctx := cloud.NewContext(projectId, client) isSub, err := pubsub.SubExists(ctx, subName) if err != nil { logFatal(LogData{ "event": "pubsub.error.subexists", "error": err.Error(), }) } if !isSub { err = pubsub.CreateSub(ctx, subName, topicName, ackDeadline, "") if err != nil { logFatal(LogData{ "event": "pubsub.error.createsub", "error": err.Error(), }) } } go func() { var lastAckErr error var lastDecodeErr error for { msgs, err := pubsub.PullWait(ctx, subName, 20) if err != nil { logInfo(LogData{ "event": "pubsub.error.pull", "error": err.Error(), }) time.Sleep(time.Second) continue } lastAckErr = nil lastDecodeErr = nil for _, m := range msgs { jsonBytes, err := msgToLogJson(m.Data) if err != nil { lastDecodeErr = err } else { msgC <- jsonBytes } err = pubsub.Ack(ctx, subName, m.AckID) if err != nil { lastAckErr = err } } // protect against flood of logs from this application // when acks/decodes fail but adding rollup & sleep delay if lastAckErr != nil { logInfo(LogData{ "event": "pubsub.error.ack", "error": lastAckErr.Error(), }) time.Sleep(time.Second) } if lastDecodeErr != nil { logInfo(LogData{ "event": "pubsub.error.decode", "error": lastDecodeErr.Error(), }) time.Sleep(time.Second) } } }() return msgC }
func (s *pubSubServiceImpl) SubExists(sub string) (bool, error) { return pubsub.SubExists(s.ctx, sub) }