Skip to content

Commit 2b9e1f9

Browse files
pubsub: default autoCreate:true
1 parent 61ffa82 commit 2b9e1f9

File tree

6 files changed

+242
-97
lines changed

6 files changed

+242
-97
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,11 @@ var pubsub = gcloud.pubsub({
214214
keyFilename: '/path/to/keyfile.json'
215215
});
216216

217-
// Create a new topic.
218-
pubsub.createTopic('my-new-topic', function(err, topic) {});
219-
220-
// Reference an existing topic.
221-
var topic = pubsub.topic('my-existing-topic');
217+
// Reference a topic.
218+
var topic = pubsub.topic('my-topic');
222219

223220
// Publish a message to the topic.
221+
// The topic will be created if it doesn't exist.
224222
topic.publish({
225223
data: 'New message!'
226224
}, function(err) {});

lib/pubsub/index.js

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,16 @@ PubSub.prototype.getTopics = function(query, callback) {
160160
*
161161
* @example
162162
* pubsub.createTopic('my-new-topic', function(err, topic, apiResponse) {
163-
* topic.publish('New message!', function(err) {});
163+
* topic.publish({
164+
* data: 'New message!'
165+
* }, function(err) {});
164166
* });
167+
*
168+
* //-
169+
* // <strong>Note:</strong> For cases like the one above, it is simpler to use
170+
* // {module:pubsub#topic}, which will create the topic for you at the time you
171+
* // publish a message.
172+
* //-
165173
*/
166174
PubSub.prototype.createTopic = function(name, callback) {
167175
callback = callback || util.noop;
@@ -315,14 +323,40 @@ PubSub.prototype.subscription = function(name, options) {
315323
*
316324
* @param {string} name - The name of the topic.
317325
* @param {object=} options - Configuration object.
318-
* @param {boolean=} options.autoCreate - Automatically create topic if it
326+
* @param {boolean} options.autoCreate - Automatically create topic if it
319327
* doesn't exist. Note that messages published to a topic with no
320-
* subscribers will not be delivered.
328+
* subscribers will not be delivered. Default: true.
321329
* @return {module:pubsub/topic}
322330
*
323331
* @example
324-
* var topic = pubsub.topic('my-existing-topic');
325-
* var topic = pubsub.topic('topic-that-maybe-exists', { autoCreate: true });
332+
* //-
333+
* // By default, it isn't required to specify a topic that already exists. The
334+
* // first time you publish a message, the topic will be created for you.
335+
* //
336+
* // This will only cost one additional API request at the time of publishing.
337+
* // If the topic doesn't need to be created, there is no performance penalty.
338+
* //-
339+
* var topic = pubsub.topic('my-topic');
340+
*
341+
* topic.publish({
342+
* data: 'New message!'
343+
* }, function(err) {});
344+
*
345+
* //-
346+
* // If you prefer an error when trying to publish to a topic that doesn't
347+
* // exist, set `autoCreate` to `false`.
348+
* //-
349+
* var nonExistentTopic = pubsub.topic('my-non-existent-topic', {
350+
* autoCreate: false
351+
* });
352+
*
353+
* nonExistentTopic.publish({
354+
* data: 'New message!'
355+
* }, function(err) {
356+
* if (err) {
357+
* // API error from trying to publish a message to a non-existent topic.
358+
* }
359+
* });
326360
*/
327361
PubSub.prototype.topic = function(name, options) {
328362
if (!name) {

lib/pubsub/subscription.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,23 @@ var util = require('../common/util.js');
7676
* //-
7777
* // From {@linkcode module:pubsub/topic#getSubscriptions}:
7878
* //-
79-
* var topic = pubsub.topic('my-existing-topic');
79+
* var topic = pubsub.topic('my-topic');
8080
* topic.getSubscriptions(function(err, subscriptions) {
8181
* // `subscriptions` is an array of Subscription objects.
8282
* });
8383
*
8484
* //-
8585
* // From {@linkcode module:pubsub/topic#subscribe}:
8686
* //-
87-
* var topic = pubsub.topic('my-existing-topic');
87+
* var topic = pubsub.topic('my-topic');
8888
* topic.subscribe('new-subscription', function(err, subscription) {
8989
* // `subscription` is a Subscription object.
9090
* });
9191
*
9292
* //-
9393
* // From {@linkcode module:pubsub/topic#subscription}:
9494
* //-
95-
* var topic = pubsub.topic('my-existing-topic');
95+
* var topic = pubsub.topic('my-topic');
9696
* var subscription = topic.subscription('my-existing-subscription');
9797
* // `subscription` is a Subscription object.
9898
*

lib/pubsub/topic.js

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ var util = require('../common/util.js');
3030
*
3131
* @param {module:pubsub} pubsub - PubSub object.
3232
* @param {object} options - Configuration object.
33+
* @param {boolean=} options.autoCreate - Automatically create topic if it
34+
* doesn't exist. Note that messages published to a topic with no
35+
* subscribers will not be delivered. Default: true.
3336
* @param {string} options.name - Name of the topic.
3437
*/
3538
/**
36-
* A Topic object allows you to interact with a Google Cloud Pub/Sub topic. To
37-
* get this object, you will use the methods on the `pubsub` object,
38-
* {@linkcode module:pubsub#topic} and {@linkcode module:pubsub#createTopic}.
39+
* A Topic object allows you to interact with a Google Cloud Pub/Sub topic.
3940
*
4041
* @constructor
4142
* @alias module:pubsub/topic
@@ -45,25 +46,15 @@ var util = require('../common/util.js');
4546
* projectId: 'grape-spaceship-123'
4647
* });
4748
*
48-
* // From pubsub.topic:
49-
* var topic = pubsub.topic('my-existing-topic');
50-
*
51-
* // From pubsub.createTopic:
52-
* pubsub.createTopic('my-new-topic', function(err, topic) {
53-
* // `topic` is a Topic object.
54-
* });
49+
* var topic = pubsub.topic('my-topic');
5550
*/
5651
function Topic(pubsub, options) {
57-
this.makeReq_ = pubsub.makeReq_.bind(pubsub);
52+
this.autoCreate = options.autoCreate !== false;
5853
this.name = Topic.formatName_(pubsub.projectId, options.name);
54+
5955
this.projectId = pubsub.projectId;
6056
this.pubsub = pubsub;
6157
this.unformattedName = options.name;
62-
63-
if (options.autoCreate) {
64-
this.origMakeReq_ = this.makeReq_;
65-
this.makeReq_ = this.autoCreateWrapper_;
66-
}
6758
}
6859

6960
/**
@@ -99,34 +90,6 @@ Topic.formatName_ = function(projectId, name) {
9990
return 'projects/' + projectId + '/topics/' + name;
10091
};
10192

102-
/**
103-
* Wrapper for makeReq_ that automatically attempts to create a topic if it does
104-
* not yet exist.
105-
*
106-
* @private
107-
*/
108-
Topic.prototype.autoCreateWrapper_ = function(method, path, q, body, callback) {
109-
var self = this;
110-
111-
function createAndRetry() {
112-
self.pubsub.createTopic(self.unformattedName, function(err) {
113-
if (err) {
114-
callback(err);
115-
return;
116-
}
117-
self.origMakeReq_(method, path, q, body, callback);
118-
});
119-
}
120-
121-
this.origMakeReq_(method, path, q, body, function(err, res) {
122-
if (err && err.code === 404 && method !== 'DELETE') {
123-
createAndRetry();
124-
} else {
125-
callback(err, res);
126-
}
127-
});
128-
};
129-
13093
/**
13194
* Publish the provided message or array of messages. On success, an array of
13295
* messageIds is returned in the response.
@@ -144,7 +107,7 @@ Topic.prototype.autoCreateWrapper_ = function(method, path, q, body, callback) {
144107
* topic.publish({
145108
* data: 'Hello, world!'
146109
* }, function(err, messageIds, apiResponse) {});
147-
*
110+
*
148111
* //-
149112
* // The data property can be a JSON object as well.
150113
* //-
@@ -159,7 +122,7 @@ Topic.prototype.autoCreateWrapper_ = function(method, path, q, body, callback) {
159122
* hello: 'world'
160123
* }
161124
* };
162-
*
125+
*
163126
* topic.publish(registerMessage, function(err, messageIds, apiResponse) {});
164127
*
165128
* //-
@@ -321,4 +284,40 @@ Topic.prototype.subscription = function(name, options) {
321284
return this.pubsub.subscription(name, options);
322285
};
323286

287+
/**
288+
* Make an API request using the parent PubSub object's `makeReq_`. If the Topic
289+
* instance has `autoCreate: true` set, this method will first try to create the
290+
* Topic in the event of a 404.
291+
*
292+
* @private
293+
*
294+
* @param {string} method - Action.
295+
* @param {string} path - Request path.
296+
* @param {*} query - Request query object.
297+
* @param {*} body - Request body contents.
298+
* @param {function} callback - The callback function.
299+
*/
300+
Topic.prototype.makeReq_ = function(method, path, query, body, callback) {
301+
var self = this;
302+
303+
function createTopicThenRetryRequest() {
304+
self.pubsub.createTopic(self.unformattedName, function(err, topic, res) {
305+
if (err) {
306+
callback(err, null, res);
307+
return;
308+
}
309+
310+
self.pubsub.makeReq_(method, path, query, body, callback);
311+
});
312+
}
313+
314+
this.pubsub.makeReq_(method, path, query, body, function(err, res) {
315+
if (self.autoCreate && err && err.code === 404 && method !== 'DELETE') {
316+
createTopicThenRetryRequest();
317+
} else {
318+
callback(err, res);
319+
}
320+
});
321+
};
322+
324323
module.exports = Topic;

system-test/pubsub.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ describe('pubsub', function() {
6363
});
6464

6565
describe('Topic', function() {
66-
6766
it('should be listed', function(done) {
6867
pubsub.getTopics(function(err, topics) {
6968
assert.ifError(err);
@@ -98,6 +97,25 @@ describe('pubsub', function() {
9897
});
9998
});
10099

100+
it('should lazily create by default', function(done) {
101+
var newTopicName = generateTopicName();
102+
var newTopic = pubsub.topic(newTopicName);
103+
104+
newTopic.publish({ data: 'message from me' }, function(err) {
105+
assert.ifError(err);
106+
107+
pubsub.getTopics(function(err, topics) {
108+
assert.ifError(err);
109+
110+
assert(topics.some(function(topic) {
111+
return topic.name.indexOf(newTopicName) > -1;
112+
}));
113+
114+
newTopic.delete(done);
115+
});
116+
});
117+
});
118+
101119
it('should publish a message', function(done) {
102120
var topic = pubsub.topic(TOPIC_NAMES[0]);
103121
topic.publish({ data: 'message from me' }, function(err, messageIds) {

0 commit comments

Comments
 (0)