Skip to content

Automatically create topic / subscription if not found. #445

Description

@theacodes

Presently I have some code to publish to a particular topic, creating it if necessary:

function publish(message, cb){
  topic.publish(message, function(err){
    if(err && err.code == 404){
      logging.info("Creating pub/sub topic.");
      pubsub.createTopic(topicName, function(err, _){
        if(err) return cb(err);
        publish(message, cb);
      });
    } else {
      cb(err);
    }
  });
}

And similar code to listen for messages to a topic. It goes the other way around - trying to create one at first then re-using if it's already there.

function subscribe(cb){
  topic.subscribe(subscriptionName, function(err, subscription){
    if(!err) return wireSubscription(subscription);
    if(err && err.code == 409) return wireSubscription(topic.subscription(subscriptionName));
    throw err;
  });
  ...
}

According to this comment, it seems that the intended usage is to create the topic and subscription outside of the application content and never touch them afterwards. It's not clear in the documentation that this is expected.

I think it would be great to either:

  1. Consolidate subscribe/subscription createTopic/topic into combined create/reuse functions (e.g. .topic() .subscription()). There can be an optional argument for erring instead of re-using. This hides all of this somewhat ugly logic from users that do want this use-case.
  2. Explicitly document that topics and subscriptions should be created beforehand.

I would personally prefer the former as it removes the need to write a "bootstrapping" script and simplifies the user-facing API.

Activity

  1. stephenplusplus commented on Mar 13, 2015

    @stephenplusplus
    Contributor

    Do you mean a Topic and Subscription object should create itself if necessary after you attempt to use it? I'm ok with this idea, but what's the trouble with manually creating the topic/sub before using it?

  2. theacodes commented on Mar 13, 2015

    @theacodes
    Author

    Yes. The trouble with manually creating it before use leads to having to write unnecessary code to handle creating it if necessary- unless you meant creating it with a bootstrap script beforehand outside of the application context. In that case, it's just inconvenient for no real benefit. I could see myself forgetting to create new subscriptions/topics while iterating new features.

  3. ryanseys commented on Mar 14, 2015

    @ryanseys
    Contributor

    The approach we have taken for every object in this library is that you can create one or reference an existing one. If we changed this, it would need to be changed everywhere and would require two API requests rather than one, causing increased delays for responses.

    Now actually, the latest pubsub v1beta2 (in this library master branch) call to create a topic/subscription is a PUT call meaning its idempotent (basically no matter how many times you call it, it won't cause more effects than if you call it just once). This means that you can effectively "create or get" by always creating the topic regardless of whether it exists or not. If we know we don't need to create it, it would be silly to try to every time we want to do something with it, this would multiply every request time by a factor of two and provide less stability overall.

    Hope this makes sense. Let me know if there's a smart compromise that could be made here.

  4. theacodes commented on Mar 18, 2015

    @theacodes
    Author

    Hmm. I definitely don't want to make a recommendation that would go against the grain of the library as a whole.

    Instead of trying to create every time, couldn't the "use existing" method create if the response is a 404? That should only add 2 additional RPCs (create, then re-submit whatever request originally gave the 404) and only once. Similar to the publish example in my first comment. This wouldn't change the surface of the API but could really help the use case I'm designing for. We could even choose to have it explicit:

    var topic = pubsub.topic('my-topic', {autoCreate: true});
    topic.publish(message);  // will catch 404, create topic, and then publish the message.
    
    var topic2 = pubsub.topic('my-topic-2');
    topic2.publish(message); // will behave as today.
  5. ryanseys commented on Mar 18, 2015

    @ryanseys
    Contributor

    I like this idea.

  6. stephenplusplus commented on Mar 18, 2015

    @stephenplusplus
    Contributor

    There might be some useful information to abstract from this pr when I had basically this exact behavior! #107

  7. theacodes commented on Mar 18, 2015

    @theacodes
    Author

    Interesting conversation there, and @rakyll seems to be pretty hardline on avoiding "magic". Two thoughts:

    1. I agree with not having methods that will potentially delete and recreate resources.
    2. I think the explicit form {autoCreate: true} avoids "magic".
  8. added this to the Pub/Sub Beta milestone on Mar 23, 2015
  9. theacodes commented on Mar 23, 2015

    @theacodes
    Author

    Here's another example to further illustrate the need for this. I followed the "encouraged" flow by writing a one-off script to create pub/sub topics and subscriptions ahead of time:

    if (!module.parent) {
      console.log(
        "Creating pub/sub topics and subscriptions on project %s.",
        config.gcloud.projectId);
    
      pubsub.createTopic(topicName, function(err, topic){
        if(err && err.code == 409 && err.errors && err.errors[0].reason == "alreadyExists") {
          console.log("Topic %s already exists.", topicName);
          topic = pubsub.topic(topicName);
        } else if(err || !topic) {
          throw err;
        } else {
          console.log('Created topic %s', topicName);
        }
    
        topic.subscribe(subscriptionName, function(err, subscription){
          if(err && err.code == 409 && err.errors && err.errors[0].reason == "alreadyExists") {
            console.log("Subscription %s already exists.", subscriptionName);
          } else if(err) {
            throw err;
          } else{
            console.log('Created subscription %s', subscriptionName);
          }
          console.log('Done');
          process.exit();
        });
      });
    }

    Definitely seems a bit unwieldy for just one topic & subscription. Of course, if there were a gcloud pubsub topics create ... command this could be workable, but as it stands I think this is poor developer experience.

  10. tmatsuo commented on Mar 25, 2015

    @tmatsuo
    Contributor

    I have a little concern.

    With the current version of Cloud Pub/Sub, a topic without any subscriptions will throw away your messages until the first subscription will be created and attached to it.

    So if we auto create on publish, then the messages subsequently published to this topic will go /dev/null, the situation will continue until you create the first subscription.

  11. tmatsuo commented on Mar 25, 2015

    @tmatsuo
    Contributor

    Also, hopefully we will start providing gcloud pubsub subcommand, as well as Developer Console UI, so the first time burden will be mitigated.

  12. theacodes commented on Mar 25, 2015

    @theacodes
    Author

    I personally think it's a better to document that a topic with no subscriptions doesn't deliver messages and add the autoCreate option than to keep the developer experience we have now. The experience we have now is quite painful and frustrating.

    Do we have any idea when gcloud pubsub will land? I think we should weigh the effort of adding this vs the time until gcloud pubsub is available.

  13. ryanseys commented on Mar 25, 2015

    @ryanseys
    Contributor

    We welcome contributions too so feel free to mock something up for this. I'm a fan of the autoCreate flag to reduce magic. We have no currently planned release date for the next version unfortunately. We're awaiting library reviews from various teams at Google. I hope to have an update for you soon!

  14. tmatsuo commented on Mar 25, 2015

    @tmatsuo
    Contributor

    Do we have any idea when gcloud pubsub will land?

    Not so far away. For a time being, you may find it useful to use my command line tool:
    https://github.com/GoogleCloudPlatform/cloud-pubsub-samples-python
    (cmdline-pull)

    Although it still doesn't support push subscription, it can be used for other operations (create, list, publish, pull, etc).

  15. 38 remaining items

  16. added a commit that references this issue on Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

🚨This issue needs some love.api: pubsubIssues related to the Pub/Sub API.triage meI really want to be triaged.

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions