blob: 38a49edf7d59464bc0e46a5f48d91294751319a0 [file] [log] [blame]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pubsub
import (
"fmt"
"golang.org/x/net/context"
)
const MaxPublishBatchSize = 1000
// Topic is a reference to a PubSub topic.
type Topic struct {
s service
// The fully qualified identifier for the topic, in the format "projects/<projid>/topics/<name>"
name string
}
// NewTopic creates a new topic.
// The specified topic name must start with a letter, and contain only letters
// ([A-Za-z]), numbers ([0-9]), dashes (-), underscores (_), periods (.),
// tildes (~), plus (+) or percent signs (%). It must be between 3 and 255
// characters in length, and must not start with "goog".
// If the topic already exists an error will be returned.
func (c *Client) NewTopic(ctx context.Context, name string) (*Topic, error) {
t := c.Topic(name)
err := c.s.createTopic(ctx, t.Name())
return t, err
}
// Topic creates a reference to a topic.
func (c *Client) Topic(name string) *Topic {
return &Topic{s: c.s, name: fmt.Sprintf("projects/%s/topics/%s", c.projectID, name)}
}
// Topics returns an iterator which returns all of the topics for the client's project.
func (c *Client) Topics(ctx context.Context) *TopicIterator {
return &TopicIterator{
s: c.s,
stringsIterator: stringsIterator{
ctx: ctx,
fetch: func(ctx context.Context, tok string) (*stringsPage, error) {
return c.s.listProjectTopics(ctx, c.fullyQualifiedProjectName(), tok)
},
},
}
}
// TopicIterator is an iterator that returns a series of topics.
type TopicIterator struct {
s service
stringsIterator
}
// Next returns the next topic. If there are no more topics, Done will be returned.
func (tps *TopicIterator) Next() (*Topic, error) {
topicName, err := tps.stringsIterator.Next()
if err != nil {
return nil, err
}
return &Topic{s: tps.s, name: topicName}, nil
}
// Name returns the globally unique name for the topic.
func (t *Topic) Name() string {
return t.name
}
// Delete deletes the topic.
func (t *Topic) Delete(ctx context.Context) error {
return t.s.deleteTopic(ctx, t.name)
}
// Exists reports whether the topic exists on the server.
func (t *Topic) Exists(ctx context.Context) (bool, error) {
if t.name == "_deleted-topic_" {
return false, nil
}
return t.s.topicExists(ctx, t.name)
}
// Subscriptions returns an iterator which returns the subscriptions for this topic.
func (t *Topic) Subscriptions(ctx context.Context) *SubscriptionIterator {
// NOTE: zero or more Subscriptions that are ultimately returned by this
// Subscriptions iterator may belong to a different project to t.
return &SubscriptionIterator{
s: t.s,
stringsIterator: stringsIterator{
ctx: ctx,
fetch: func(ctx context.Context, tok string) (*stringsPage, error) {
return t.s.listTopicSubscriptions(ctx, t.name, tok)
},
},
}
}
// Publish publishes the supplied Messages to the topic.
// If successful, the server-assigned message IDs are returned in the same order as the supplied Messages.
// At most MaxPublishBatchSize messages may be supplied.
func (t *Topic) Publish(ctx context.Context, msgs ...*Message) ([]string, error) {
if len(msgs) == 0 {
return nil, nil
}
if len(msgs) > MaxPublishBatchSize {
return nil, fmt.Errorf("pubsub: got %d messages, but maximum batch size is %d", len(msgs), MaxPublishBatchSize)
}
return t.s.publishMessages(ctx, t.name, msgs)
}