Pub/Sub: Can't seem to get local emulator working with Node.js

Viewed 1722

I read in the following link, that I must start a pub/sub instance locally with the command: gcloud beta emulators pubsub env-init && gcloud beta emulators pubsub start:

https://cloud.google.com/pubsub/docs/emulator

This is fine, and the instance is up and running.

What I don't understand is when I start up node.js application it doesn't seem to interact with this instance.

I'm able to get the following working without the pub/sub emulator instance running locally:

  const subscription = pubsub.subscription(topicName);
  // Register a listener for `message` events.
  subscription.on('message', (message) => {
    console.log('->', message);
  });
  const results = await pubsub.topic('my-new-topic').publish('my message');
  const messageIds = results[0];
  console.log(`Message ${messageIds[0]} published.`);

I thought that it might go up against my project on the cloud however since I also ran the gcloud beta emulators pubsub env-init that it should use the local one. As said it seems to be working even though I don't have it started.

I wonder if I've misunderstood the how it works in local development. The following is what I've read.

  1. Create Project
  2. Enable Pub/Sub
  3. Download SDK install and initialize
  4. Install NPM library in Node.js application
  5. Set environmental variable via gcloud beta emulators pubsub env-init
  6. Start the local pub/sub emulator via gcloud beta emulators pubsub start
  7. Start Node.js application, watch it connect, get topic, publish, subscribe etc.

I wish google would just do a simple bullet list sometimes and make the deep reading optional.

Here is how it looks:

karl@karl-Dell-Precision-M3800:~/dev/node(dev/feat/setup)$ ps aux | grep pubsub
karl     19538  0.0  0.0   4512   848 pts/1    S+   14:52   0:00 /bin/sh /opt/google-cloud-sdk/bin/gcloud beta emulators pubsub start --verbosity=info
karl     19545  1.2  0.2  88796 32760 pts/1    S+   14:52   0:00 python2 -S /opt/google-cloud-sdk/lib/gcloud.py beta emulators pubsub start --verbosity=info
karl     19570  4.0  0.3 6982280 64888 pts/1   Sl+  14:52   0:00 /usr/lib/jvm/java-8-oracle//bin/java -jar /opt/google-cloud-sdk/platform/pubsub-emulator/lib/cloud-pubsub-emulator-0.1-SNAPSHOT-all.jar --host=localhost --port=8085
1 Answers

In general, you need to run

$ gcloud beta emulators pubsub start
$ $(gcloud beta emulators pubsub env-init)

before you start your Node application.

The env-init command will export an environment variable (PUBSUB_EMULATOR_HOST) that will be automatically picked up by the Nodejs PubSub client library in your Node application, causing it to connect to the emulator rather than the global Google Cloud Pubsub.

To verify your application sees this variable, you could add something like:

assert(process.env.PUBSUB_EMULATOR_HOST);

at the point where you are creating your PubSub instance.

Note that:

  • pubsub start should happen before env-init, because the latter depends on the dynamic port chosen by the former
  • The environment variable defined by env-init needs to be injected into the local terminal so that it can be seen by your Nodejs application. That's why we need to wrap it in the bash $() syntax.

(and unfortunately it seems that testing Nodejs push endpoints with the PubSub emulator via functions-framework is broken, so depending on how you're interacting with PubSub you may have to adjust your strategy for local testing. Other topic operations seem to work as expected.)

Related